滚动时 MFC 中的 BitBlt 问题:未绘制新的可见区域

问题描述 投票:0回答:1

我正在致力于在利用

CScrollView
的 MFC 项目中使用内存 DC 实现双缓冲。我的自定义视图类源自
CScrollView

但是,向下滚动时遇到一个问题:新可见的区域未绘制。

我尝试使用

memDC.SetViewportOrg(0, 0);
重置视口原点,但这并没有解决问题。此外,之前可见的区域在滚动后会错误地重新绘制 - 它们与我滚动的数量不对齐。

令人惊讶的是,我发现了一个与 MSDN 官方对

BitBlt
参数描述相矛盾的解决方法。

有人可以帮助澄清为什么观察到的行为与 MSDN 文档不同吗?在具有双缓冲的

CScrollView
中正确处理滚动和重绘时,我可能会缺少什么?

这是没有所有杂项的代码:

void CMyScrollView::OnDraw(CDC* pDC)
{
    CDocument* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;

    CRect rect;
    GetClientRect(&rect);

    CDC memDC;
    memDC.CreateCompatibleDC(pDC);

    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
    CBitmap* pOldBitmap = memDC.SelectObject(&bitmap);

    // set the viewport origin to reflect the mouse scroll.
    CPoint scrollPos = GetDeviceScrollPosition();
    memDC.SetViewportOrg(-scrollPos.x, -scrollPos.y);

    // custom drawing function.
    myDrawingFunction(&memDC); 

    // reset the viewport origin.
    // memDC.SetViewportOrg(0, 0);

    pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);

    // This works, but seems quite hacky and it doesn't seem to match the MSDN description of the parameters.
    // pDC->BitBlt(0, 0, rect.Width()+scrollPos.x, rect.Height()+scrollPos.y, &memDC, 0, 0, SRCCOPY)

    memDC.SelectObject(pOldBitmap);
}
c++ winapi mfc scrollview gdi
1个回答
0
投票

CScrollView
类处理滚动并调用
OnDraw()
进行重绘。它的工作原理与
CView
类似,但有一些差异。基本上,
CDC
是由滚动位置偏移的。然而,
GetClientRect()
函数返回的矩形(窗口可见区域)位于窗口客户端坐标中,即从
(0,0)
开始。因此,正确的使用方法是仅绘制可见区域,这可以通过将客户端矩形偏移滚动位置并将这些值传递给
BitBlt()
来实现。无需为
SetViewportOrg()
调用
memDC
,您可以简单地从其正常原点
(0,0)
绘制它。

在下面的链接中找到我之前的一些相关内容:
MFC:使用CScrollView时如何访问滚动条?
MFC CScrollView 不清除背景

© www.soinside.com 2019 - 2024. All rights reserved.