如何使用 SetTimer() 在 C++ 中创建一定数量的消息框?

How do I use SetTimer() to create certain number of message boxes after another in c++?

我正在努力做到这一点,当一个消息框打开时,另一个消息框会在几秒钟后打开,而无需任何用户输入(按 OK 按钮)。我希望旧的保持打开状态,但出现新的。我还希望能够使用 SetWindowsHookEx 并限制创建的消息框数量。我知道这使用函数 SetTimer() 并且需要某种 if 语句,其中当前的对话框数量等于限制并在达到该数量时停止。那么我该如何进行这项工作呢?我试图研究,但似乎没有任何效果。

我的尝试:

#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;

thread_local int MsgBox_X;
thread_local int MsgBox_Y;
thread_local int Limit = 10;

static LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_CREATEWND)
    {
        CBT_CREATEWND* s = (CBT_CREATEWND*)lParam;
        if (s->lpcs->hwndParent == NULL)
        {
            s->lpcs->x = MsgBox_X;
            s->lpcs->y = MsgBox_Y;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int MessageBoxPos(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, int X, int Y)
{
    HHOOK hHook = SetWindowsHookEx(WH_CBT, &CBTProc, NULL, GetCurrentThreadId());
    MsgBox_X = X;
    MsgBox_Y = Y;
    int result = MessageBox(hWnd, lpText, lpCaption, uType);
    if (hHook) UnhookWindowsHookEx(hHook);
    return result;
if (<# of dialogs> == Limit) {
    std::terminate()
    }
}

void _MessageBox()
{
    HWND HWND1;
    MessageBox(HWND1, TEXT("Message"), TEXT("MsgBox"), MB_ICONWARNING | MB_OK);
    SetTimer(HWND1, 
        TIMER1,
        2000,
        (TIMERPROC)NULL);
    case WM_TIMER:

        switch (wParam)
        {
        case TIMER1:
            MessageBoxPos(NULL, TEXT("Message 2"), TEXT("MsgBox 2"), MB_ICONWARNING | MB_OK, 50, 50);

            return 0;
        }
    }
}
int main()
{
    ShowWindow(::GetConsoleWindow(), SW_HIDE);
    _MessageBox();
}

您正在将 未初始化的 HWND 传递给 MessageBox()

此外,MessageBox()是一个阻塞函数,直到对话框关闭它才会退出,所以你需要在调用之前创建定时器MessageBox()。除非您使用 SetWindowsHookEx()SetWinEventHook() 挂钩对话框的创建,否则您可以在创建对话框的 HWND 时创建计时器,然后将 HWND 传递给 SetTimer().

此外,您处理 WM_TIMER 消息的语法完全错误。

也就是说,MessageBox() 显示模式对话框并运行自己的消息循环,因此您根本不需要手动处理 WM_TIMER。您可以为计时器分配一个回调,让模态循环为您调度回调事件。

试试像这样的东西:

#include <Windows.h>

thread_local int MsgBox_X;
thread_local int MsgBox_Y;
thread_local int NumMsgBoxes = 0;

static LRESULT CALLBACK CBTSetPosProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_CREATEWND)
    {
        CBT_CREATEWND* s = (CBT_CREATEWND*)lParam;
        if (s->lpcs->hwndParent == NULL)
        {
            s->lpcs->x = MsgBox_X;
            s->lpcs->y = MsgBox_Y;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int MessageBoxPos(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, int X, int Y)
{
    HHOOK hHook = SetWindowsHookEx(WH_CBT, &CBTSetPosProc, NULL, GetCurrentThreadId());
    MsgBox_X = X;
    MsgBox_Y = Y;
    int result = MessageBox(hWnd, lpText, lpCaption, uType);
    if (hHook) UnhookWindowsHookEx(hHook);
    return result;
}

static void CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD)
{
    if (NumMsgBoxes > 0)
    {
        --NumMsgBoxes;
        MessageBoxPos(NULL, TEXT("Message 2"), TEXT("MsgBox 2"), MB_ICONWARNING | MB_OK, 50, 50);
    }
}

void _MessageBox(int NumberOfMsgBoxes)
{
    NumMsgBoxes = NumberOfMsgBoxes;
    if (NumMsgBoxes > 0)
    {
        --NumMsgBoxes;
        UINT timer = SetTimer(NULL, 0, 2000, &TimerProc);
        if (timer) {
            MessageBox(NULL, TEXT("Message"), TEXT("MsgBox"), MB_ICONWARNING | MB_OK);
            KillTimer(NULL, timer);
        }
    }
}

int main()
{
    ShowWindow(GetConsoleWindow(), SW_HIDE);
    _MessageBox(5);
}

或者:

#include <Windows.h>

thread_local int MsgBox_X;
thread_local int MsgBox_Y;
thread_local int NumMsgBoxes = 0;

static LRESULT CALLBACK CBTSetPosProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_CREATEWND)
    {
        CBT_CREATEWND* s = (CBT_CREATEWND*)lParam;
        if (s->lpcs->hwndParent == NULL)
        {
            s->lpcs->x = MsgBox_X;
            s->lpcs->y = MsgBox_Y;
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int MessageBoxPos(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, int X, int Y)
{
    HHOOK hHook = SetWindowsHookEx(WH_CBT, &CBTSetPosProc, NULL, GetCurrentThreadId());
    MsgBox_X = X;
    MsgBox_Y = Y;
    int result = MessageBox(hWnd, lpText, lpCaption, uType);
    if (hHook) UnhookWindowsHookEx(hHook);
    return result;
}

static void CALLBACK TimerProc(HWND hwnd, UINT message, UINT_PTR idTimer, DWORD dwTime)
{
    KillTimer(hwnd, idTimer);
    if (NumMsgBoxes > 0)
        MessageBoxPos(NULL, TEXT("Message 2"), TEXT("MsgBox 2"), MB_ICONWARNING | MB_OK, 50, 50);
}

static LRESULT CALLBACK CBTSetTimerProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HCBT_CREATEWND)
    {
        CBT_CREATEWND* s = (CBT_CREATEWND*)lParam;
        if (s->lpcs->hwndParent == NULL)
        {
            if (--NumMsgBoxes > 0)
                SetTimer((HWND)wParam, 1, 2000, &TimerProc);
        }
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

void _MessageBox(int NumberOfMsgBoxes)
{
    HHOOK hHook = SetWindowsHookEx(WH_CBT, &CBTSetTimerProc, NULL, GetCurrentThreadId());
    NumMsgBoxes = NumberOfMsgBoxes;
    if (NumMsgBoxes > 0)
        MessageBox(NULL, TEXT("Message"), TEXT("MsgBox"), MB_ICONWARNING | MB_OK);
    if (hHook) UnhookWindowsHookEx(hHook);
}

int main()
{
    ShowWindow(GetConsoleWindow(), SW_HIDE);
    _MessageBox(5);
}