为什么消息框不阻止线程?
Why doesn't message box block the thread?
考虑下面的代码片段,其中WM_TIMER消息上显示了一个消息框。
#define IDT_TIMER1 1001
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
//...
case WM_INITDIALOG:
{
//...
SetTimer(hWnd, IDT_TIMER1, 1000, (TIMERPROC)NULL);
break;
}
case WM_TIMER:
{
int ret = MessageBox(hWnd, L"Cancel operation?", NULL, MB_YESNO);
if(ret == IDYES) {
EndDialog(hWnd, 0);
} else {
// no-op: keep going
}
break;
}
//...
default:
return FALSE;
}
return FALSE;
}
我希望这段代码在初始计时器滴答声时显示一个消息框,并阻塞线程,直到用户单击按钮。实际发生的情况是,即使用户没有单击任何按钮,每个计时器勾选时都会显示新消息框。
当我检查线程的调用堆栈时,我看到对DialogProc()
的多个调用,都停留在调用MessageBox()
的行上(即,都在等待用户输入)。
给定调用堆栈的状态,DialogProc()
怎么可能在同一线程中被调用,而MessageBox()
在对DialogProc()
的最后一次调用中尚未返回?
附言:请注意,我并不是在问如何完成期望的行为。我只是想了解实际行为中"幕后"发生了什么。
MessageBox
启动一个新的Message Loop,它可以通过正常的Windows回调机制访问并调用您的DialogProc
。
如果它不这样做,那么像WM_PAINT
这样的事件就不会得到处理,你的应用程序看起来就像死了一样(除了消息框)。因为计时器仍在运行,所以WM_TIMER
事件会在适当的时间排队。
MessageBox
进入呈现窗口、处理按钮所需的嵌套消息循环。
指定为MessageBox
调用中第一个参数的窗口的输入已被EnableWindow
禁用,但这不会禁用所有消息,因此您仍然可以接收WM_PAINT、WM_TIMER和其他消息。通常,它会禁用用户输入:鼠标、键盘,但也会使用鼠标调整窗口大小。
这个伪代码显示了MessageBox模拟是如何潜在地实现的:
int MessageBox( HWND owner_hwnd, ... )
{
...
HWND box_hwnd = CreateWindowEx( ..., owner_hwnd, ... );
...
EnableWindow( owner_hwnd, FALSE );
...
while ( !done )
{
MSG msg;
GetMessage( &msg, ... );
if ( IsDialogMessage( box_hwnd, &msg ) )
continue;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
...
EnableWindow( owner_hwnd, TRUE );
...
DestroyWindow( box_hwnd );
...
return button;
}
相关文章:
- 线程消息传递或更好:在"大师班"中访问其他班级的成员
- 将类成员函数作为线程调用到另一个类成员函数时发出警告消息
- C++ Poco - 如何向特定线程发送通知/消息?
- 如何从其他线程 winapi 获取消息
- 为什么分离线程没有得到输出消息
- QTcpSocket:消息不是从另一个线程发送的
- 多线程套接字编程服务器仅从 1 个客户端线程获取消息
- 视觉C++跨线程发送消息
- 从 Visual C++ 2010 中的单独线程调用消息框
- IPC Unix 消息队列线程安全吗?
- boost消息队列线程安全和进程安全吗?
- 为什么消息框不阻止线程?
- 回复:等待完整消息(可变大小消息,线程)
- 在状态栏上显示来自不同线程中回调的消息
- 增强ASIO和线程之间的消息传递
- 从内存转储中查找线程消息队列中的消息
- 来自另一个线程的 SendMessage() 调用是否将消息发布到消息队列
- 消息蜂鸣线程阻塞
- 多线程C++消息传递
- 线程消息之间的优先级