在一个按钮的响应函数里,比如OnBnClickedXXX(),如果写上一句Sleep(10000),那么点击这个按钮后,整个程序会卡住10秒。这很好理解,因为那条按钮的WM_COMMAND消息一直没处理完,所以消息队列里的其它消息处于阻塞状态。但是假如我写的不是Sleep(),而是XXX.DoModal(),见证奇迹的时刻就来了,明明这条WM_COMMAND消息没处理完——DoModal()后面的代码还没执行,为什么这个时候主窗口和DoModal出来的窗口都能继续处理消息?——比如WM_PAINT、WM_SETCURSOR等等。。为什么呢?

解决方案 »

  1.   

    "为什么这个时候主窗口和DoModal出来的窗口都能继续处理消息",主窗口还能响应吗?这个没试过?
      

  2.   


    spy一下就知道了,主窗口还能继续处理WM_PAINT消息的;或者我们能看到主窗口能不断重绘,也就证明它在成功地处理WM_PAINT。另外,你还可以SetTimer一下,就知道主窗口还能处理消息了。
      

  3.   

    sleep很好理解的,完全阻塞住了消息队列,
    domodle里还是比较复杂的,在domodle()里是将父窗口进行了disable,和控件是一样的,disable,绘制消息还是会响应的,并不是完全的品比所有消息。
      

  4.   

    不能貌似哦。
    我们来看看经典的消息循环—— // 主消息循环:
    while (GetMessage(&msg, NULL, 0, 0))
    {
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    }msg的结构体有一个HWND成员,也就是说,一个程序所有的窗口的消息都是这一个循环在处理,何来另一个线程?如果有,那个线程什么时候开启,又是怎么样工作的呢?其实纯Win32工程里,比如helloworld工程,也有一个帮助对话框,一样是模态的,也一样有这样的问题,可见这个现象不是MFC才有的。
      

  5.   


    屏蔽消息可以理解,比如,主窗口已经没收到WM_LBUTTONDOWN了。但问题是,在DoModal()的地方,这个WM_COMMAND消息还没处理完,消息循环是怎样继续的呢?为什么还可以有WM_PAINT这样的消息继续循环?
      

  6.   

    DoModal()不会屏蔽所有的消息,一些需要的消息还是会在消息循环中处理的
      

  7.   

    GetMessage(&msg, NULL, 0, 0),这个不能说明什么
    看这个吧http://wenku.baidu.com/view/1f9e5c669b6648d7c1c74655.html
      

  8.   

    DoModal()有自己的消息循环,会阻塞父窗口的部分消息,注意不是所有消息
      

  9.   

    感谢大家的指导!结合《Windows程序设计》,研究了一下,从纯Win32消息循环角度总结如下——在主消息循环里,DispatchMessage(&msg)把从GetMessage(&msg, NULL, 0, 0)获取回来的消息重新交给Windows处理,在这个函数里面,Windows调用了这个消息所属窗口的窗口过程函数。如果是一般的消息处理,那么处理完毕后,窗口过程函数结束,随后Windows将重新把控制权交还给程序,程序继续下一次的消息循环;但如果在消息处理中,有DialogBox()函数调用,那么这一次的消息过程函数将一直不会结束,直到这个模态对话框被关闭为止。在这个过程中,我认为是会阻塞父窗口的全部消息的,因为我试了一下,在helloworld工程,模态对话框弹出后,在主消息循环里下断点,无论用鼠标在哪里点击,父窗口如何的重绘,甚至在这个时候给父窗口发送自定义消息,始终都不会触发那个断点(而自定义消息的响应函数还是会被调用的,只是不经过主消息循环),直到模态对话框关闭,断点就会马上触发。在模态对话框存在的过程中,父窗口之所以能收到消息,我估计还是DialogBox内部的实现,它除了自己有自己的消息循环外,还会给父窗口发送它需要的消息(比如WM_PAINT)——不过与其说“发送”,可能说“接管”还比较合适,因为这个时候主窗口的消息,估计就是在模态对话框内部直接GetMessage()获取,然后有选择性地进行处理,并在模态对话框内部的消息循环里有选择性地对父窗口的WndProc进行调用(至于是直接调用还是DispatchMessage()调用就不得而知了)。然后,直到模态对话框结束,它才会把控制权重新交还给DialogBox()函数调用时的WndProc,再然后,主消息循环才得以继续。以上结论的部分包含了个人的主观臆测,如有错漏,请大家指正。。
      

  10.   

    DoModal本来就不是挂起程序阻塞父窗口所有消息的
    否则一个直观的问题就是当窗口被遮挡再重现父窗口无法重绘啊
      

  11.   


    我认为是阻塞全部的,那些重绘消息我看是模态对话框内部以某种方式让父窗口得以调用响应重绘消息的函数。你可以做个实验,在Win32的helloworld工程,弹出帮助对话框后,把断点设在主消息循环里。除非帮助对话框被关闭,否则该断点一直不会命中。
      

  12.   

    Sleep主线程。所有界面当然没法响应了。
      

  13.   

    所谓DoModal的阻塞只是因为模态对话框自带消息循环,截获了消息循环而已。对于某些消息,对话框取得之后通过DispatchMessage(&msg)还是会分配给主窗口来处理。