在使用GDI进行图形处理的传统Windows程序中,您只需要担心只绘制需要重绘的窗口区域;这是“更新矩形”,可以通过PAINTSTRUCT.rcPaint
或致电GetUpdateRect()
来访问。 (这也可以通过其他方式作为HRGN
使用。)
我是否需要使用Direct2D做同样的事情? MSDN上的所有示例都只是不加选择地绘制整个客户区域,并且在线搜索没有显示任何其他内容。
或者换句话说,如果我只在更新rect中绘制,例如手动或使用PushAxisAlignedClip()
或PushLayer()
,那么更新rect之外的部分会发生什么不好吗?
此外,ID2D1HwndRenderTarget::Resize()
的文档说
调用此方法后,即使在创建渲染目标时指定了D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS选项,也不会定义渲染目标的后缓冲区的内容。
这是否意味着调整大小(例如来自this picture的this page显示)导致的更新区域无效,我应该重绘整个窗口(例如,通过调用{{1调整大小?
感谢。
答案 0 :(得分:1)
是。将PushAxisAlignedClip
与D2D1_ANTIALIAS_MODE_ALIASED
一起使用。
调整窗口大小时调用ID2D1HwndRenderTarget::Resize
。请注意它返回的HRESULT。它可以返回D2DERR_RECREATE_TARGET
,但您可能不知道它也可以返回D2DERR_DISPLAY_STATE_INVALID
(也可以由EndDraw
,btw返回)。是的,之后请致电InvalidateRect(NULL)
。
我还建议使用D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS
,否则你会在某些愚蠢的驱动程序/硬件配置和其他事件中遇到令人讨厌的错误。不要问我为什么 - 如果没有这个,它就不会表现得很好。您将收到错误报告,表明您的整个渲染区域都充满了黑色。花了我几个月的时间才弄清楚我所要做的就是使用那面旗帜。我无法在本地重新解决问题。
答案 1 :(得分:0)
不。与gdi一样,您必须做与正常情况相同的事情。不必使用HBITMAP后备缓冲区,而必须使用d2d位图。在wm_size中,您需要调整大小并重绘d2d位图,而在wm_paint中,您必须使用render drawbitmap方法而不是bitblt hbitmap。并仅渲染paintstruct rect成员的一部分(希望对您有帮助):
全球成员或班级成员:
ID2D1Factory* g_pD2DFactory = NULL;
ID2D1HwndRenderTarget* g_pRenderTarget = NULL;
ID2D1SolidColorBrush* g_pBlackBrush = NULL;
ID2D1SolidColorBrush* g_pWhiteBrush = NULL;
ID2D1BitmapRenderTarget* g_bitmapRenderTarget = NULL; //for d2d bitmap
全局或类静态wndproc:
case WM_CREATE: {
if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &g_pD2DFactory))) {
throw;
}
LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
HRESULT hr = g_pD2DFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(hWnd, D2D1::SizeU(lpcs->cx, lpcs->cy)),
&g_pRenderTarget
);
if (FAILED(hr)) {
throw;
}
if (FAILED(g_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &g_pBlackBrush))) {
throw;
}
if (FAILED(g_pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &g_pWhiteBrush))) {
throw;
}
break;
}
case WM_SIZE: {
if(FAILED(g_pRenderTarget->Resize(D2D1::SizeU(LOWORD(lParam), HIWORD(lParam))))) {
throw;
}
D2D_SAFE_RELEASE(g_bitmapRenderTarget)
g_pRenderTarget->CreateCompatibleRenderTarget(&g_bitmapRenderTarget);
g_bitmapRenderTarget->BeginDraw();
g_bitmapRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::AliceBlue));
g_bitmapRenderTarget->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(100,100), 50,50), g_pBlackBrush);
g_bitmapRenderTarget->EndDraw();
break;
}
case WM_PAINT: {
HDC hDc;
PAINTSTRUCT ps;
LPCRECT lpRect;
ID2D1Bitmap* bitmap;
D2D1_RECT_F d2d1Rect;
hDc = BeginPaint(hWnd, &ps);
lpRect = &ps.rcPaint;
d2d1Rect = D2D1::RectF(lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
g_bitmapRenderTarget->GetBitmap(&bitmap);
g_pRenderTarget->BeginDraw();
g_pRenderTarget->DrawBitmap(
bitmap, d2d1Rect, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE::D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
d2d1Rect
);
g_pRenderTarget->EndDraw();
EndPaint(hWnd, &ps);
return 0;
}