当前位置: 首页 > article >正文

MFC 刷新失效的Picture控件

http://www.cnblogs.com/zwh0214/p/6050479.html


 

问题描述:如在摄像头显示时,关闭摄像头,此时Picture控件仍然显示最后一帧图像,需要刷新掉,还原Picture控件。或者重复显示两张不同大小的图片时,第二张背景有第一张图片残留。

 

解决方法1:(最笨的方法)

 用对话框背景色来填充控件,

CRect rect;
GetDlgItem(IDC_ShowImage)->GetClientRect(&rect);
GetDlgItem(IDC_ShowImage)->GetDC()->FillSolidRect(&rect2, RGB(255, 255, 255));//可能会把边界线也刷掉
//CRect rect2(rect.left+1 , rect.top+1 , rect.Width()-1 , rect.Height()-1 ); //可以转化一下,但治标不治本

 

解决方法2:

(1)Invalidate(); //使整个窗体无效,全部重绘

(2)GetDlgItem(IDC_ShowImage)->Invalidate(true);//使控件部分无效,进行重绘,但测试发现好像无效,原因不知,有知道的可以留言告知,谢谢!

Invalidate()是使整个窗口客户区无效, 窗口的客户区无效意味着需要重绘,会将整个窗口下所有控件都给刷新,一般会造成闪烁。

 

Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),需要处理到WM_PAINT消息时才真正重绘。

Invalidate里面有个bool型的参数,用来标识重绘的时候是否用背景色填充,默认为true。

 

注意:UpdateWindow() 则是要求系统对区域进行立即重绘。向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT。

设想了一下:直接UpdateWindow()是不执行的,因此,

InvalidateRect(rect); //声明无效区
UpdateWindow(); //进行重绘

确实重绘了,但由于相对坐标系的问题,导致重绘区域不是想要的,方法3会讲解原因以及解决方法。

UpdateData()这个函数不是刷新界面用的。
UpdateData()参数为FALSE时,将界面上控件绑定的变量的数据导到控件内,参数为TRUE时,导入方向则相反。

 

解决方法3:(比较推荐的)

InvalidateRect(rect);
InvalidateRect(rect,true);   //rect如果为NULL,全部的窗口客户区域将被增加到更新区域中。
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,在客户区域重绘之前先重绘背景。
如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,
补充说明:
InvalidateRect是将窗口中的一块矩形区域标注为“无效”,系统会不断向窗口发送WM_PAINT消息令其重绘。在响应WM_PAINT消息时,需要调用BeginPaint获取DC来进行重绘。该函数会合并所有“无效”区域,对DC进行裁剪,将整个窗口标注为“有效”,清除WM_PAINT消息。DC经裁剪之后,在进行绘制时,超出DC范围的操作将不被处理,所以即使在响应WM_PAINT消息时绘制的是整个窗口,而实际上绘制的也只是“无效”区域。恰当地使用InvalidateRect进行刷新比刷新整个窗口的效率要高。在WM_PAINT消息时,应尽量根据PAINTSTRUCT结构中rcPaint指定的矩形来处理重绘,减少执行不必要的代码,从而提高效率。调用InvalidateRect后不需要手动发送WM_PAINT消息。
但要特别注意的是,InvalidateRect(rect)  使用的是对话框的坐标系,而不是绘图控件的坐标系。所以这种用法并不能直接得到想要的效果,
pWnd->GetClientRect(&rect);//得到控件客户区区域

这是因为该种方法得到的 rect是控件客户区坐标, 而InvalidateRect ,RedrawWindow用的却是对话框客户区坐标,所以在使用InvalidateRect、RedrawWindow 之前 必须将其他坐标系下的坐标进行转换,否则不能按预想的执行。

复制代码
CWnd* pWnd = GetDlgItem(IDC_ShowImage);
pWnd->GetClientRect(&rect);//得到控件客户端区域坐标
pWnd->ClientToScreen(rect);//将区域坐标由 控件客户区转成对话框区
//pWnd->GetWindowRect(&rect); //直接得到控件的对话框区坐标this->ScreenToClient(rect); //将区域坐标由 对话框区转成对话框客户区坐标
InvalidateRect(rect);
//RedrawWindow(rect);
复制代码

这里面有几个需要注意的点:

1.可以通过GetWindowRect直接获取控件相对于对话框区坐标。

2. 注意对话框区和对话框客户区的区别。(参考链接2)

3.在这里,InvalidateRect(rect);和RedrawWindow(rect)效果一样,这是由于消息队列消息很少,所以执行很快,但需要注意:

InvalidateRect()不能实现立即更新 ;

InvalidateRect()与 UpdateWindow()结合后可以实现立即更新;

两者结合的效果相当于RedrawWindow(rect)。

 

参考链接:

(1) InvalidateRect()、UpdateWindow()、RedrawWindow()区别

  http://blog.csdn.net/shuilan0066/article/details/6826000

(2) GetWindowRect和GetClientRect的区别详解

  http://www.cnblogs.com/wb-DarkHorse/archive/2013/07/08/3178201.html

(3) 使用InvalidateRect(rect) 防止图片移动时发生闪烁

  http://blog.csdn.net/shuilan0066/article/details/6676229

http://www.lryc.cn/news/2419333.html

相关文章:

  • Gensim做中文主题模型(LDA)
  • 利用电脑玩android版天天连萌刷高分 二,利用计算机玩Android版“天天连萌”刷高分(一)——截图...
  • javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative
  • Solid converter【专业PDF转换器】
  • 【爬虫】get 和 post 的区别
  • 如何为微信小程序添加在线客服和用户支持功能
  • Honey Select 2 AIShoujo 自用搜集插件+下载地址
  • svchost.exe[1348]中发生未处理的win32异常 分析
  • 针不错!10+个综合资源网站,好用的很网站!
  • https://www.luogu.org/blog/An-Amazing-Blog/mu-bi-wu-si-fan-yan-ji-ge-ji-miao-di-dong-xi
  • Lou's Pseudo 3d Page v0.91
  • marquee属性详细解答
  • H3C交换机路由器配置命令大全
  • 将数据与OpenLayers结合在一起
  • 图像分割之(五)活动轮廓模型之Snake模型简介
  • shell脚本中四则运算
  • 认识C语言的线程
  • explorer是什么?
  • 一文看懂:网址,URL,域名,IP地址,DNS,2024年最新秀出天际
  • 数据库 超键、候选键、主键、外键
  • 【Flink-HDFS】Call From * to * failed on connection exception: java.net.ConnectException: 拒绝连接;
  • cs服务器(cs索沛服务器)
  • 梯度下降法求解线性回归之python实现
  • ASP.NET运行环境配置
  • 云诺网盘为什么关停了好用的企业网盘有哪些
  • 使用vAPP管理资源
  • Unity - Shader - Projector 高空云层底下透明阴影 - semitransparent shadow
  • Linux 串口RS232/485/GPS 驱动实验(移植minicom)
  • MTK 平台屏蔽 factory mode
  • Redis可视化工具Windows版 Another Redis Desktop Manager 安装与使用_保姆级别