⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timeoutmessagebox.cpp

📁 版本更新了一下
💻 CPP
字号:
// TimeOutMessageBox.cpp
// Found from http://www.codeguru.com/. Modified for Eraser - sami@tolvanen.com

// From http://www.codeguru.com/submission_guide.shtml :
//
// "While we are talking about copyrights, you retain copyright of
//  your article and code but by submitting it to CodeGuru you give it
//  permission to use it in a fair manner and also permit all developers
//  to freely use the code in their own applications - even if they are
//  commercial."

#include "stdafx.h"
#include "resource.h"
#include "windows.h"
#include <process.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;

static 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;
}

static 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)GetWindowLongPtr(hwnd, -21 /*GWL_USERDATA*/), hwnd,
                          uMsg, wParam, lParam);
}

static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
    if (lParam)
    {
        SetWindowLong(hwnd, -21 /*GWL_USERDATA*/, SetWindowLong(hwnd, -4 /*GWL_WNDPROC*/,
                      (LONG)MyWindowProc));
    }
    else
		SetWindowLong(hwnd, -4 /*GWL_WNDPROC*/, GetWindowLong(hwnd, -21 /*GWL_USERDATA*/));

    return TRUE;
}

static UINT _stdcall TimeoutMsgBox(LPVOID pParam)
{
    trMyData    *prMyData       = (trMyData *)pParam;
    UINT        uTime;
    UINT        uBlinkingTime   = prMyData->uBlinkingTime;
    UINT        uElapse;
    UINT        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, -21 /*GWL_USERDATA*/, SetWindowLong(hwndMsgBox,-4 /* GWL_WNDPROC*/, (long)MyWindowProc));
    EnumChildWindows(hwndMsgBox, EnumChildProc, TRUE);

    if (uBlinkingTime > prMyData->uElapse)
        uBlinkingTime = prMyData->uElapse;

    BOOL bAgain = TRUE;

    while (bAgain)
    {
        bAgain = FALSE;

        uElapse = prMyData->uElapse - uBlinkingTime;
        dWaitRetVal = WaitForSingleObject(prMyData->EventHandle, uElapse);

        if (dWaitRetVal == WAIT_TIMEOUT)
        {
            if (bUserIsHere)
            {
                bUserIsHere = FALSE;

                bAgain = TRUE;
                continue;
            }
            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);

                        bAgain = TRUE;
                        continue;
                    }

                    uTime -= uCaretBlinkTime;
                }
            }
        }
    }

    SetWindowLong(hwndMsgBox, -4 /*GWL_WNDPROC*/, GetWindowLong(hwndMsgBox, -21/*GWL_USERDATA*/));
    EnumChildWindows(hwndMsgBox, EnumChildProc, FALSE);

    if (dWaitRetVal == WAIT_TIMEOUT)
        EndDialog(hwndMsgBox, IDCLOSED_BY_TIMEOUT);

    return 0;
}

static 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);

    UINT uThreadID;
    HANDLE hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, TimeoutMsgBox,
        (LPVOID)&rMyData, 0, &uThreadID);

    if (hThreadHandle)
        CloseHandle(hThreadHandle);

    int Res = MessageBox(hWnd, lpText, lpCaption, uType);

    SetEvent(rMyData.EventHandle);
    CloseHandle(rMyData.EventHandle);

    return Res;
}

#define AFX_ELAPSE_TIME     15000
#define AFX_BLINKING_TIME   3000

int AFXAPI AfxTimeOutMessageBox(LPCTSTR lpszText, UINT nType)
{
    CWinApp *pApp   = AfxGetApp();
    int iResult     = 0;

    if (pApp != NULL)
    {
        iResult =
            MsgBoxWithTimeout(AfxGetMainWnd()->GetSafeHwnd(),
                             lpszText, pApp->m_pszAppName,
                             nType, AFX_ELAPSE_TIME, AFX_BLINKING_TIME);
    }

    return iResult;
}

int AFXAPI AfxTimeOutMessageBox(UINT nIDPrompt, UINT nType)
{
    CString string;

    try
    {
        if (!string.LoadString(nIDPrompt))
        {
            TRACE1("Error: failed to load message box prompt string 0x%04x.\n",
                nIDPrompt);
            ASSERT(FALSE);
        }

        return AfxTimeOutMessageBox(string, nType);
    }
    catch (...)
    {
        ASSERT(FALSE);
    }

    return -1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -