Direct2D绘图,透明,如何使后面画的覆盖前面画的

我最近初学Direct2D。这个窗口是支持透明的,这里我画了两个实心圆,它们有重合的部分

img

    //ID2D1DCRenderTarget* pDCRT;
    //ID2D1SolidColorBrush* pBrush;

    pDCRT->Clear(D2D1::ColorF(D2D1::ColorF(0, 0, 1, 0.5f)));

    D2D1_ELLIPSE pe1 = D2D1::Ellipse(D2D1::Point2F(200, 200), 150, 150); 
    D2D1_ELLIPSE pe2 = D2D1::Ellipse(D2D1::Point2F(350, 200), 150, 150);

    pDCRT->CreateSolidColorBrush(D2D1::ColorF(1, 0, 0, 1), &pBrush);    
    pDCRT->FillEllipse(pe1, pBrush); 
     
    pDCRT->CreateSolidColorBrush(D2D1::ColorF(0, 1, 0, 0.5f), &pBrush);       
    pDCRT->FillEllipse(pe2, pBrush);  

我想让重合的部分只有右边实心圆的颜色,就是让它透明的时候忽略掉左边圆和窗口背景色直接透到桌面,请问,怎么才能实现的效果。

【以下回答由 GPT 生成】

要实现让重叠的部分只显示右边实心圆的颜色,可以通过以下步骤进行:

  1. 首先,我们需要在创建窗口时设置窗口的样式为WS_EX_LAYERED,以支持透明度。可以使用以下代码片段将窗口的样式设置为WS_EX_LAYERED
DWORD exStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
exStyle |= WS_EX_LAYERED;
SetWindowLong(hWnd, GWL_EXSTYLE, exStyle);
  1. 在绘制窗口之前,我们需要使用D2D1::RenderTargetProperties来创建一个具有透明背景的ID2D1HwndRenderTarget对象。可以使用以下代码片段:
D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties = D2D1::RenderTargetProperties(
    D2D1_RENDER_TARGET_TYPE_DEFAULT,
    D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
    0,
    0,
    D2D1_RENDER_TARGET_USAGE_NONE,
    D2D1_FEATURE_LEVEL_DEFAULT
);

HRESULT hr = pFactory->CreateHwndRenderTarget(
    renderTargetProperties,
    D2D1::HwndRenderTargetProperties(hWnd, size),
    &pRenderTarget
);
  1. 在绘制实心圆之前,我们需要设置ID2D1HwndRenderTarget的透明度模式为D2D1_ALPHA_MODE_PREMULTIPLIED。可以使用以下代码片段:
pRenderTarget->SetDpi(dpiX, dpiY);
pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
pRenderTarget->BeginDraw();
pRenderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));
pRenderTarget->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
pRenderTarget->SetPixelSnappingPolicy(D2D1_PIXEL_SNAPPING_POLICY_DIPS);
pRenderTarget->SetTags(0, 0);
pRenderTarget->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_SOURCE_OVER);
  1. 如果要让右边实心圆的颜色覆盖重叠部分,可以修改以下代码段:
pDCRT->CreateSolidColorBrush(D2D1::ColorF(1, 0, 0, 1), &pBrush);    
pDCRT->FillEllipse(pe1, pBrush); 

pDCRT->CreateSolidColorBrush(D2D1::ColorF(0, 1, 0, 1), &pBrush);       
pDCRT->FillEllipse(pe2, pBrush);

其中,右边实心圆的颜色的透明度为1,这样重叠部分就会完全覆盖左边实心圆的颜色。

完整的代码示例可以参考以下内容:

#include <Windows.h>
#include <d2d1.h>

ID2D1Factory* pFactory = nullptr;
ID2D1HwndRenderTarget* pRenderTarget = nullptr;

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
    // 创建窗口

    HWND hWnd = CreateWindowExW(
        WS_EX_LAYERED,
        L"WindowClassName",
        L"Transparent Window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        nullptr, nullptr, hInstance, nullptr
    );

    if (hWnd == nullptr)
    {
        return 0;
    }

    // 创建Direct2D工厂

    HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);

    if (FAILED(hr))
    {
        return 0;
    }

    // 设置窗口透明度样式

    DWORD exStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
    exStyle |= WS_EX_LAYERED;
    SetWindowLong(hWnd, GWL_EXSTYLE, exStyle);

    // 创建透明窗口

    RECT windowRect;
    GetWindowRect(hWnd, &windowRect);

    D2D1_SIZE_U size = D2D1::SizeU(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);

    D2D1_RENDER_TARGET_PROPERTIES renderTargetProperties = D2D1::RenderTargetProperties(
        D2D1_RENDER_TARGET_TYPE_DEFAULT,
        D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
        0,
        0,
        D2D1_RENDER_TARGET_USAGE_NONE,
        D2D1_FEATURE_LEVEL_DEFAULT
    );

    hr = pFactory->CreateHwndRenderTarget(
        renderTargetProperties,
        D2D1::HwndRenderTargetProperties(hWnd, size),
        &pRenderTarget
    );

    if (FAILED(hr))
    {
        return 0;
    }

    ShowWindow(hWnd, nCmdShow);

    // 消息循环

    MSG msg = {};
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // 释放资源

    pRenderTarget->Release();
    pFactory->Release();

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_PAINT:
    {
        if (pRenderTarget == nullptr)
        {
            break;
        }

        // 绘制透明窗口

        pRenderTarget->BeginDraw();
        pRenderTarget->Clear(D2D1::ColorF(0, 0, 0, 0));
        pRenderTarget->EndDraw();

        // 绘制实心圆

        D2D1_ELLIPSE pe1 = D2D1::Ellipse(D2D1::Point2F(200, 200), 150, 150);
        D2D1_ELLIPSE pe2 = D2D1::Ellipse(D2D1::Point2F(350, 200), 150, 150);

        ID2D1SolidColorBrush* pBrush;

        pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(1, 0, 0, 1), &pBrush);
        pRenderTarget->FillEllipse(pe1, pBrush);

        pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(0, 1, 0, 1), &pBrush);
        pRenderTarget->FillEllipse(pe2, pBrush);

        pBrush->Release();

        ValidateRect(hWnd, NULL);
    }
    return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hWnd, message, wParam, lParam);
}


【相关推荐】



如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^