MFC 窗口重绘问题

在客户区画直线等图形时, 发现当其最小化或者其他窗口遮挡时,出现窗口重绘,而将原来绘制的图形删除,上网上搜索知道,绘制图形的代码必须放置在Ondraw函数中,才能避免重绘时图形消失(因为一直在响应WM_PAINT消息,不断的重绘),但是这样做却只能保存最近的一次绘图,只适用于单幅固定的图形,对于其中有多幅图形就不能这么做了,解决的思路是:考虑到MFC时 文档/视图 类,视图CView负责数据的显示和修改,文档CDocument类负责数据的存储和加载,从而把数据管理和显示方法分离开来。我们在CDocument类中添加一个CBitMap对象,将每次中间绘图时的客户区的内容保存成BitMap,当所有的操作都执行好以后,将最终的BitMap拷贝到屏幕中,这就是所谓的内存缓存画图方式。这么做还有一个好处就是更新是看不到闪烁。

具体代码如下:

1、中间图形处理过程(事先已经在CDrawDoc类中添加了变量CBitmap m_bmpBuf;):

void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
 CDC *pDC = GetDC();
 CDrawDoc *pDoc = GetDocument();
 CDC dcMem;

dcMem.CreateCompatibleDC(NULL);
 CRect rect;
 GetClientRect(&rect); //获取客户区域
 pDoc->m_bmpBuf.DeleteObject();
 pDoc->m_bmpBuf.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
 CBitmap *pOldBitmap = dcMem.SelectObject(&pDoc->m_bmpBuf);//将创建好的m_bmpBuf添加到临时的CDC的Object中,类似于在墙上先糊上墙纸^_^,先在墙纸上作画,最后将最终形成的画拷贝到墙上。
 m_ptEnd = point;

dcMem.BitBlt(0,0,rect.Width(),rect.Height(),pDC,0,0,SRCCOPY);

dcMem.SelectObject(pOldBitmap); //将pDC即当前客户区里面的内容拷贝到临时的MEM中,MEM虽然过后会被delete掉,但是它更新了CDocument类中的m_bmpBuf
 m_bDraw = false;
 dcMem.DeleteDC();
}

2、最终显示(在OnDraw中实现):

void CDrawView::OnDraw(CDC* pDC)
{
 CDrawDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 if (!pDoc)
  return;
 CRect rect;
 GetClientRect(&rect);
 CDC dcMem;//以下是输出位图的标准操作
 CBitmap *pOldBitmap = NULL;
 dcMem.CreateCompatibleDC(NULL);
 pOldBitmap = dcMem.SelectObject(&pDoc->m_bmpBuf);
 
 pDC->BitBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0,SRCCOPY);
 dcMem.SelectObject(pOldBitmap); //将dcMeM中的bitmap拷贝到当前客户区
 dcMem.DeleteDC();

}

http://www.cnblogs.com/lidabo/p/3491850.html

时间: 2024-08-05 14:07:55

MFC 窗口重绘问题的相关文章

MFC窗口重绘

Invalidate()与 UpdateAllViews()有什么分别 Invalidate()是让程序重画窗口. UpdateAllViews()是在DOC/VIEW结构中, 当一个视图的数据改变后, 通知所有视图作相应的改变, 和重画毫无关系. Invalidate()是使窗口无效,使系统向其发WM_PAINT消息,使的程序的OnPaint被调用重画客户区. 而UpdateAllViews()是文档与视之间的联系,调用从它会使程序与此文档相关的所有视的UpdateView被调用至于是否重画以

【MFC】MFC中窗口重绘

MFC中窗口重绘 摘自:http://blog.csdn.net/shuilan0066/article/details/5859057 在刷新窗口时经常要调用重绘函数 MFC提供了三个函数用于窗口重绘 InvalidateRect(&Rect) Invalidate() UpdateWindow() 当需要更新或者重绘窗口时,一般系统会发出两个消息WM_PAINT(通知客户区有变化)和 WM_NCPAINT(通知非客户区有变化)WM_NVPAINT系统会自己搞定WM_PAINT消息对应的函数是

