WM_PAINT产生原因有2种(用户操作和API)——WM_PAINT和WM_ERASEBKGND产生时的先后顺序不一定(四段讨论)
1. 当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再发送WM_PAINT消息.
如果处理WM_ERASEBKGND消息时返回FALSE,BeginPaint标记pt.fErase 为TRUE,如果处理WM_ERASEBKGND时返回TRUE,BeginPaint标记pt.fErase为FALSE.
2.当WM_PAINT由InvalidateRect产生时,先发送WM_PAINT消息(异步),如果InvalidateRect的bErase为TRUE,BeginPaint检查到更新区域需要删除背景,向窗口发送一个WM_ERASEBKGND消息,如果处理WM_ERASEBKGND消息时返回FALSE,BeginPaint标记pt.fErase 为TRUE,如果处理WM_ERASEBKGND时返回TRUE,BeginPaint标记pt.fErase为FALSE.
如果pt.fErase标记为TRUE,指示应用程序应该处理背景,但是应用程序不一定需要处理,pt.fErase只是作为一个标记.
补充:DefWindowProc(hWnd, message, wParam, lParam)处理WM_ERASEBKGND消息时默认用下面的画刷清除背景
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
WM_ERASEBKGND返回TRUE和返回FALSE是一个规范,一般情况下没有什么区别,但是如果什么时候用到了,会根据函数返回值判断后续处理。因此最好按照要求返回数据.
http://note.sdo.com/u/432181446/NoteContent/pMF36~jDXzSFnM1rg001sf
------------------------------------------------------------------------------------------
当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再发送WM_PAINT消息.
当WM_PAINT由InvalidateRect产生时,先发送WM_PAINT消息,OnPaint()这个执行内部向窗口发送了 WM_ERASEBKGND消息来刷新背景。在OnPaint()函数中会首先调用BeginPaint()函数,在BeginPaint 函数中会发送WM_ERASBKGND.
OnEraseBkgnd函数内部不要使用 UpdateWindow MoveWindow SetWindowPos RedrawWindow等引起调用wm_paint的函数,如果在 OnEraseBkgnd 函数处理过程中 产生了需要刷新的无效区,导致系统产生wm_paint消息,这样就产生了死循环!
要在程序中想要把背景色设置成其他颜色(不是默认的),那这个代码一般在WM_ERASEBKGND 的消息响应函数中执行,而当我们想在界面上画个图形之类的,一般在WM_PAINT的消息响应函数如OnPain中执行。凡事无绝对,就是你也可以把 背景的设置放在OnPain中绘制
WM_ERASEBKGND如果返回非0,说明已经重画背景,如果返回0,程序将继续试图重画背景。
问题:Windows系统没有发出WM_ERASEBKGND消息
根据MSDN的描述,当windows被最小化时,系统需要绘制icon。
通常,系统会首先发送WM_ICONERASEBKGND给窗口,然后再发送WM_PAINTICON消息给窗口。MSDN又说,如果应用程序的WNDCLASS结构的hIcon成员如果为NULL,那么系统会发送WM_ERASEBKGND消息来替代
WM_ICONERASEBKGND消息,然后再发送WM_PAINT消息。为此应用程序应该在自己的代码中,
通过IsIconic()函数来判断当前是否application处于miminized状态。如果是,那么在
其OnEraseBkGnd函数和OnPain函数中都应该根据其minimized状态来绘制图标背景和图标。当然,MFC程序会封装WNDCLASS结构,为此我们看不到RegisterClass函数。为此我通过
GetClassInfo函数来获取WNDCLASS结构,结果发现hIcon域为NULL。根据MSDN的描述,在窗口minimized的情况下,系统应该会发出WM_ERASEBKGND消息,但是我通过
打印TRACE信息发现,系统根本没有在minimized情况下发出WM_ERASEBKGND消息。另外,根据MSDN的描述,WM_ICONERASEBKGND消息仅仅在Windows NT 3.51 and earlier有效。请高手指点,谢谢!!
The WM_ERASEBKGND message is sent when the window background must be erased (for example, when a window is resized). The message is sent to prepare an invalidated portion of a window for painting.
-------------
个人觉得最小化(IsIconic函数调用为TRUE),图标化了,就没有必要发送WM_ERASEBKBND消息来绘制窗口背景,可能是为了效率。
刚刚搜索到一个老外的描述:他说IsIconic是win16和NT3.x以前的东西,现在已经可以不需要这个分支了。另外,在百度上看到这篇文章:觉得分析得有道理。当窗口最小化时,此时已经不需要绘制client area,为此不会发出WM_PAINT消息。实际上,仅仅当application client area有update region时,系统才会在message queue为空时,才会发出WM_PAINT消息。而当application接收到WM_PAINT消息时,会首先调用BeginPaint函数来准备display device context(在CDialog::OnPaint => CPaintDC dc(this)构造函数之中),如果update region被标记为erasing,那么BeginPaint又会发出WM_ERASEBKGND消息。为此,既然在最小化时系统没有发送WM_PAINT消息给窗口,为此更不会发出WM_ERASEBKGND消息。
我曾在最小化时,故意发出WM_PAINT消息,此时该消息会进入到OnPaint的IsIconic分支。但是,如果你故意发出WM_ERASEBKGND消息,那么该消息必须在Cdialog::OnSysCommand函数之前,否则会被系统丢弃,为此不会进入OnEraseBkGnd函数。
谢谢VisualEleven的回复,系统确实为了优化client area operation而限制了某些不必要消息的发送。
http://www.debugease.com/vc/1246693.html
请问MFC的一个代码简单却功能奇怪的问题?
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
上面这个代码是MCF向导自动生成的,我跟踪了一下在最小化,最大化的过程发现没有被执行到,去掉 发现出也没出现什么不同,为何MFC要默认的帮我们生产上面的代码,有哪位高手知道上面的代码正真的目的是什么?在什么情况下会被执行到?
这段代码是有用的,尽管通常情况下不会被调用。他的作用是在最小化状态下重绘窗口图标。
IsIconic()作用是判断窗口是否处于最小化状态(点击了最小化按钮之后)。
对于普通的对话框来说,如果你在if (IsIconic()) 下面加入AfxMessageBox("haha") ,你会发现消息框并不会弹出。
原因是,if (IsIconic()) 这段代码是在OnPaint()函数内,当你最小化了对话框之后,虽然IsIconic()的值是TRUE,但是OnPaint()函数并不会运行。因为OnPaint()响应的是WM_PAINT消息,而WM_PAINT消息是针对客户区的。一个最小化了的窗口不需要重绘客户区。
为了验证这一点,可以设置一定时器,在OnTimer()函数里写上
if(IsIconic()) MessageBeep(MB_OK);
当你点击最小化按钮后,你会听见嘟嘟声。
那么这段代码究竟有什么用?它是不是永远不会被执行呢?当然不是。举两个例子。
第一,如果你强行发送WM_PAINT消息,它会执行。
第二,特殊的对话框。比如一个ToolBox风格的对话框。这个对话框不显示在任务栏,在最小化之后它会变成一个很小的一条显示在桌面上。这时如果它被遮挡,就会出发WM_PAINT消息,从而执行那段代码。
总之,一般情况下可以不要这段代码,它的特殊用途我也不是很了解,但是我们至少可以知道它是怎么样工作的。
http://zhidao.baidu.com/question/50297340
WM_PAINT产生原因有2种(用户操作和API)——WM_PAINT和WM_ERASEBKGND产生时的先后顺序不一定(四段讨论)的更多相关文章
- WM_PAINT与WM_ERASEBKGND(用户操作和API这两种情况产生消息的顺序有所不同)
1)当WM_PAINT不是由InvalidateRect产生时,即由最大化,最小化等产生时,或者移动产生(移动有时只会产生WM_ERASEBKGND消息)系统先发送WM_ERASEBKGND消息,再发 ...
- 终于懂了:WM_PAINT 与 WM_ERASEBKGND(三种情况:用户操作,UpdateWindow,InvalidateRect产生的效果并不相同),并且用Delphi代码验证 good
一直对这两个消息的关系不是太了解,借重新深刻学习windows编程的机会研究一番. 1)当窗口从无效变为有效时,比方将部分覆盖的窗口恢复时会重绘窗口时:程序首先会通过发送其他消息调用DefWindow ...
- Entity Framework 实体框架的形成之旅--几种数据库操作的代码介绍(9)
本篇主要对常规数据操作的处理和实体框架的处理代码进行对比,以便更容易学习理解实体框架里面,对各种数据库处理技巧,本篇介绍几种数据库操作的代码,包括写入中间表操作.联合中间表获取对象集合.递归操作.设置 ...
- jQuery中模拟用户操作
有时为了节省不想手动操作网页,但又想看到用户操作时的效果,可以用到jQuery提供的trigger方法.见下图代码 在不点击按钮时仍然想弹出this.value 我们只需要在后面加上.trigger( ...
- 关于Linux 交互(用户操作接口)
Linux 系统提供两种基本接口给用户操作:命令行,图形界面. 不同接口也有相应的访问终端. 一.命令行 Command Line Linux系统命令行,一般指 Shell. Shell 接受经键盘输 ...
- 从知乎首页用户操作入口学习到的CSS技巧 - 合理利用伪元素实现一些装饰样式
最近在模仿做一个静态的PC版知乎,在模仿的过程中,从知乎工程师的方法中学到了不少知识,比如CSS方面的,以下介绍一个今天学到的伪元素的技巧. 示例 DOM结构为: <div class=&quo ...
- Linux下ftp安装配置及三种用户的验证
一.原理简介 二.安装配置 三.三种用户的验证 一.简介 FTP即文件传输协议(File Transfer Protocol),完成各主机的文件共享功能,基于客户端-服务器的协议,工作在应用层,tcp ...
- C#路径的八种相关操作,判断字符串是否为路径等
原文:C#路径的八种相关操作,判断字符串是否为路径等 1.判定一个给定的C#路径是否有效,合法 通过Path.GetInvalidPathChars或Path.GetInvalidFileNameCh ...
- linux下用户操作记录审计环境的部署记录
通常,我们运维管理人员需要知道一台服务器上有哪些用户登录过,在服务器上执行了哪些命令,干了哪些事情,这就要求记录服务器上所用登录用户的操作信息,这对于安全维护来说很有必要.废话不多说了,下面直接记录做 ...
随机推荐
- 高级UIKit-05(CoreData)
[day06_1_CoreDataPerson]:保存person对象到coreData数据库 保存大量数据时用CoreData保存到数据库,数据库会存在documents目录下 操作步骤: 1.创建 ...
- extern、static、auto、register 定义变量的不同用法
首先得说明什么叫“编译单元”.每个 .c 文件会被编译为一个 .o 文件,这个就是一个编译单元.最后所有的编译单元被链接起来,就是一个库或一个程序. 一个变量/函数,只要是在全局声明的,链接之后都隐含 ...
- GExpert 1.38 实验版含经典代码格式工具 Berlin 编译版
安装方法:修改install.reg,然后导入.源代码地址:http://blog.dummzeuch.de/experimental-gexperts-version/ http://bbs.2cc ...
- POJ 3986 Math teacher's homework
题目 给出\(n,m_1,m_2,...,m_n\),求\(x_1 xor x_2 xor ... xor x_n=k (0 \leq x_i \leq m_i)\)的解的数量.二进制位数小于\(32 ...
- SQL之单行函数
单行函数语法: function name(column|expression,[arg1,arg2,...]) 参数说明: function name:函数名称 column:数据库列名 expre ...
- 幻世(OurDream)2D图形引擎使用教程8——处理操作输入(2)
声明:本教程版权归Lizcst Software Lab所有,欢迎转载,但是转载必须保留本段声明文字,并注明文章来源:http://blog.csdn.net/kflizcst 谢谢合作! 今天的教程 ...
- CEGUI 输入法窗口实现
游戏中经常要输入汉字,但当我们游戏没有自己实现输入法窗口时,windows会使用用户安装的输入法,但这个输入法窗口只会显示在游戏窗口外头,而且当我们游戏全屏时(真全屏,不是那种窗口式的假全屏),屏幕上 ...
- sqlserver bak还原
一.查看: restore filelistonly from disk='F:\Db\A_backup.bak' 二.还原:RESTORE DATABASE AFROM DISK = 'F:\Db\ ...
- call、apply以及bind
call与apply都可以改变js的this指向,两者最主要的区别就是使用时传参的不同,apply的参数可以以数组的形式传进来,但是call方法的参数必须要一个一个的传进来,就像这样. func.ca ...
- 一点一滴完全突破KAZE特征检测算法,从各向异性扩散滤波开始(1)
ECCV2012中出现了一种比SIFT更稳定的特征检测算法KAZE.尽管,这个算法是几个法国人提出的,但是算法却有一个日文的名字.KAZE是日语‘风’的谐音,最近宣布退休的宫崎骏所拍摄的影片“起风了” ...