原文地址:
这两天慢慢把这次实训的成果总结出来,这是第一篇日志。
最早碰到的一个报错问题,在窗口消息处理函数中使用MessageBox(包括A和W版),由于MessageBox特性,程序会被阻塞,此时由于窗口处理函数未返回,消息分发会继续分发这个“未处理”的消息,从而导致消息重入。
下面进行分析:
MessageBox是模态对话框,Msdn中对于Dialog的解释为:
The DialogBox macro uses the CreateWindowEx function to create the dialog box. DialogBox then sends a WM_INITDIALOG message (and a WM_SETFONT message if the template specifies the DS_SETFONT style) to the dialog box procedure. The function displays the dialog box (regardless of whether the template specifies the WS_VISIBLE style), disables the owner window, and starts its own message loop to retrieve and dispatch messages for the dialog box.
原因如下:
所有的输入型消息都被MessageBox先处理,有一些在处理完后直接被丢弃,并不会传递给所有者窗体以及其他兄弟窗体;而非输入型消息在此期间MessageBox并未做处理,而是根据消息信息直接传递给所有者窗体或其他兄弟窗体,此时虽然未点击MessageBox上的任何按钮关闭MessageBox,但是同样的消息处理函数有可能重入。
我自己的解决方法是写一个多线程的对话框函数:
DWORD WINAPI _MTMessageBox(LPVOID argv){ DWORD dwBtn; TCHAR* szText; TCHAR* szCaption; TCHAR* szMsg = (TCHAR*)argv; int iMsgLen = _tcslen(szMsg); TCHAR* szBuff = new TCHAR[iMsgLen + 1]; _tcscpy(szBuff,szMsg); for (int i=0;i
使用MultiThreadMessageBox就行了,同时支持ANSI和Unicode。
备注:原作者写的MultiThreadMessageBox存在一些问题。比如“delete szBuff;”需要修改为“delete [] szBuff;”,否则会泄露内存。
下面是我重新实现了一下:
typedef struct{ TCHAR text[MAX_PATH]; TCHAR caption[MAX_PATH]; UINT type;}MessageBoxData;DWORD WINAPI MessageBoxThread(LPVOID parameter){ MessageBoxData * message_box_data = static_cast(parameter); MessageBox(NULL, message_box_data->text, message_box_data->caption, message_box_data->type); delete message_box_data; message_box_data = NULL; return 0;}void MultiThreadMessageBox(LPCTSTR lpText, LPCTSTR lpCaption, UINT uType){ MessageBoxData * message_box_data = new MessageBoxData; _tcscpy(message_box_data->text ,lpText); _tcscpy(message_box_data->caption, lpCaption); message_box_data->type = uType; HANDLE handle_thread = CreateThread(0, 0, MessageBoxThread, (LPVOID)message_box_data, 0, NULL); if (NULL != handle_thread) CloseHandle(handle_thread);}