简体   繁体   中英

WINAPI application closes when I press either ALT, why?

I had practised winapi apps before, but never got this problem.

I have tried making a custom WindowProc to override default behaviour for WM_QUIT/WM_CLOSE/WM_DESTROY messages to do nothing, but the window still closes when I press ALT!

This is the entire code:

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

I believe the window shouldn't close when I press ALT, but it does.

You're mixing the message field with the wParam field:

while (msg.wParam != WM_QUIT)

When you press ALT, the window receives a WM_KEYDOWN message whose wParam is the virtual keycode. It so happens that ALT has the same VK code as the constant for WM_QUIT (0x12).

In addition, you're also translating and dispatching WM_QUIT before quitting. You can deal with both of these by having a single level of indentation with an appropriate check:

while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) && msg.message != WM_QUIT)

As pointed out in the comment, this is cleaner with GetMessage :

while (GetMessage(&msg, nullptr, 0, 0) > 0)

There are a few problems with your code.

First, you should be using GetMessage() and not PeekMessage() . The fundamental difference is that PeekMessage() is non-blocking, and therefore your program will use 100% of a CPU running that loop.

Also, because the inner loop may or may not loop through multiple messages in a row, checking things on the outer loop like you're doing will be a hit or miss and won't check all messages. You should be checking every message in the inner loop instead.

But in this case it's not necessary since this loop will end if the Window is closed anyway. This check you're doing is pointless.

There are a few other inconsistencies with your code, wc.hInstance should be hInstance , that one you received as parameter in WinMain() . There's no need to go looking for this information using APIs.

Also CreateWindow() should receive hInstance again as it's second to last parameter, not nullptr .

And finally as pointed out by chris' answer , you should be looking for the message type in msg.message and not in msg.wParam .

In addition to all that, this is no place to do a "custom WindowProc". If you want to do a custom WndProc then you should set wc.lpfnWndProc to your own function instead of DefWindowProc , and there you can define custom behavior to your Window.

For example:

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

Note there's no need to test WM_QUIT as this message will only happen if your application calls PostQuitMessage() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM