我正在学习如何使用Direct 2D和DirectWrite。我写了一个示例应用程序,它使用这些库直接在主(顶级)窗口中呈现内容。它工作得很好。
现在我尝试在另一个应用程序中重写子窗口的绘画代码。原始代码使用GDI并且工作正常。但是当我将其转换为使用Direct 2D时,什么也没有出现(子窗口显示为黑色)。
我已经将绘制代码简化为简单地填充客户区。
LRESULT PlotWnd::OnPaint(UINT, WPARAM, LPARAM, BOOL &) {
ATL::CComPtr<ID2D1Factory> pD2DFactory;
HRESULT hr = ::D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);
assert(SUCCEEDED(hr));
ATL::CComPtr<ID2D1HwndRenderTarget> pRT;
RECT rc;
GetClientRect(&rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
hr = pD2DFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(/* D2D1_RENDER_TARGET_TYPE_SOFTWARE */),
D2D1::HwndRenderTargetProperties(m_hWnd, size), &pRT);
assert(SUCCEEDED(hr));
pRT->BeginDraw();
pRT->Clear(D2D1::ColorF(D2D1::ColorF::Beige));
hr = pRT->EndDraw();
assert(SUCCEEDED(hr));
ValidateRect(nullptr);
return 0;
}
所有的Direct 2D调用都成功地使用了S_OK
,所以我有点不知所措,不知道该在哪里寻找问题。在这一点上,我能看到的唯一显着差异,我的工作实验和这个程序之间的是,在这个程序中,我只在一个子窗口中使用Direct 2D。
所以我的问题是:在子窗口中使用Direct 2D时,是否有我遗漏的问题?有什么进一步调试的提示吗?
**更新:**为了避免混淆,我已经删除了静态。我完全设置并拆除了每个绘制的Direct 2D。只有一个绘制调用,具有真实的大小。
如果我切换到软件渲染(通过在渲染目标属性中使用D2D1_RENDER_TARGET_TYPE_SOFTWARE
),问题就消失了--我得到了预期的米色填充。
这让我怀疑我的显卡驱动程序已经过时了。但是我现在已经更新了我的显卡驱动程序,它仍然以同样的方式失败。还有什么会导致硬件渲染失败,而软件渲染却能正常工作?
更新2:我仍然在尝试重现这是一个小的,独立的例子。同时,我注意到,简单地启动Spy++将 * 有时 * 导致窗口实际呈现到屏幕上(一次)。
4条答案
按热度按时间p1tboqfb1#
好吧,对于初学者,你应该在应用程序启动时创建工厂,并在窗口(HWND)中创建渲染目标。这些不应该是“临时”对象,只要你的OnPaint(WM_PAINT)正在执行,它们就存在。
pdsfdshx2#
除了Rick建议将HWNDRenderTarget转换为永久对象之外,我建议调用
BeginPaint()
-EndPaint()
(或创建一个本地CPaintDC
对象,它会自动执行此操作),即使您不使用PAINTSTRUCT
。参见MainWindow::OnPaint
here。如果这没有帮助,您可以始终启用Direct2D Debug Layer以获取更多调试信息。
31moq8wy3#
除了使用软件渲染之外,我仍然没有解决方案。我相当肯定这是一个图形驱动程序错误,具体来说,是一个竞争条件。
证据:
反证:
我把这篇文章作为一个“答案”贴出来,因为其他一些人也看到了类似的症状,问我是否找到了答案。我仍然愿意阅读其他的想法,并会支持好的答案。
z31licg04#
我建议使用相同的工厂和像素格式为你的子窗口或其他[共享]资源创建渲染目标。