MFC中窗口重绘

搬家于CSDN 2015-05-14 MFC提供了三个函数用于窗口重绘 InvalidateRect(&Rect) Invalidate() UpdateWindow() 当需要更新或者重绘窗口时,一般系统会发出两个消息WM_PAINT(通知客户区有变化)和 WM_NCPAINT    (通知非客户区有变化) WM_NVPAINT    系统会自己搞定 WM_PAINT         消息系统默认对应的函数是OnPaint(),但‍一般在重绘时都在OnDraw,因为在ONPAIN中调用了OND

【转】VC的MFC中重绘函数的使用总结(整理)

原文网址:http://www.cnblogs.com/x8023z/archive/2008/12/09/mfc33.html 在刷新窗口时经常要调用重绘函数MFC提供了三个函数用于窗口重绘InvalidateRect(&Rect)Invalidate()UpdateWindow()当需要更新或者重绘窗口时,一般系统会发出两个消息WM_PAINT(通知客户区有变化)和WM_NCPAINT(通知非客户区有变化)--WM_NVPAINT系统会自己搞定--WM_PAINT消息对应的函数是OnPain

WM_PAINT消息在窗口重绘的时候产生,那什么时候窗口会重绘(异步工作方式,效率更高,灵活性更强)

Q:wm_paint消息在窗口重绘的时候产生,那什么时候窗口会重绘?? A: 严格地说,只有当收到WM_PAINT消息后窗口会重绘 但是引起这个消息的事件有很多, 比如: 首次创建 移动 改变大小 showwindow/ activate window/ invalidate window .... 系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地

窗口重绘

Windows程序运行时,如果程序窗口大小发生变化,窗口会发生重绘,窗口中已输入的文字或图像就会被擦除.如果希望输入的内容始终保留在窗口上,就要在响应WM_PAINT消息的函数中将内容再次输出.在MFCAppWizard的视图窗口中提供了类似于WM_PAINT消息响应函数的OnDraw函数,当窗口发生重绘时,应用程序框架代码就会调用该函数. OnDraw函数: void CTextView::OnDraw(CDC* pDC) { CTextDoc* pDoc = GetDocument(); A

MFC按钮重绘

1 //按钮重绘函数 2 void CWeather091001Dlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { 3 CDC buttonDC; 4 CBitmap bitmapTrans; 5 BITMAP bmp; 6 CDC mem; 7 CRect rc; 8 buttonDC.Attach(lpDrawItemStruct->hDC); 9 //得到用于绘制按钮的DC 10 mem.CreateCompat

mfc 按钮自绘

MFC  按钮自绘 :songyanwu 如果你是大神就没必要看这个文章了! 说明 源码下载:mfc 按钮自绘 先说说自己的一些想法:我就想把按钮封装成一个类,每次在使用的时候会很方便,当然在自己的类中去重载也可以! 此文章可借鉴学习:MFC基础,MFC自绘控件学习总结. (我也主要研究了自绘控件的子类化方法  ),看完前面推荐的文章,你似乎有何种感觉呢? 先实际操作吧;原理在后面介绍: 1 新建一个对画框 应用程序 2 新添加一个CMyButton继承CButton 3 为你自己添加的类 添加

vc++图像保存,重绘

新建mfc应用程序,单文档 增加绘图 分别增加命令响应 添加成员变量UINIT 图形可以运行,如何保存呢?(一个集合类,CPtArt) 用一个类的对象来保存一个图形的三个要素 所以插入一个新的类(通常的类) 增加三个成员变量,第一个类型,设置为公有的 也可以在函数中直接写,添加起点,终点 让用户在构造的时候直接传递进来给这三个成员变量赋值 然后在原文件当中,对成员变量进行赋值 (这样构造一个类的对象来保存一个图形的三个要素) 要想增加一个指针用add,要想取出原数用GetAt CObArray