透明なウィンドウに透明なDirectXコンテンツを描画するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/148275

質問

DirectXコンテンツをデスクトップや実行中の他のアプリケーションの上に浮かぶように描画したい。また、DirectXコンテンツを半透明にする必要があるため、他のこともわかります。これを行う方法はありますか?

C#でManaged DXを使用しています。

役に立ちましたか?

解決

OregonGhostが提供するリンクから、Vistaで動作するソリューションを見つけました。これは、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バージョンは、DWMが使用するバージョンによって制限されているようです(VistaではまだDX9)。より高いDXバージョンの回避策は、可能な場合はDXGIを介して可能です。

ピクセルごとのアルファが必要ない場合は、半透明フォームの不透明度値を使用することもできます。

またはウィンドウのグローバルアルファにネイティブWin32メソッドを使用します(アルファの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帰属
所属していません StackOverflow
scroll top