[英]WINAPI application closes when I press either ALT, why?
我之前練習過 winapi 應用程序,但從未遇到過這個問題。
我嘗試制作自定義 WindowProc 來覆蓋 WM_QUIT/WM_CLOSE/WM_DESTROY 消息的默認行為以不執行任何操作,但是當我按下 ALT 時 window 仍然關閉!
這是整個代碼:
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 時 window 不應該關閉,但確實如此。
您正在將message
字段與wParam
字段混合:
while (msg.wParam != WM_QUIT)
當您按下 ALT 時,window 會收到一條WM_KEYDOWN
消息,其wParam
是虛擬鍵碼。 碰巧 ALT 與WM_QUIT
(0x12) 的常量具有相同的 VK 代碼。
此外,您還在退出前翻譯和調度WM_QUIT
。 您可以通過使用適當的檢查進行單級縮進來處理這兩種情況:
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) && msg.message != WM_QUIT)
正如評論中所指出的,這更干凈GetMessage
:
while (GetMessage(&msg, nullptr, 0, 0) > 0)
您的代碼存在一些問題。
首先,您應該使用GetMessage()
而不是PeekMessage()
。 根本區別在於PeekMessage()
是非阻塞的,因此您的程序將使用 100% 的 CPU 運行該循環。
此外,由於內部循環可能會或可能不會連續遍歷多條消息,因此像您正在做的那樣檢查外部循環上的內容將是命中或未命中,並且不會檢查所有消息。 您應該檢查內部循環中的每條消息。
但在這種情況下,沒有必要,因為如果 Window 無論如何關閉,這個循環就會結束。 你做的這個檢查是沒有意義的。
您的代碼還有其他一些不一致之處, wc.hInstance
應該是hInstance
,這是您在WinMain()
中作為參數收到的那個。 無需 go 使用 API 查找此信息。
CreateWindow()
也應該再次接收hInstance
,因為它是倒數第二個參數,而不是nullptr
。
最后,正如克里斯的回答所指出的那樣,您應該在msg.message
而不是在msg.wParam
中尋找消息類型。
除此之外,這里沒有做“自定義 WindowProc”的地方。 如果你想做一個自定義的 WndProc,那么你應該將wc.lpfnWndProc
設置為你自己的 function 而不是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
,因為此消息僅在您的應用程序調用PostQuitMessage()
時才會發生。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.