codeguru找到的一份源码,相比前面两个相比更是,更加严谨:

// // TOMsgBox.h // #include <windows.h> #include <process.h> #include <tchar.h> #define TIME_TO_APPEAR 1000 #define IDCLOSED_BY_TIMEOUT 50 static HWND hwndMsgBox = NULL; static BOOL bUserIsHere = FALSE; typedef struct { DWORD CurrentThreadID; HANDLE EventHandle; UINT uElapse; UINT uBlinkingTime; } trMyData; BOOL CALLBACK FindMsgBox(HWND hwnd, LPARAM lParam) { TCHAR ClassNameBuf[256]; BOOL RetVal = TRUE; int Ret = GetClassName(hwnd, ClassNameBuf, 100); if (!_tcscmp(ClassNameBuf, _T("#32770"))) { hwndMsgBox = hwnd; RetVal = FALSE; } return RetVal; } LRESULT CALLBACK MyWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if ( (WM_KEYFIRST <= uMsg && uMsg <= WM_KEYLAST) || (WM_MOUSEFIRST <= uMsg && uMsg <= WM_MOUSELAST) || (WM_NCMOUSEMOVE <= uMsg && uMsg <= WM_NCMBUTTONDBLCLK) ) bUserIsHere = TRUE; return CallWindowProc((WNDPROC)GetWindowLong(hwnd, GWL_USERDATA), hwnd, uMsg, wParam, lParam); } BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) { if (lParam) SetWindowLong(hwnd, GWL_USERDATA, SetWindowLong(hwnd, GWL_WNDPROC, (long)MyWindowProc)); else SetWindowLong(hwnd, GWL_WNDPROC, GetWindowLong(hwnd, GWL_USERDATA)); return TRUE; } unsigned int _stdcall TimeoutMsgBox(void *pParam) { trMyData *prMyData = (trMyData *)pParam; UINT uTime, uBlinkingTime = prMyData->uBlinkingTime; UINT uElapse, uCaretBlinkTime; DWORD dWaitRetVal; if (prMyData->uElapse <= TIME_TO_APPEAR) return 0; prMyData->uElapse-= TIME_TO_APPEAR; //Give time for MessageBox to appear Sleep(TIME_TO_APPEAR); EnumThreadWindows(prMyData->CurrentThreadID, FindMsgBox, NULL); if (!hwndMsgBox) return 0; SetWindowLong(hwndMsgBox, GWL_USERDATA, SetWindowLong(hwndMsgBox, GWL_WNDPROC, (long)MyWindowProc)); EnumChildWindows(hwndMsgBox, EnumChildProc, TRUE); if (uBlinkingTime > prMyData->uElapse) uBlinkingTime = prMyData->uElapse; _Again: uElapse = prMyData->uElapse - uBlinkingTime; dWaitRetVal = WaitForSingleObject(prMyData->EventHandle, uElapse); if (dWaitRetVal == WAIT_TIMEOUT) { if (bUserIsHere) { bUserIsHere = FALSE; goto _Again; } if ((int)uBlinkingTime > 0) { SetForegroundWindow(hwndMsgBox); uCaretBlinkTime = GetCaretBlinkTime(); uTime = uBlinkingTime; while ((int)uTime > 0) { FlashWindow(hwndMsgBox, TRUE); dWaitRetVal = WaitForSingleObject(prMyData->EventHandle, uCaretBlinkTime); if (dWaitRetVal != WAIT_TIMEOUT) break; if (bUserIsHere) { bUserIsHere = FALSE; SendMessage(hwndMsgBox, WM_NCACTIVATE, (WPARAM)(GetForegroundWindow() == hwndMsgBox), 0); goto _Again; } uTime-= uCaretBlinkTime; } } } SetWindowLong(hwndMsgBox, GWL_WNDPROC, GetWindowLong(hwndMsgBox, GWL_USERDATA)); EnumChildWindows(hwndMsgBox, EnumChildProc, FALSE); if (dWaitRetVal == WAIT_TIMEOUT) EndDialog(hwndMsgBox, IDCLOSED_BY_TIMEOUT); return 0; } int MsgBoxWithTimeout(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, UINT uElapse, UINT uBlinkingTime) { trMyData rMyData; rMyData.CurrentThreadID = GetCurrentThreadId(); rMyData.uElapse = uElapse; rMyData.uBlinkingTime = uBlinkingTime; rMyData.EventHandle = CreateEvent(NULL, TRUE, FALSE, NULL); unsigned int uThreadID; HANDLE hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, TimeoutMsgBox, (void*)&rMyData, 0, &uThreadID); if (hThreadHandle) CloseHandle(hThreadHandle); int Res = MessageBox(hWnd, lpText, lpCaption, uType); SetEvent(rMyData.EventHandle); CloseHandle(rMyData.EventHandle); return Res; }

 

// // main.cpp // #include "TOMsgBox.h" void main() { int nRes = MsgBoxWithTimeout(NULL, "If there is no user interaction,/n this message box should close in 6 seconds", "Message Box with Timeout", MB_OK, 6000, 3000); }

 

 (另外,感谢徐艺波大佬在百忙之中提供无私的帮助,致敬!)