如何清除Direct2D渲染目标以使其完全透明

Sau*_*aul 7 c c++ transparency hwnd direct2d

我试图在一个看不见的HWND上绘制半透明的矩形.但是,使用ID2D1HwndRenderTarget :: Clear清除窗口只会使整个窗口变黑,所以当我在顶部绘制矩形时,它们看起来是半黑色的.

如果我没有Clear()并且没有绘制,那么窗口是不可见的,因为它应该是.Clear()是罪魁祸首; 但是,如果我不使用它,那么绘画就会非常糟糕.

这是我在WindowProc中使用的代码:

case WM_PAINT:
    // Begin drawing
    pRenderTarget->BeginDraw();
    pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());

    // Clear the window
    pRenderTarget->Clear();

    // Paint the panel and its children
    D2DSurface()->StartPainting();
    {
        D2DSurface()->PaintTraverse(panel);
    }
    D2DSurface()->FinishPainting();

    // Finish drawing
    HRESULT hr = plat->pRenderTarget->EndDraw();
Run Code Online (Sandbox Code Playgroud)

提前致谢!

小智 5

透明度是个问题。唯一支持每像素透明度的窗口是 WS_EX_LAYERED 窗口。这些窗口是为拖放图标等用途而设计的,这会导致其他用途出现问题。

将 D2D 与 WS_EX_LAYERED 窗口一起使用需要您使用 DXGI 渲染目标。对于 EndDraw,你从渲染目标中获得一个 DC,然后将它传递到分层窗口并告诉分层窗口更新自身。(用 HWNDRenderTarget 试试这个——它可能会导致设备驱动程序崩溃)。

我怀疑您的窗口看起来是透明的,因为它根本没有在绘图。

您可能会遇到的另一个问题......如果窗口足够透明,鼠标点击将通过它到达底层窗口。

  • 也就是说,当您使用 -1 的边距将 WS_EX_COMPOSITED 与 `DwmExtendFrameIntoClientArea( mWindow, &m );` 结合使用时,您将拥有一个直接绘制到 D3D 表面的清晰窗口。与分层窗口不同,使用它时,您必须自己进行点击测试。 (3认同)

小智 5

使用ID2D1DCRenderTarget而不是ID2D1HwndRendTarget,然后在绘制开始之前绑定窗口的设备上下文 (DC)。

WS_EX_LAYERED当然,您需要为窗口设置,然后调用SetLayeredWindowAttributes设置透明颜色:

SetLayeredWindowAttributes(hWnd, RGB(0, 0, 0), 0, LWA_COLORKEY);
Run Code Online (Sandbox Code Playgroud)

截屏:


unt*_*927 1

创建 RenderTarget 时,您必须告诉 D2D 您想要以像素格式使用 alpha(在预乘模式下):

  HRESULT hr = mD2DFactory->CreateHwndRenderTarget(
    D2D1::RenderTargetProperties( D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat( DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED ) ),
    D2D1::HwndRenderTargetProperties( mWindow, size ),
    &mRenderTarget );
Run Code Online (Sandbox Code Playgroud)

此后,Clear()使用 alpha 值为零的调用就可以正常工作了。

  • 仍然不起作用,我的窗口没有背景画笔,创建窗口时我需要做任何额外的设置吗?例如,窗口样式? (3认同)
  • 它对我不起作用,我用你的方法得到了黑色背景,你能将代码粘贴到 Clear 方法吗?或者粘贴透明窗口的屏幕截图? (2认同)