简体   繁体   English

如何在透明窗口中绘制透明的 DirectX 内容?

[英]How do I draw transparent DirectX content in a transparent window?

I want to draw DirectX content so that it appears to be floating over top of the desktop and any other applications that are running.我想绘制 DirectX 内容,使其看起来漂浮在桌面和正在运行的任何其他应用程序的顶部。 I also need to be able to make the directx content semi-transparent, so other things show through.我还需要能够使 Directx 内容半透明,以便其他内容显示出来。 Is there a way of doing this?有没有办法做到这一点?

I am using Managed DX with C#.我在 C# 中使用 Managed DX。

I found a solution which works on Vista, starting from the link provided by OregonGhost.我找到了一个适用于 Vista 的解决方案,从 OregonGhost 提供的链接开始。 This is the basic process, in C# syntax.这是基本过程,采用 C# 语法。 This code is in a class inheriting from Form.此代码位于从 Form 继承的类中。 It doesn't seem to work if in a UserControl:如果在 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();
}

Lastly, a Form with default setting will have a glassy looking partially transparent background.最后,具有默认设置的表单将具有玻璃般的部分透明背景。 Set the FormBorderStyle to "none" and it will be 100% transparent with only your content floating above everything.将 FormBorderStyle 设置为“none”,它将 100% 透明,只有您的内容浮动在所有内容之上。

You can either use DirectComposition, LayeredWindows, DesktopWindowManager or WPF.您可以使用 DirectComposition、LayeredWindows、DesktopWindowManager 或 WPF。 All methods come with their advantages and disadvantages:所有方法都有其优点和缺点:

-DirectComposition is the most efficient one, but needs Windows 8 and is limited to 60Hz. -DirectComposition 是最有效的一种,但需要 Windows 8 并且限于 60Hz。

-LayeredWindows are tricky to get working with D3D via Direct2D-interop using DXGI. -LayeredWindows 使用 DXGI 通过 Direct2D-interop 处理 D3D 很棘手。

-WPF is relatively easy to use via D3DImage, but is also limited to 60Hz and DX9 and no MSAA. -WPF 通过 D3DImage 使用起来相对容易,但也仅限于 60Hz 和 DX9,没有 MSAA。 Interops to higher DX-Versions via DXGI are possible, also MSAA can be used when the MSAA-Rendertarget is resolved to the native nonMSAA surface.可以通过 DXGI 与更高的 DX 版本互操作,当 MSAA-Rendertarget 解析为本地非 MSAA 表面时,也可以使用 MSAA。

-DesktopWindowManager is great for high performance available since Windows Vista, but DirectX-Versions seem to be limited by the Version the DWM uses (still DX9 on Vista). -DesktopWindowManager 非常适合自 Windows Vista 以来可用的高性能,但 DirectX-Versions 似乎受到 DWM 使用的版本的限制(在 Vista 上仍然是 DX9)。 Workarounds for higher DX-Versions should be possible via DXGI where available.如果可用,应该可以通过 DXGI 解决更高 DX 版本的变通方法。

If you don't need per pixel aplha, you can also use the opacity-value of a semi-transparent form.如果您不需要每像素 aplha,您还可以使用半透明形式的不透明度值。

Or you use the native Win32 method for the Window global alpha (Remember a alpha of 0 will not catch the mouse input):或者您使用本机 Win32 方法进行 Window 全局 alpha(记住 alpha 为 0 不会捕获鼠标输入):

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

I have been able to use all of the described techniques with C# and SharpDX, but in case of DirectComposition, LayeredWindows and native Win32 a little C++-Wrappercode was needed.我已经能够在 C# 和 SharpDX 中使用所有描述的技术,但是在 DirectComposition、LayeredWindows 和本机 Win32 的情况下,需要一点 C++-Wrappercode。 For starters I would suggest to go via WPF.对于初学者,我建议通过 WPF。

I guess that will be hard without using the Desktop Window Manager, ie if you want to support Windows XP.我想如果不使用桌面窗口管理器,即如果您想支持 Windows XP,那将很难。 With the DWM, it seems to be rather easy though.使用 DWM,这似乎相当容易

If speed is not an issue, you may get away with rendering to a surface and then copying the rendered image to a layered window.如果速度不是问题,您可以避免渲染到表面,然后将渲染的图像复制到分层窗口。 Don't expect that to be fast though.不过不要指望这会很快。

WPF is also another option. WPF也是另一种选择。

Developed by Microsoft, the Windows Presentation Foundation (or WPF) is a computer-software graphical subsystem for rendering user interfaces in Windows-based applications.由 Microsoft 开发的 Windows Presentation Foundation(或 WPF)是一个计算机软件图形子系统,用于在基于 Windows 的应用程序中呈现用户界面。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM