enablewindow showwindow 模态对话框的消息处理机制分析

电脑杂谈  发布时间:2017-01-22 04:03:32  来源:网络整理

MFC对“设置”按钮自动添加的OnConfig函数响应实际是用

PostMessage来处理的,也就是说用户点击“设置”对话框产生的消息是Post程A的消息队列里的。

所以,同事把这个逻辑加到了他的线程B中,他在响应我的UM_CONFIG消息时候,弹出的是个模态的设置对话框。我是调用

SendMessage(UM_CONFIG)给他的,结果还是发现多次点击“设置”按钮的时候,只会出现一个设置对话框,但是关闭后,又会出现第二个设置对话框。奇怪的是不管点击多少次“

设置”,都是出现两个设置对话框。

当把我的发送消息的方式由SendMessage(UM_CONFIG)改为PostMessage(UM_CONFIG)后,问题完美解决,无论用户怎么点击“设置”按钮,都只会出现一个模态的设置对话框,而且

关闭后也不再出现。

这几种情况到底有什么区别,导致效果不同呢?为此我查阅相关资料研究了下,原因就在于模态对话框的消息处理过程,它会导致消息重入:

当一个窗口时模态对话框时,它的消息处理过程是有点特殊的。模式对话框都有自己的消息循环,它阻塞的是原始的消息循环,但是被对话框的消息循环接替。消息循环的本

质是调用窗口过程,进一步调用你的各种消息响应函数,所以无论有多少个消息循环存在,只要有一个消息循环有效,所有的消息响应函数都能被调用,这也是为什么主窗口还能

响应消息的缘故。多个消息循环的存在会产生某些副作用,比如消息重入,第一次消息响应时弹出一个模式对话框,模式对话框的消息循环2取代原始消息循环1,假设此时主窗口

消息队列里又有一个同样的消息到来,消息循环2也会调用同样的窗口过程(响应函数),此时就能导致消息重入(因为第一次进入这个处理函数还没有返回,本质上这个响应函数

被递归调用了),这也是能弹出多个模式对话框的原因。每个模式对话框都有自己的消息循环,只有最后一个弹出对话框的消息循环才是活动的消息循环,其它所有消息循环(包

括主窗口、之前弹出的模式对话框)全被阻塞。enablewindow showwindow这里的“阻塞”并不是消息被阻塞,而只是DispatchMessage一直没有返回而已,但是其它的消息循环会接替这些工作。

网上有人写出了模拟模态对话框的消息循环的代码:

BOOL DoModule()

{

HWND hParent = ::GetActiveWindow();

Create(hParent);

CenterWindow();

::EnableWindow(hParent, FALSE);

ShowWindow(SW_RESTORE);

SetActiveWindow();

MSG msg;

while(TRUE)

{

while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))

{

if(msg.message == WM_QUIT)

{

::EnableWindow(hParent, TRUE);

::SetActiveWindow(hParent);

return FALSE;

}

::GetMessage(&msg, NULL, 0, 0);

if(msg.message == hParent && msg.message != WM_PAINT)

{

continue;

}

::TranslateMessage(&msg);

::DispatchMessage(&msg);

if(!IsWindow())

{

::EnableWindow(hParent, TRUE);


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-27964-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...