我正在致力于在利用
CScrollView
的 MFC 项目中使用内存 DC 实现双缓冲。我的自定义视图类源自CScrollView
。
但是,向下滚动时遇到一个问题:新可见的区域未绘制。
我尝试使用
memDC.SetViewportOrg(0, 0);
重置视口原点,但这并没有解决问题。此外,之前可见的区域在滚动后会错误地重新绘制 - 它们与我滚动的数量不对齐。
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);
}
CScrollView
类处理滚动并调用 OnDraw()
进行重绘。它的工作原理与 CView
类似,但有一些差异。基本上,CDC
是由滚动位置偏移的。然而,GetClientRect()
函数返回的矩形(窗口可见区域)位于窗口客户端坐标中,即从(0,0)
开始。因此,正确的使用方法是仅绘制可见区域,这可以通过将客户端矩形偏移滚动位置并将这些值传递给BitBlt()
来实现。无需为 SetViewportOrg()
调用 memDC
,您可以简单地从其正常原点 (0,0)
绘制它。
在下面的链接中找到我之前的一些相关内容:
MFC:使用CScrollView时如何访问滚动条?
MFC CScrollView 不清除背景