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

问题描述 投票:3回答:2

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

我需要对Direct2D做同样的事情吗? MSDN上的所有示例只是不加区别地绘制了整个客户区域,并且在线搜索没有发现其他任何内容。

或者换句话说,如果我仅在更新矩形内,例如手动或使用PushAxisAlignedClip()PushLayer()绘制,则更新矩形之外的零件会发生任何不良情况吗?

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

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

这是否意味着由调整大小引起的任何更新区域(例如this picture中的this page所示)都是无效的,因此我应该在调整大小时重绘整个窗口(例如,通过调用InvalidateRect(NULL))?

谢谢。

winapi direct2d
2个回答
1
投票

是。将PushAxisAlignedClipD2D1_ANTIALIAS_MODE_ALIASED一起使用。

调整窗口大小时调用ID2D1HwndRenderTarget::Resize。请注意它返回的HRESULT。它可以返回D2DERR_RECREATE_TARGET,但您可能不知道它也可以返回D2DERR_DISPLAY_STATE_INVALID(也可以由EndDraw,btw返回)。是的,此后致电InvalidateRect(NULL)

我也建议使用D2D1_PRESENT_OPTIONS_RETAIN_CONTENTS,因为否则,在某些愚蠢的驱动程序/硬件配置和其他事件中,您将遇到讨厌的bug。不要问我为什么-如果没有这个,它的表现就不好。您将收到错误报告,指出整个渲染区域都被黑色填充。我花了几个月的时间才弄清楚我要做的就是使用该标志。我无法在本地重现该问题。


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;

全局或类静态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);
© www.soinside.com 2019 - 2024. All rights reserved.