MessageBoxTimeout API






4.84/5 (27 votes)
An article on using the non documented MessageBoxTimeout API.
Introduction
For reasons unknown, Microsoft has never documented the
MessageBoxTimeout
API located in user32.dll, so here it is
for those seeking a Message Box that times out and auto closes if the user does
not respond to it first.
Using the code
The code is usable for both UNICODE and MBCS, simply add the following to a source (cpp) file:
#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 <--
Call the function as follows:
//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); }
The function will return an integer value of either a
MB_TIMEDOUT
value indicating the timeout period was reached and the
Message Box auto closed, or a value representing the button the user clicked.
Note that when a Message Box with only an OK button (MB_OK
Flag) is
used, the return value is always 1.
The sample code provided is for Visual Studio .NET 2003 but can easily be used in other compilers.
Points of Interest
You may be thinking what reassurances exist that someday Microsoft may remove
this function. In all honesty, there are none, however, it's interesting to note
that internally, all the documented MessageBox*
functions call the
MessageBoxTimeout
API and simply pass 0xFFFFFFFF as the timeout
period (a very long time), so the probability of it being removed is
minimal.