首页 > 解决方案 > 使用模数来确定数字是否可以被变量整除

问题描述

我在使用 % 运算符时遇到问题。这很难解释,所以我先展示我的代码。

#include <windows.h>
const char ClassName[] = "WindowClass";
int divisible = 1;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:
        SetTimer(hwnd, 1, 50, NULL);
        break;
    case WM_TIMER:
    {
        if (divisible % 15 == 0) {
            MessageBox(hwnd, "a", "a", MB_ABORTRETRYIGNORE | MB_ICONASTERISK);
        }
        divisible++;
        break;
    }
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_SHIELD);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = ClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_SHIELD);

    RegisterClassEx(&wc);

    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        ClassName,
        "Tank Survival",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 820, 642,
        NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

所以发生的情况是,WM_TIMER 中的消息框在每次调用 WM_TIMER 时都会重复,尽管它应该只每 15 次调用 WM_TIMER 运行一次。任何帮助,将不胜感激。谢谢!

标签: c++winapi

解决方案


好吧,评论中已经提出了一些好的观点,但这里的基本问题是,当消息框在屏幕上时,Windows 会继续发送消息(包括 WM_TIMER 消息),因此您最终会在MessageBox每次定时器触发时递归调用(但是,因为这些都在另一个之上,所以你只能看到一个)。

解决此问题的一种方法是在屏幕上显示消息框时终止计时器,如下所示:

case WM_TIMER:
{
    if (divisible % 15 == 0) {
        KillTimer (hwnd, 1);
        MessageBox (hwnd, "a", "a", MB_ABORTRETRYIGNORE | MB_ICONASTERISK);
        SetTimer (hwnd, 1, 50, NULL);
    }
    divisible++;
    break;
}

但是您应该在更改代码之前对其进行调试,以便您完全了解发生了什么。


推荐阅读