导航
  • 主页
  • VC综合技术
  • 互联网技术
  • MFC AppLauncher
  • .NET 技术
  • 界面
  • 进程
  • 算法
  • 硬件/系统
  • 数据库
  • VC++技术资源

处理WM_PAINT的代码会被重叠执行?

蒙飞鸿 2009-07-25 04:29:52
经典教材《WINDOWS程序设计》的第一个自己的窗口例题,如果在处理WM_PAINT的代码里,加入一个MESSAGEBOX代码,那么,运行以后,对窗口做些动作比如拖动,都会产生(弹出)新的MESSAGEBOX。这个怎么解释?
该教材里已经说了“直到窗口过程将控制返回给Windows,DispatchMessage才能返回”,那不就是处理WM_PAINT的代码不应该在没结束上一次处理前被执行的啊??
...全文
149 点赞 收藏 26
写回复
26 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
蒙飞鸿 2009-10-08
回头看看,了解了个大概,估计完全捋清这个东西还是得了解WINDOWS核心点的知识,先结贴散分。
回复
fly4free 2009-07-26
记得windows程序设计里 提到 windows 在几种情况下 自己处理重绘,比如鼠标移过
有几种情况肯定会有WM_PAINT,有几种情况不一定会有……

看的英文版,现在找不到位置了……晕。
回复
schlafenhamster 2009-07-26
MESSAGEBOX是个模态对话框!
ValidateRect(hwnd,0);// 客户区不PAINT,但无法停止非客户区的REPAINT。否则就不会死循环!
MessageBox()第一个参数可以是:0,hwnd,GetDesktopWindow()。都一样
MessageBox(hwnd,"haha","hunhun",MB_OK);
回复
fly4free 2009-07-26
摘自某电子版:


在发生下面几种事件之一时,窗口消息处理程序会接收到一个WM_PAINT消息:

在使用者移动窗口或显示窗口时,窗口中先前被隐藏的区域重新可见。
 
使用者改变窗口的大小(如果窗口类别样式有着CS_HREDRAW和CS_VREDRAW位旗标的设定)。
 
程序使用ScrollWindow或ScrollDC函数滚动显示区域的一部分。
 
程序使用InvalidateRect或InvalidateRgn函数刻意产生WM_PAINT消息。
 
在某些情况下,显示区域的一部分被临时覆盖,Windows试图保存一个显示区域,并在以后恢复它,但这不一定能成功。在以下情况下,Windows可能发送WM_PAINT消息:

Windows擦除覆盖了部分窗口的对话框或消息框。
 
菜单下拉出来,然后被释放。
 
显示工具提示消息。(tool tip)
 
在某些情况下,Windows总是保存它所覆盖的显示区域,然后恢复它。这些情况是:

鼠标光标穿越显示区域。
 
图标拖过显示区域。
回复
lzg0001 2009-07-26
拖动消息框,其下面的窗口就出现了无效区域,WM_PAINT消息就会被发送到你的窗口;

消息框本质是一个模态对话框,内部有自己的消息循环,正是这个内部的消息循环使你窗口的窗口过程不断处理WM_PAINT消息,于是不断有新的消息框被产生出来。
回复
schlafenhamster 2009-07-26
MESSAGEBOX是个模态对话框!
ValidateRect(hwnd,0);// 客户区不PAINT,但无法停止非客户区的REPAINT。否则就不会死循环!
MessageBox()第一个参数可以是:0,hwnd,GetDesktopWindow()。都一样
你不点OK是不会产生下一个MessageBox即WM_PAINT)的。你因为你点了OK主窗口要重画,所以又产生了一个MessageBox !(并没有什么“被挂起”的程序竟然能“仍然”被调用。)
回复
arong1234 2009-07-26
尝试想想,每个对话框工程开始处都有dlg.DoModal(),他也不返回,难道那个线程什么都干不了?好好想想一个对话框起来以后系统内部会做什么
回复
uniqueid 2009-07-26
当当当,我来公布最终答案:
根据《WINDOWS程序设计》一书的11.1.4节,最后一段话:“即使在显示对话框时,WndProc也可以继续接收消息。实际上,你可以从对话框过程内部给WndProc发送消息。”
这里的对话框是模态的,消息框也是模态的,具体原因就不要想太多了,楼主研究的很仔细嘛
回复
arong1234 2009-07-26
你说的那段关于“直到窗口过程将控制返回给Windows,DispatchMessage才能返回”只是说了DispatchMessage这个函数没有返回,但是由于MessageBox 是一个建立窗口的函数过程,他本身有义务不阻塞整个线程,虽然这个函数自己不会立刻返回,但是他内部一定需要一定的机制去处理消息循环,在这个过程中,消息循环会自己进行诸如GetMessage/TranslateMessage/DispatchMessage的过程,也就是DispatchMessage应该间接的递归调用了自己

