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

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

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

CRect rect;
GetDlgItem(IDC_ShowImage)->GetClientRect(&rect);
GetDlgItem(IDC_ShowImage)->GetDC()->FillSolidRect(&rect2, RGB(, , ));//可能会把边界线也刷掉
//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

MFC 刷新失效的Picture控件的更多相关文章

  1. Opencv+MFC获取摄像头数据,显示在Picture控件

    分为两步:OpenCV获取摄像头数据+图像在Picture上显示 第一步:OpenCV获取摄像头数据 参考:http://www.cnblogs.com/epirus/archive/2012/06/ ...

  2. MFC中Picture控件显示图像

    图片显示在picture控件中,整个软件最小化后图片消失问题. 解决方案:OpenCV学习笔记(9)利用MFC的Picture控件显示图像+播放视频和捕获摄像头画面 - CSDN博客  http:// ...

  3. MFC-----在MFC中使用Picture控件加载任意图片

    对于刚刚接触OpenCV的童鞋来说,如何在MFC中加载并显示一张图片.应该是初期必定会碰到的问题之一.因此本文在分享这方面经验的同时,也相当于是写给自己的一份备忘录. 本文使用的是OpenCV2.1+ ...

  4. [转]MFC子线程中更新控件内容的两种办法

    一.概述 每个系统中都有线程(至少都有一个主线程),而线程最重要的作用就是并行处理,提高软件的并发率.针对界面来说,还能提高界面的响应能力.一般的,为了应用的稳定性,在数据处理等耗时操作会单独在一个线 ...

  5. VC/MFC 当鼠标移到控件上时显示提示信息

    VC/MFC 当鼠标移到控件上时显示提示信息 ToolTip是Win32中一个通用控件,MFC中为其生成了一个类CToolTipCtrl,总的说来其使用方法是较简单的,下面讲一下它的一般用法和高级用法 ...

  6. Winform中Picture控件图片的拖拽显示

    注解:最近做了一个小工具,在Winform中对Picture控件有一个需求,可以通过鼠标从外部拖拽图片到控件的上,释放鼠标,显示图片! 首先你需要对你的整个Fom窗口的AllowDrop设置Ture ...

  7. 不受路径限制的 HALCON开发环境, 并且初始化两个Picture控件;

    知识储备: http://bbs.csdn.net/topics/391829463    关于 添加第三方库的方式 http://www.ihalcon.com/read-3730.html  VS ...

  8. 如何在vs2010中添加Picture控件

    1.新建项目,并在对话框控件中拖入picture控件,并做如下设置 2.在picture控件的属性栏需要进行如下修改:ID需要修改,不能为static ID是控件的唯一标识,PictureCtrl(p ...

  9. 将OpenCV捕获的摄像头加载到picture控件中

    CRect rect; CStatic* pStc; CDC* pDC; HDC hDC; pStc = (CStatic*)GetDlgItem(IDC_CAM);//IDC_CAM是Picture ...

随机推荐

  1. 【Lotus Notes】邮件获取

    public class LotusManager { public static int bodyMaxLength, length; public static List<Entity.Lo ...

  2. Python基础-输入输出(IO)

    Python基础-输入输出(IO) 程序会有输入和输出,输入可以从标准输入或是从一个文件读入数据,程序的输出可以以一种友好可读的方式(human-readable)打印出来,或是写进一个文件,而标准输 ...

  3. QQ高仿版

    可在广域网部署运行的QQ高仿版 -- GG叽叽(源码)   前段时间看到园子里有朋友开发了QQ高仿版的程序,我也非常有兴趣,以前一直有个做即时聊天程序的梦,趁这段时间工作不是很忙,就开始动手来做这个事 ...

  4. #2006 - MySQL server has gone away 问题解决方法 (全) (转)

    #2006 - MySQL server has gone away 问题解决方法 原文地址:http://www.cnblogs.com/bisonjob/archive/2009/08/18/15 ...

  5. SQL Server 2014新特性:五个关键点带你了解Excel下的Data Explorer

    SQL Server 2014新特性:五个关键点带你了解Excel下的Data Explorer Data Explorer是即将发布的SQL Server 2014里的一个新特性,借助这个特性讲使企 ...

  6. Kendo UI开发教程(6): Kendo DataSource 概述

    Kendo 的数据源支持本地数据源(JavaScript 对象数组),或者远程数据源(XML, JSON, JSONP),支持CRUD操作(创建,读取,更新和删除操作),并支持排序,分页,过滤,分组和 ...

  7. 64位linux报错Could not initialize class java.awt.image.BufferedImage

    最近碰到一个问题: 64位linux报错Could not initialize class java.awt.image.BufferedImage 在WIN平台下运行正常BufferedImage ...

  8. windows下安装Django

    因为Django本身是由Python编写,所以先要安装Python.下载地址(可以根据读者当前版本自行下载):http://www.python.org/download/releases/3.3.4 ...

  9. C语言之break和continue

    一 break 和 continue 的介绍 break: 1).跳出当前所在的switch语句(tips:可查看前面 switch 部分)   2).跳出当前所在的循环 continue: 结束本次 ...

  10. 怎样求FIRST集、FOLLOW集和SELECT集

    一,要知道什么是终结符和非终结符. 终结符:通俗的说就是不能单独出现在推导式左边的符号,也就是说终结符不能再进行推导. 非终结符:不是终结符的都是非终结符.(非男即女,呵呵) 如:A-->B,则 ...