MFC编程,Cview类OnDraw重绘时,视图内容消失问题的解决

      问题描述:在进行MFC绘图编程时(以简单的绘制线条为例),视图窗口的大小变化会引起调用OnDraw()。默认的OnDraw()会重绘显示出一个空白的视图,因此必须重写这个方法以显示文档的视图。

   解决思路:通过查阅资料发现,这种问题通常的处理方法是在文档中记录绘图数据,在窗口重绘时使用这些数据恢复图像。我认为使用这种方法时,在绘图的同时考虑记录数据将增加不少代码复杂度(因我了解的不够及水平有限,这种观点可能有误),同时在复杂的图像所需要记录的数据量将很大。另外,还有一种“内存缓存画图”的方式,考虑到MFC时 文档/视图 类,视图CView负责数据的显示和修改,文档CDocument类负责数据的存储和加载,从而把数据管理和显示方法分离开来。我们在CDocument类中添加一个CBitMap对象,将每次中间绘图时的客户区的内容保存成BitMap,当所有的操作都执行好以后,将最终的BitMap拷贝到屏幕中,这就是所谓的内存缓存画图方式。我比较倾向于用这种方式解决重绘问题,但我所查到的网上所提供的代码都只能解决绘图时的“闪烁”问题(参考搜索“C++双缓冲绘图”)。因此我基于后者的缓冲绘图思想,以绘制线条为例,编写代码解决重绘问题。
具体实现过程及代码如下(工程名为LocateByLh):
1、在CLocateByLhDoc类中创建CBitmap类型的m_bmpBuf用于保存视图(同时也可以用于缓冲绘图),同时在CLocateByLhView类中添加一个bool型变量。
public:
 CBitmap m_bmpBuf;
/
private:
 bool bFlag;
/
2、在OnDraw()方法内添加m_bmpBuf输出代码和只在首次执行的m_bmpBuf初始化代码(设置bFlag就是为了只执行一次)。
void CLocateByLhView::OnDraw(CDC* pDC){
 CLocateByLhDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 // TODO: add draw code for native data here
 //重绘显示bitmap,思路是创建一个临时的dcMem,先把m_bmpBuf作为画布放入其中,然后拷贝到pDC中显示出来
 CDC dcMem;
 CRect rect;
 GetClientRect(&rect);
 dcMem.CreateCompatibleDC(NULL);
 dcMem.SelectObject(&pDoc->m_bmpBuf);
 pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY);
 dcMem.DeleteDC();
 //初始化一个白色填充的m_bmpBuf,
 if(bFlag){
 CLocateByLhDoc *pDoc = GetDocument();
 CDC dcMem2;
 dcMem2.CreateCompatibleDC(NULL);
 pDoc->m_bmpBuf.CreateCompatibleBitmap(pDC,2500,1500);
 dcMem2.SelectObject(&pDoc->m_bmpBuf);
 dcMem2.FillSolidRect(0,0,2500,1500,RGB(255,255,255));
 dcMem2.BitBlt(0,0,rect.Width(),rect.Height(),pDC,0,0,SRCCOPY);
 dcMem2.DeleteDC();
 bFlag=false;
 }
}
 
 
3、鼠标左键弹起事件中的绘图线条代码,
void CLocateByLhView::OnLButtonUp(UINT nFlags, CPoint point) 
{
 // TODO: Add your message handler code here and/or call default
 
 CLocateByLhDoc *pDoc = GetDocument();
 CDC* pDC = GetDC();
 CDC dcMem;
 CRect rect;
 GetClientRect(&rect);
 dcMem.CreateCompatibleDC(NULL);

 //注释部分采用的是非缓冲画图,直接用pDC进行绘图,然后复制到m_bmpBuf
 //CPen pen(PS_SOLID,2,RGB(255,0,0));
 //pDC->SelectObject(&pen);
 //pDC->MoveTo(m_ptOrigin);
 //pDC->LineTo(point);
 //dcMem.SelectObject(&pDoc->m_bmpBuf);
 //dcMem.BitBlt(0,0,rect.Width(),rect.Height(),pDC,0,0,SRCCOPY); 

 //在虚拟的dcMem中绘图,然后一次性输出显示,同时更新了m_bmpBuf
 dcMem.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, 0, 0, SRCCOPY);
 dcMem.SelectObject(&pDoc->m_bmpBuf);
 dcMem.MoveTo(m_ptOrigin);//绘制线条代码
 dcMem.LineTo(point);//绘制线条代码
 pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY); 
 
 dcMem.DeleteDC();
 ReleaseDC(pDC);
 
 CView::OnLButtonUp(nFlags, point);
}
总结:
代码中所涉及的函数如BitBlt,FillSolidRect等很具有特性,对问题的解决造成了很大的困扰,通过在代码的调试中不断的摸索才渐渐熟悉了这些特性,进而解决问题。代码肯定存在不完善的地方,希望大家能给予指正,共同进步!


  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值