多数情况下窗口重绘的产生大多是因为窗口部分被遮挡或者窗口有滚动发生,改变的区域并不是整个图形而只有一小部分,这一部分需要改变的就是pDC中的裁剪区了。因为显示(往内存或者显存都叫显示)比绘图过程的计算要费时得多,有了裁剪区后显示的就只是应该显示的部分,大大提高了显示效率。但是这个裁剪区是MFC设置的,它已经为我们提高了显示效率,在进行复杂图形的绘制时如何进一步提高效率呢?那就只有去掉在裁剪区外的绘图过程了。可以先用pDC->GetClipBox()得到裁剪区,然后在绘图时判断你的图形是否在这个区内,如果在就画,不在就不画。
以下是我编写的shape文件读写关于重绘部分的实例
void CShpviewView::OnDraw(CDC* pDC)
{
CShpviewDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
/*双缓存绘图*/
CDC MemDC; //定义一个显示设备对象
CBitmap MemBitmap; //定义一个位图对象
CRect rcClient; //客户区
CRect rcClip; //裁剪区
pDC->GetClipBox(rcClip); //得到整个无效区
GetClientRect(&rcClient); //得到客户区范围
//建立与屏幕显示兼容的内存显示设备
MemDC.CreateCompatibleDC(pDC);
//建立一个与屏幕显示兼容的空位图,用窗口的大小
MemBitmap.CreateCompatibleBitmap(pDC,rcClient.Width(),rcClient.Height());
OnPrepareDC(&MemDC, NULL);
//将位图选入到内存显示设备中
//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
MemDC.SelectClipRgn(NULL);
MemDC.IntersectClipRect(rcClip); //使窗口范围等于无效区
//先用背景色将位图清除干净,用的是白色作为背景
MemDC.FillSolidRect(0,0,rcClient.Width(),rcClient.Height(),RGB(255,255,255));
/*绘图*/
int i = 0;
//画点
int ptCount;
ptCount = pDoc->m_pointArray.GetSize();
for(i=0; i<ptCount; i++)
{
((CshpPoint*)pDoc->m_pointArray.GetAt(i))->DrawPoint(&MemDC); //应该选入MemDC
}
//画线
int lCount;
lCount = pDoc->m_lineArray.GetSize();
for(i=0; i<lCount; i++)
{
((CshpLine*)pDoc->m_lineArray.GetAt(i))->DrawLine(&MemDC); //要修改成GDI+
}
//画面
int pCount;
pCount = pDoc->m_polygonArray.GetSize();
for(i=0; i<pCount; i++)
{
((CshpPolygon*)pDoc->m_polygonArray.GetAt(i))->DrawPolygon(&MemDC); //要修改成GDI+
}
//将内存中的图拷贝到剪裁区上进行显示
pDC->BitBlt(rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(),
&MemDC, rcClip.left, rcClip.top, SRCCOPY);
//绘图完成后的清理
MemBitmap.DeleteObject();
MemDC.DeleteDC();
// TODO: add draw code for native data here
}