如何在Direct2D中清除右侧圆形区域以实现桌面穿透显示
问题场景
现有一个支持透明效果的分层窗口,使用Direct2D绘制内容:
- 窗口背景为半透明蓝色(alpha=0.5)
- 左侧是不透明红色圆形
- 右侧是半透明绿色圆形,当前透过绿色圆形能看到左侧红色圆形及窗口蓝色背景
需求:绘制右侧绿色圆形前,先清除该区域的窗口内容,使右侧圆形位置能直接透出桌面,最终透过半透明绿色圆形看到的是桌面而非窗口内的其他内容。
原始代码
// 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);
原始效果

解决方案
核心思路
要让窗口局部透出桌面,需将该区域的窗口像素设置为完全透明(alpha=0),结合Direct2D的混合模式可实现这一效果:
- 使用
D2D1_COMPOSITE_MODE_DEST_OUT混合模式,在目标区域绘制不透明内容,会将该区域的窗口像素alpha置为0,形成“透明洞”透出桌面。 - 恢复默认混合模式后,再绘制半透明绿色圆形,此时绿色圆形会叠加在桌面内容之上。
修改后的代码
// ID2D1DCRenderTarget* pDCRT; // ID2D1SolidColorBrush* pBrush; // 需提前实现SafeRelease宏:#define SafeRelease(p) { if(p) { (p)->Release(); (p)=nullptr; } } 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); SafeRelease(&pBrush); // 关键:清除右侧区域,透出桌面 pDCRT->CreateSolidColorBrush(D2D1::ColorF(1, 1, 1, 1), &pBrush); // 设置混合模式为DEST_OUT,将目标区域像素置为完全透明 pDCRT->SetCompositeMode(D2D1_COMPOSITE_MODE_DEST_OUT); pDCRT->FillEllipse(pe2, pBrush); // 恢复默认混合模式,避免影响后续绘制 pDCRT->SetCompositeMode(D2D1_COMPOSITE_MODE_SRC_OVER); SafeRelease(&pBrush); // 绘制右侧半透明绿色圆形(此时叠加在桌面之上) pDCRT->CreateSolidColorBrush(D2D1::ColorF(0, 1, 0, 0.5f), &pBrush); pDCRT->FillEllipse(pe2, pBrush); SafeRelease(&pBrush);
注意事项
- 窗口必须是分层窗口:创建窗口时添加
WS_EX_LAYERED扩展样式,并通过SetLayeredWindowAttributes或UpdateLayeredWindow启用透明,这是透出桌面的基础条件。 - 及时释放Direct2D资源:每次创建画刷后要调用
Release()避免内存泄漏,示例中用SafeRelease宏简化操作。
内容的提问来源于stack exchange,提问作者Klein Moretti
相关产品推荐
相关产品推荐

