我应该如何处理Direct2D应用程序中的更新rect / region / area?

时间:2015-10-14 15:13:01

标签: winapi direct2d

在使用GDI进行图形处理的传统Windows程序中,您只需要担心只绘制需要重绘的窗口区域;这是“更新矩形”,可以通过PAINTSTRUCT.rcPaint或致电GetUpdateRect()来访问。 (这也可以通过其他方式作为HRGN使用。)

我是否需要使用Direct2D做同样的事情? MSDN上的所有示例都只是不加选择地绘制整个客户区域,并且在线搜索没有显示任何其他内容。

或者换句话说,如果我只在更新rect中绘制,例如手动或使用PushAxisAlignedClip()PushLayer(),那么更新rect之外的部分会发生什么不好吗?

此外,ID2D1HwndRenderTarget::Resize()的文档说

  

调用此方法后,即使在创建渲染目标时指定了D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS选项,也不会定义渲染目标的后缓冲区的内容。

这是否意味着调整大小(例如来自this picturethis page显示)导致的更新区域无效,我应该重绘整个窗口(例如,通过调用{{1调整大小?

感谢。

2 个答案:

答案 0 :(得分:1)

是。将PushAxisAlignedClipD2D1_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;
 }