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

发布于 2025-01-11 10:12:43 字数 1718 浏览 1 评论 0原文

我试图做到这一点,以便当一个消息框打开时,另一个消息框会在几秒钟后打开,而无需任何用户输入(按“确定”按钮)。我希望旧的保持开放,但新的出现。我还希望能够使用 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();
}

I am trying to make it so when a messagebox opens another one opens a couple seconds later without any user input (pressing the OK button). I want the old one to stay open, but a new one to appear. I also want to be able to use SetWindowsHookEx and set a limit on how many message boxes are created. I know this uses the function SetTimer() and needs some kind of if statement with the current number of dialogs that equal the limit and stop when the number is reached. So how do I make this work? I tried to research, but nothing seemed to work.

My attempt:

#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();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

窗影残 2025-01-18 10:12:44

您正在将未初始化 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);
}

You are passing an uninitialized HWND to MessageBox().

Also, MessageBox() is a blocking function, it doesn't exit until the dialog is closed, so you need to create the timer before you call MessageBox(). Unless you use SetWindowsHookEx() or SetWinEventHook() to hook the creation of the dialog, then you can create the timer when the dialog's HWND is created, and you pass that HWND to SetTimer().

Also, your syntax to handle the WM_TIMER message is just plain wrong.

That being said, MessageBox() displays a modal dialog and runs its own message loop, so you don't need to handle WM_TIMER manually at all. You can assign a callback to the timer, and let the modal loop dispatch the callback events for you.

Try something more like this:

#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);
}

Alternatively:

#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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文