c# - ¿Cómo dibujo contenido transparente de DirectX en una ventana transparente?
windows direct3d (4)
Encontré una solución que funciona en Vista, a partir del enlace proporcionado por OregonGhost. Este es el proceso básico, en sintaxis C #. Este código pertenece a una clase que hereda 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 vidrioso parcialmente transparente. Establezca FormBorderStyle en "none" y será 100% transparente, con solo su contenido flotando por encima de todo.
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 #.
Puede usar DirectComposition, LayeredWindows, DesktopWindowManager o WPF. Todos los métodos vienen con sus ventajas y desventajas:
-DirectComposition es el más eficiente, pero necesita Windows 8 y está limitado a 60Hz.
-LayeredWindows son difíciles de trabajar con D3D a través de Direct2D-interoperabilidad 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. Es posible interoperar con versiones DX más altas a través de DXGI, también se puede usar MSAA cuando el MSAA-Rendertarget se resuelve en la superficie no MSAA nativa.
-DesktopWindowManager es ideal para el alto rendimiento disponible desde Windows Vista, pero las versiones de DirectX parecen estar limitadas por la versión que usa DWM (aún DX9 en Vista). Las soluciones para versiones DX más altas deberían ser posibles a través de DXGI cuando esté disponible
Si no necesita una aplha por píxel, también puede usar el valor de opacidad de una forma semitransparente. He podido utilizar todas las técnicas descritas con C # y SharpDX, pero en el caso de DirectComposition y LayeredWindows se necesitaba un pequeño C ++ - Wrappercode. 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. Con el DWM, parece ser bastante fácil sin embargo.
Si la velocidad no es un problema, puede salirse con la renderización a una superficie y luego copiar la imagen renderizada en una ventana en capas. Sin embargo, no esperes que sea rápido.
WPF es también otra opción.
Desarrollado por Microsoft, Windows Presentation Foundation (o WPF) es un subsistema gráfico de software de computadora para renderizar interfaces de usuario en aplicaciones basadas en Windows.