我估计在WM_PAINT处理函数部分加个断点,然后看调用堆栈,一定会发现一些奇怪有趣的事情

要把“异步消息”机制好好理解理解,不要只关注一个函数的返回与否问题
另外:在消息处理中做MessageBox是非常危险的,尤其当你不怎么理解这个机制前
尝试在WM_PAINT处理函数中定义一个1024字节的数组,然后移动几次那个消息框看看


[Quote=引用 19 楼 mengfeihong 的回复:]
问题应该不在于WM_PAINT怎么多次产生,而在于为什么处理WM_PAINT的代码看起来“被挂起”以后竟然能“仍然”被调用。

初步结论是MessageBox()(因为第一参数为NULL)并没有把处理WM_PAINT的代码挂起来。
是吧?
[/Quote]
回复
蒙飞鸿 2009-07-26
问题应该不在于WM_PAINT怎么多次产生,而在于为什么处理WM_PAINT的代码看起来“被挂起”以后竟然能“仍然”被调用。

初步结论是MessageBox()(因为第一参数为NULL)并没有把处理WM_PAINT的代码挂起来。
是吧?
回复
wu_qing_yun 2009-07-26
WM_ONPAINT消息是WINDOWS出发的,每当窗口移动,切换时都会出发这个消息,所以会不停地弹出对话框
回复
蒙飞鸿 2009-07-25
看了看回贴,我觉得发生这个情况的原因跟MESSAGEBOX第一个参数有明显关系,但并不能因此就下定论,而且这样也没有捋清逻辑上的因果。另一个关键应该是marrco2005说的消息泵机制,这个在经典教材里还没提到,得去找找,如果有人能深入浅出把逻辑因果补充完就太好了。
回复
schlafenhamster 2009-07-25
改成这样试试:
case WM_PAINT:
ValidateRect(hwnd,0);
MessageBox(hwnd,"haha","hunhun",MB_OK);
break;
你再点点OK看看。
回复
fly4free 2009-07-25
MessageBox的消息循环 和 主窗口的消息循环 没啥联系吧?
回复
stjay 2009-07-25
MessageBox内部的WM_PAINT消息
回复
marrco2005 2009-07-25
窗口的执行过程肯定不会并行的,是串行的。
一般情况下,只有一个消息处理函数返回后才会执行下一个消息处理函数
但MessageBox有它特殊的地方
MessageBox创建之后,
其内部会建立一个"消息泵"
在MessageBox尚未返回的这段时间里,由这个消息泵负责接收、分发消息。

所以,你虽然没有按下OK按钮,WM_PAINT处理函数也没有返回,但是由于
MessageBox建立了一个新的消息泵,你的程序仍然能够处理消息
回复
arong1234 2009-07-25
你说的这个是"SendMessage"的说明吧?WM_PAINT不是SendMessage发出的,因此不符合你说的情况吧

[Quote=引用楼主 mengfeihong 的回复:]
经典教材《WINDOWS程序设计》的第一个自己的窗口例题,如果在处理WM_PAINT的代码里,加入一个MESSAGEBOX代码,那么,运行以后,对窗口做些动作比如拖动,都会产生(弹出)新的MESSAGEBOX。这个怎么解释?
该教材里已经说了“直到窗口过程将控制返回给Windows,DispatchMessage才能返回”,那不就是处理WM_PAINT的代码不应该在没结束上一次处理前被执行的啊??
[/Quote]
回复
fly4free 2009-07-25
你把 MessageBox (NULL,TEXT("loop?"),TEXT(""),MB_OK); 换成
MessageBox (hwnd,TEXT("loop?"),TEXT(""),MB_OK);
看看有什么效果?

-----------------------------------------
个人觉得,这两种效果是由这个消息以非队列形式而来造成的。

回复
schlafenhamster 2009-07-25
不是叫你”把你的窗口搞的很小试试“吗!
回复
蒙飞鸿 2009-07-25
不是循环的问题吧,是并行执行同一段窗口过程代码的问题,该段被MESSAGEBOX挂起以后,竟然在其他地方被再次并行执行了,
回复
发动态
发帖子
VC/MFC
创建于2007-09-28

1.5w+

社区成员

VC/MFC相关问题讨论
申请成为版主
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……