///////////////////////////////////////////////////////////////////////////////
// Util_MessageBoxEx()
//
// Windows message box with an optional timeout (0=wait forever)
///////////////////////////////////////////////////////////////////////////////
int Util_MessageBoxEx(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, UINT uTimeout)
{
MsgBoxExData MyData;
unsigned int uThreadID;
HANDLE hThreadHandle = NULL;
// Reset the timed out flag
g_bMsgBoxTimedOut = false;
if (uTimeout)
{
g_bMsgBoxThreadEnabled = true;
MyData.CurrentThreadID = GetCurrentThreadId();
MyData.dwTimeout = (DWORD)uTimeout;
hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, Util_TimeoutMsgBoxThread, (void*)&MyData, 0, &uThreadID);
}
// Run the windows message box - the spawned thread will force it to close if it times out
int Res = MessageBox(hWnd, lpText, lpCaption, uType);
if (hThreadHandle)
{
g_bMsgBoxThreadEnabled = false; // Signal thread to terminate (if not already)
WaitForSingleObject(hThreadHandle, INFINITE);
CloseHandle(hThreadHandle);
}
if (g_bMsgBoxTimedOut == true)
return -1; // Timed out
else
return Res;
}
unsigned int _stdcall Util_TimeoutMsgBoxThread(void *pParam)
{
MsgBoxExData *pMyData = (MsgBoxExData *)pParam;
DWORD dwStart, dwDiff, dwCur;
// Get the current time, and close the message box after the timeout has been
// exceeded - check every 10ms to avoid CPU load
dwStart = timeGetTime();
for (;;)
{
if (g_bMsgBoxThreadEnabled == false)
return 0; // Caller requested close
// Get current time in ms
dwCur = timeGetTime();
if (dwCur < dwStart)
dwDiff = (UINT_MAX - dwStart) + dwCur; // timer wraps at 2^32
else
dwDiff = dwCur - dwStart;
// Timer elapsed?
if (dwDiff >= pMyData->dwTimeout)
break;
else
Sleep(10);
}
// Find and close the msgbox
g_hwndMsgBox = NULL;
EnumThreadWindows(pMyData->CurrentThreadID, Util_FindMsgBoxProc, 0);
if (g_hwndMsgBox == NULL)
return 0; // MsgBox doesn't exist, just exit
// Signal the timeout
g_bMsgBoxTimedOut = true;
// End the MessageBox with our special message
EndDialog(g_hwndMsgBox, 1); // Id 1 works no matter what buttons are used
return 0;
}
BOOL CALLBACK Util_FindMsgBoxProc(HWND hwnd, LPARAM lParam)
{
TCHAR szClassname[256];
BOOL RetVal = TRUE;
int nRes = GetClassName(hwnd, szClassname, 256);
if (!_tcscmp(szClassname, TEXT("#32770")) ) // Class name for a MessageBox window
{
g_hwndMsgBox = hwnd;
RetVal = FALSE;
}
return RetVal;
}
|