当我按ALT时,WINAPI应用程序关闭,为什么?

时间:2019-10-19 17:42:05

标签: c++ windows winapi winmain

我以前曾经练习过winapi应用,但从未遇到过这个问题。

我尝试制作一个自定义WindowProc来替代WM_QUIT / WM_CLOSE / WM_DESTROY消息的默认行为,但是什么也不做,但是当我按ALT时,窗口仍然关闭!

这是完整的代码:

int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
{
    const LPCSTR className = "Class name";
    WNDCLASS wc = {};
    wc.style = 0;
    wc.lpfnWndProc = DefWindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = GetModuleHandle(nullptr);
    wc.hIcon = nullptr;
    wc.hCursor = nullptr;
    wc.hbrBackground = nullptr;
    wc.lpszMenuName = nullptr;
    wc.lpszClassName = className;

    RegisterClass(&wc);
    HWND window = CreateWindow(className, "Title", WS_OVERLAPPEDWINDOW, 200, 200, 600, 400, nullptr, nullptr, nullptr, nullptr);

    ShowWindow(window, SW_SHOW);

    MSG msg = {};

    while (msg.wParam != WM_QUIT)
    {
        while(PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return msg.wParam;
}

我相信按ALT时不应关闭窗口,但确实会关闭。

2 个答案:

答案 0 :(得分:4)

您正在将select get_percentageed_reward(random()), count(*) from generate_series(1, 100000) group by 1 order by 1 get_percentageed_reward | count -------------------------+------- A | 20008 B | 30165 C | 49827 (3 rows) 字段与message字段混合:

wParam

当您按ALT时,窗口会收到一条while (msg.wParam != WM_QUIT) 是虚拟键码的WM_KEYDOWN消息。碰巧ALT与wParam(0x12)的常量具有相同的VK代码。

此外,您还将在退出之前翻译和分派WM_QUIT。您可以通过单层缩进并进行适当的检查来处理这两种情况:

WM_QUIT

正如评论中指出的那样,使用while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) && msg.message != WM_QUIT) 可以使操作更简洁:

GetMessage

答案 1 :(得分:3)

您的代码有一些问题。

首先,您应该使用GetMessage()而不是PeekMessage()。根本区别在于PeekMessage()是非阻塞的,因此您的程序将使用100%运行该循环的CPU。

此外,由于内部循环可能会或可能不会连续遍历多个消息,因此像您一样检查外部循环上的内容会很容易出错,也不会检查所有消息。您应该改为检查内部循环中的每条消息。

但是在这种情况下,这是没有必要的,因为无论如何关闭Window,此循环都会结束。您正在进行的检查毫无意义。

您的代码还有其他一些不一致之处,wc.hInstance应该是hInstance,这是您在WinMain()中作为参数收到的。无需去使用API​​查找这些信息。

另外,CreateWindow()应该再次收到hInstance,因为它是倒数第二个参数,而不是nullptr

最后,如chris' answer所指出的,您应该在msg.message中而不是在msg.wParam中查找消息类型。

除此之外,这里也不是要做“自定义WindowProc”的地方。如果要执行自定义WndProc,则应将wc.lpfnWndProc设置为自己的函数而不是DefWindowProc,然后可以在其中定义Window的自定义行为。

例如:

LRESULT CALLBACK MyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CLOSE:
    case WM_DESTROY:
        // do nothing
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

请注意,无需测试WM_QUIT,因为仅当您的应用程序调用{​​{1}}时才会出现此消息。