在codeguru找到的一份源码,相比前面两个相比更是,更加严谨:
#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;
}
#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);
}
(另外,感谢徐艺波大佬在百忙之中提供无私的帮助,致敬!)