如何在本机桌面Windows应用程序中使用Direct2D呈现子窗口?

时间:2015-10-01 09:15:24

标签: c++ transparency direct2d

我有一个桌面应用程序,其中所有窗口(HWND)使用Direct2D 1.1自行渲染。我的问题是如何正确地做到这一点

每个窗口是否都有自己的Direct2D设备上下文派生自一个Direct2D设备?在这种情况下,我无法在没有额外技巧的情况下在子窗口上呈现透明内容(我必须在父窗口的上下文中更改目标,将父窗口呈现为Direct2D位图,然后在子目标上绘制此位图)。

可能最好有一个Direct2D设备上下文,所有窗口都自动呈现?我相信DirectComposition以类似的方式工作。不幸的是,我无法使用它,因为我的目标是Windows 7。

1 个答案:

答案 0 :(得分:6)

您问的答案将是非常特定于应用程序的问题。我建议避免尝试让HWND在彼此之间进行透明渲染的整个问题,特别是如果你将Direct2D投入混合中。在那个方向上有太多的痛苦。您支持的每个Windows版本都会有不同的错误,您将不断碰到并掌握解决方法。

例证:对于Paint.NET的v4.0版本,我将所有文本呈现转换为DirectWrite,几乎所有UI控件都使用Direct2D。窗口顶部的图像缩略图控件(MDI选择器)正在使用Direct2D进行渲染,但它也必须在其背后构成。而且它必须在Win7上玩好玻璃(它看起来很棒!)。这个代码很糟糕,很棘手,几乎无法维护,而且似乎在每个Windows版本上遇到不同的渲染错误:7,7 SP1,8,8.1和10都表现得略有不同!测试也很烦人;这是我必须为我支持的每个Windows版本(除了安装程序和更新程序)设置和维护VM的唯一原因。 Windows 7工作正常,然后7 SP1添加了一个错误,需要调整我填充alpha通道的方式。当你调整窗口大小时Windows 8闪烁,除非我做了某个黑客,但8.1工作正常。 10如果使用软件渲染,则会有自己的闪烁错误。远程桌面以自己的方式打破事物。然后你还要担心高对比度,以及如果你支持Windows 7,是否启用/禁用DWM。它们的行为都不一样,真的很痛苦。

反正。你真正需要的是一个像WPF或XAML这样的UI系统,它不使用顶级HWND容器以外的任何东西。那时你就是自定义渲染所有内容并进行自己的命中测试和输入路由(以及可访问性和各种其他事情),所以这不是一项小任务。

关于“如何更正确地做”设备和设备上下文的问题和基数:您是否考虑过仅使用ID2D1Factory::CreateHWNDRenderTargetID2D1Factory::CreateDCRenderTarget?他们返回ID2D1RenderTarget,但您可以致电QueryInterface将其转发给ID2D1DeviceContext(这些事实在文档中缺失,但也明显是故意的)。这应该可以简化Direct2D和HWND的使用。这就是我在Paint.NET中所做的:我仍然为每个控件使用HWND,但每个控件都使用自己的HWND或DC渲染目标。如果您愿意使用Reflector或ILSpy,请检查Paint.NET DLL中的Direct2DControlDirect2DControlHandler

另外,请注意使用多个硬件加速的HWND渲染目标。您不希望进入一个奇怪的区域,每个基于Direct2D的UI控件都在等待VSync。在创建HWND渲染目标时使用D2D1_PRESENT_OPTIONS_IMMEDIATELY应该会有所帮助。 DWM已经处理过VSync,所以你应该告诉Direct2D忽略它,除非你用动画和定时器做一些相当具体的事情。