在使用GDI进行图形处理的传统Windows程序中,您不必担心仅绘制需要重绘的窗口区域;这是“更新矩形”,可以通过PAINTSTRUCT.rcPaint
或对GetUpdateRect()
的调用来访问。 (也可以通过其他方式将其作为HRGN
使用。)
我需要对Direct2D做同样的事情吗? MSDN上的所有示例只是不加区别地绘制了整个客户区域,并且在线搜索没有发现其他任何内容。
或者换句话说,如果我仅在更新矩形内,例如手动或使用PushAxisAlignedClip()
或PushLayer()
绘制,则更新矩形之外的零件会发生任何不良情况吗?
此外,ID2D1HwndRenderTarget::Resize()
的文档说
调用此方法后,即使在创建渲染目标时指定了D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS选项,也未定义渲染目标的后缓冲区的内容。
这是否意味着由调整大小引起的任何更新区域(例如this picture中的this page所示)都是无效的,因此我应该在调整大小时重绘整个窗口(例如,通过调用InvalidateRect(NULL)
)?
谢谢。
是。将PushAxisAlignedClip
与D2D1_ANTIALIAS_MODE_ALIASED
一起使用。
调整窗口大小时调用ID2D1HwndRenderTarget::Resize
。请注意它返回的HRESULT。它可以返回D2DERR_RECREATE_TARGET
,但您可能不知道它也可以返回D2DERR_DISPLAY_STATE_INVALID
(也可以由EndDraw
,btw返回)。是的,此后致电InvalidateRect(NULL)
。
我也建议使用D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS
,因为否则,在某些愚蠢的驱动程序/硬件配置和其他事件中,您将遇到讨厌的bug。不要问我为什么-如果没有这个,它的表现就不好。您将收到错误报告,指出整个渲染区域都被黑色填充。我花了几个月的时间才弄清楚我要做的就是使用该标志。我无法在本地重现该问题。
没有与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;
全局或类静态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;
}
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();
case WM_PAINT: {
HDC hDc;
PAINTSTRUCT ps;
LPCRECT lpRect;
ID2D1Bitmap* bitmap;
hDc = BeginPaint(hWnd, &ps);
lpRect = &ps.rcPaint;
g_bitmapRenderTarget->GetBitmap(&bitmap);
g_pRenderTarget->BeginDraw();
g_pRenderTarget->DrawBitmap(
bitmap,
D2D1::RectF(lpRect->left, lpRect->top, lpRect->right, lpRect->bottom),
1.0f,
D2D1_BITMAP_INTERPOLATION_MODE::D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
D2D1::RectF(lpRect->left, lpRect->top, lpRect->right, lpRect->bottom)
);
g_pRenderTarget->EndDraw();
EndPaint(hWnd, &ps);