我以前曾经练习过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时不应关闭窗口,但确实会关闭。
答案 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}}时才会出现此消息。