Pergunta

Eu quero desenhar o conteúdo DirectX para que ele parece estar flutuando por cima da área de trabalho e quaisquer outras aplicações que estão em execução. Eu também preciso ser capaz de fazer o conteúdo DirectX semi-transparente, para outras coisas mostrar completamente. Existe uma maneira de fazer isso?

Eu estou usando Managed DX com C #.

Foi útil?

Solução

Eu encontrei uma solução que funciona no Vista, a partir do link fornecido pelo OregonGhost. Este é o processo básico, na sintaxe C #. Este código está em uma classe herdar de Form. Ele não parece trabalho, se em um UserControl:

//this will allow you to import the necessary functions from the .dll
using System.Runtime.InteropServices;

//this imports the function used to extend the transparent window border.
[DllImport("dwmapi.dll")]
static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd, ref Margins pMargins);

//this is used to specify the boundaries of the transparent area
internal struct Margins {
    public int Left, Right, Top, Bottom;
}
private Margins marg;

//Do this every time the form is resized. It causes the window to be made transparent.
marg.Left = 0;
marg.Top = 0;
marg.Right = this.Width;
marg.Bottom = this.Height;
DwmExtendFrameIntoClientArea(this.Handle, ref marg);

//This initializes the DirectX device. It needs to be done once.
//The alpha channel in the backbuffer is critical.
PresentParameters presentParameters = new PresentParameters();
presentParameters.Windowed = true;
presentParameters.SwapEffect = SwapEffect.Discard;
presentParameters.BackBufferFormat = Format.A8R8G8B8;

Device device = new Device(0, DeviceType.Hardware, this.Handle,
CreateFlags.HardwareVertexProcessing, presentParameters);

//the OnPaint functions maked the background transparent by drawing black on it.
//For whatever reason this results in transparency.
protected override void OnPaint(PaintEventArgs e) {
    Graphics g = e.Graphics;

    // black brush for Alpha transparency
    SolidBrush blackBrush = new SolidBrush(Color.Black);
    g.FillRectangle(blackBrush, 0, 0, Width, Height);
    blackBrush.Dispose();

    //call your DirectX rendering function here
}

//this is the dx rendering function. The Argb clearing function is important,
//as it makes the directx background transparent.
protected void dxrendering() {
    device.Clear(ClearFlags.Target, Color.FromArgb(0, 0, 0, 0), 1.0f, 0);

    device.BeginScene();
    //draw stuff here.
    device.EndScene();
    device.Present();
}

Por fim, um formulário com configuração padrão terá um glassy olha o fundo parcialmente transparente. Defina o FormBorderStyle como "nenhum" e vai ser 100% transparente com apenas o seu conteúdo flutuando acima de tudo.

Outras dicas

Você pode usar DirectComposition, LayeredWindows, DesktopWindowManager ou WPF. Todos os métodos têm as suas vantagens e desvantagens:

-DirectComposition é o mais eficiente, mas precisa de Windows 8 e está limitada a 60 Hz.

-LayeredWindows são complicados para começar a trabalhar com D3D via Direct2D-interoperabilidade usando DXGI.

-WPF é relativamente fácil de usar via D3DImage, mas também é limitado a 60 Hz e DX9 e nenhum MSAA. Interoperabilidade para mais elevadas são possíveis DX-Versões via DXGI, também MSAA pode ser usado quando o MSAA-Rendertarget é resolvido para a superfície nonMSAA nativa.

-DesktopWindowManager é grande para o alto desempenho disponível desde o Windows Vista, mas com DirectX versões parecem ser limitado pela versão dos usos DWM (ainda DX9 no Vista). Soluções alternativas para maiores DX-Versões deve ser possível através DXGI quando disponíveis.

Se você não precisa per aplha pixel, você também pode usar a opacidade de valor de uma forma semi-transparente.

Ou você usa o método Win32 nativo para o alfa mundial Window (Lembre-se um alfa de 0 não vai pegar a entrada do mouse):

SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
COLORREF color = 0;
BYTE alpha = 128;
SetLayeredWindowAttributes(hWnd, color, alpha, LWA_ALPHA);

Eu tenho sido capaz de usar todas as técnicas descritas com C # e SharpDX, mas em caso de DirectComposition, LayeredWindows e Win32 nativo um pouco de C ++ - era necessário Wrappercode. Para começar eu sugiro ir via WPF.

Eu acho que vai ser difícil sem usar o Desktop Window Manager, ou seja, se você quiser dar suporte ao Windows XP. Com o DWM, parece ser bastante fácil embora.

Se a velocidade não é um problema, você pode ir longe com renderização para uma superfície e, em seguida, copiar a imagem renderizada para uma janela em camadas. Não espere que para ser rápido embora.

WPF também é outra opção.

Desenvolvido pela Microsoft, o Windows Presentation Foundation (ou WPF) é um subsistema gráfico-software de computador para processamento de interfaces de usuário em aplicativos baseados no Windows.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top