MessageBoxTimeout API






4.84/5 (27投票s)
一篇关于使用未文档化的 MessageBoxTimeout API 的文章。
引言
出于未知的原因,微软从未公开文档化位于 user32.dll 中的 MessageBoxTimeout
API。因此,这里提供给那些需要一个超时并自动关闭的消息框(如果用户未先响应)的人们。
使用代码
该代码可用于 UNICODE 和 MBCS,只需将以下代码添加到源文件(cpp)中即可
#include <windows.h> #include <tchar.h> //Functions & other definitions required--> typedef int (__stdcall *MSGBOXAAPI)(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds); typedef int (__stdcall *MSGBOXWAPI)(IN HWND hWnd, IN LPCWSTR lpText, IN LPCWSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds); int MessageBoxTimeoutA(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds); int MessageBoxTimeoutW(IN HWND hWnd, IN LPCWSTR lpText, IN LPCWSTR lpCaption, IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds); #ifdef UNICODE #define MessageBoxTimeout MessageBoxTimeoutW #else #define MessageBoxTimeout MessageBoxTimeoutA #endif #define MB_TIMEDOUT 32000 int MessageBoxTimeoutA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwMilliseconds) { static MSGBOXAAPI MsgBoxTOA = NULL; if (!MsgBoxTOA) { HMODULE hUser32 = GetModuleHandle(_T("user32.dll")); if (hUser32) { MsgBoxTOA = (MSGBOXAAPI)GetProcAddress(hUser32, "MessageBoxTimeoutA"); //fall through to 'if (MsgBoxTOA)...' } else { //stuff happened, add code to handle it here //(possibly just call MessageBox()) return 0; } } if (MsgBoxTOA) { return MsgBoxTOA(hWnd, lpText, lpCaption, uType, wLanguageId, dwMilliseconds); } return 0; } int MessageBoxTimeoutW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwMilliseconds) { static MSGBOXWAPI MsgBoxTOW = NULL; if (!MsgBoxTOW) { HMODULE hUser32 = GetModuleHandle(_T("user32.dll")); if (hUser32) { MsgBoxTOW = (MSGBOXWAPI)GetProcAddress(hUser32, "MessageBoxTimeoutW"); //fall through to 'if (MsgBoxTOW)...' } else { //stuff happened, add code to handle it here //(possibly just call MessageBox()) return 0; } } if (MsgBoxTOW) { return MsgBoxTOW(hWnd, lpText, lpCaption, uType, wLanguageId, dwMilliseconds); } return 0; } //End required definitions <--
按如下方式调用该函数
//you must load user32.dll before calling the function HMODULE hUser32 = LoadLibrary(_T("user32.dll")); if (hUser32) { int iRet = 0; UINT uiFlags = MB_OK|MB_SETFOREGROUND|MB_SYSTEMMODAL|MB_ICONINFORMATION; iRet = MessageBoxTimeout(NULL, _T("Test a timeout of 2 seconds."), _T("MessageBoxTimeout Test"), uiFlags, 0, 2000); //iRet will = 1 uiFlags = MB_YESNO|MB_SETFOREGROUND|MB_SYSTEMMODAL|MB_ICONINFORMATION; iRet = MessageBoxTimeout(NULL, _T("Test a timeout of 5 seconds."), _T("MessageBoxTimeout Test"), uiFlags, 0, 5000); //iRet will = MB_TIMEDOUT if no buttons pressed, button values otherwise //only unload user32.dll when you have no further need //for the MessageBoxTimeout function FreeLibrary(hUser32); }
该函数将返回一个整数值,要么是 MB_TIMEDOUT
值,表示达到超时时间并且消息框自动关闭,要么是用户点击的按钮所代表的值。请注意,当使用仅带有“确定”按钮的消息框(MB_OK
标志)时,返回值始终为 1。
提供的示例代码适用于 Visual Studio .NET 2003,但可以轻松地在其他编译器中使用。
关注点
你可能会想知道,是否有保证微软不会有一天删除此函数。坦白地说,没有,但是有趣的是,内部所有文档化的 MessageBox*
函数都调用 MessageBoxTimeout
API,并简单地将 0xFFFFFFFF 作为超时时间传递(非常长的时间),因此被删除的可能性很小。