Pregunta

Quiero dibujar contenido de DirectX para que parezca estar flotando sobre la parte superior del escritorio y cualquier otra aplicación que se esté ejecutando. También necesito poder hacer que el contenido de directx sea semitransparente, para que se muestren otras cosas. ¿Hay alguna forma de hacer esto?

Estoy usando Managed DX con C #.

¿Fue útil?

Solución

Encontré una solución que funciona en Vista, comenzando desde el enlace proporcionado por OregonGhost. Este es el proceso básico, en la sintaxis de C #. Este código está en una clase heredada de Form. No parece funcionar si en un 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 último, un formulario con la configuración predeterminada tendrá un fondo parcialmente transparente de aspecto vidrioso. Establezca FormBorderStyle en " ninguno " y será 100% transparente con solo su contenido flotando por encima de todo.

Otros consejos

Puede usar DirectComposition, LayeredWindows, DesktopWindowManager o WPF. Todos los métodos tienen sus ventajas y desventajas:

-DirectComposition es el más eficiente, pero necesita Windows 8 y está limitado a 60Hz.

-LayeredWindows es complicado para trabajar con D3D a través de Direct2D-interop usando DXGI.

-WPF es relativamente fácil de usar a través de D3DImage, pero también está limitado a 60Hz y DX9 y no a MSAA. La interoperabilidad con versiones DX superiores a través de DXGI es posible, también se puede usar MSAA cuando el MSAA-Rendertarget se resuelve en la superficie nativa no MSAA.

-DesktopWindowManager es excelente para el alto rendimiento disponible desde Windows Vista, pero las versiones DirectX parecen estar limitadas por la versión que utiliza DWM (todavía DX9 en Vista). Las soluciones para versiones DX superiores deberían ser posibles a través de DXGI cuando estén disponibles.

Si no necesita aplha por píxel, también puede usar el valor de opacidad de una forma semitransparente.

O utiliza el método nativo Win32 para el alfa global de Windows (recuerde que un alfa de 0 no capturará la entrada del mouse):

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

He podido usar todas las técnicas descritas con C # y SharpDX, pero en el caso de DirectComposition, LayeredWindows y Win32 nativo se necesitaba un pequeño código C ++. Para empezar, sugeriría ir a través de WPF.

Supongo que será difícil sin usar Desktop Window Manager, es decir, si desea admitir Windows XP. Sin embargo, con el DWM parece ser bastante fácil .

Si la velocidad no es un problema, puede obtener la representación en una superficie y luego copiar la imagen renderizada en una ventana con capas. Sin embargo, no esperes que sea rápido.

WPF también es otra opción.

  

Desarrollado por Microsoft, Windows Presentation Foundation (o WPF) es un subsistema gráfico de software para representar interfaces de usuario en aplicaciones basadas en Windows.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top