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

您所在的位置:网站首页 对话框画图 MFC编程,Cview类OnDraw重绘时,视图内容消失问题的解决

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

2024-07-10 17:08| 来源: 网络整理| 查看: 265

      问题描述:在进行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等很具有特性,对问题的解决造成了很大的困扰,通过在代码的调试中不断的摸索才渐渐熟悉了这些特性,进而解决问题。代码肯定存在不完善的地方,希望大家能给予指正,共同进步!



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3