簡體   English   中英

如何在透明窗口中繪制透明的 DirectX 內容?

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

我想繪制 DirectX 內容,使其看起來漂浮在桌面和正在運行的任何其他應用程序的頂部。 我還需要能夠使 Directx 內容半透明,以便其他內容顯示出來。 有沒有辦法做到這一點?

我在 C# 中使用 Managed DX。

我找到了一個適用於 Vista 的解決方案,從 OregonGhost 提供的鏈接開始。 這是基本過程,采用 C# 語法。 此代碼位於從 Form 繼承的類中。 如果在 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();
}

最后,具有默認設置的表單將具有玻璃般的部分透明背景。 將 FormBorderStyle 設置為“none”,它將 100% 透明,只有您的內容浮動在所有內容之上。

您可以使用 DirectComposition、LayeredWindows、DesktopWindowManager 或 WPF。 所有方法都有其優點和缺點:

-DirectComposition 是最有效的一種,但需要 Windows 8 並且限於 60Hz。

-LayeredWindows 使用 DXGI 通過 Direct2D-interop 處理 D3D 很棘手。

-WPF 通過 D3DImage 使用起來相對容易,但也僅限於 60Hz 和 DX9,沒有 MSAA。 可以通過 DXGI 與更高的 DX 版本互操作,當 MSAA-Rendertarget 解析為本地非 MSAA 表面時,也可以使用 MSAA。

-DesktopWindowManager 非常適合自 Windows Vista 以來可用的高性能,但 DirectX-Versions 似乎受到 DWM 使用的版本的限制(在 Vista 上仍然是 DX9)。 如果可用,應該可以通過 DXGI 解決更高 DX 版本的變通方法。

如果您不需要每像素 aplha,您還可以使用半透明形式的不透明度值。

或者您使用本機 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);

我已經能夠在 C# 和 SharpDX 中使用所有描述的技術,但是在 DirectComposition、LayeredWindows 和本機 Win32 的情況下,需要一點 C++-Wrappercode。 對於初學者,我建議通過 WPF。

我想如果不使用桌面窗口管理器,即如果您想支持 Windows XP,那將很難。 使用 DWM,這似乎相當容易

如果速度不是問題,您可以避免渲染到表面,然后將渲染的圖像復制到分層窗口。 不過不要指望這會很快。

WPF也是另一種選擇。

由 Microsoft 開發的 Windows Presentation Foundation(或 WPF)是一個計算機軟件圖形子系統,用於在基於 Windows 的應用程序中呈現用戶界面。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM