分开 window 消息泵和接收 WM_QUIT
Separate window message pumps and receiving WM_QUIT
我正在尝试为我的项目创建独立的 window 包装器 类。它主要工作但无法弄清楚如何在我的主消息泵中获取 WM_QUIT 。为了学习Windows,我不想为此使用其他库。
这是正在发生的事情的一个简单示例。
#include <iostream>
#include <Windows.h>
void TestPump()
{
MSG msg = { 0 };
PostQuitMessage(0);
std::cout << "Posted WM_QUIT" << std::endl;
while (true)
{
BOOL result = PeekMessage(&msg, (HWND) -1, 0, 0, PM_REMOVE);
std::cout << "PeekMessage returned " << result << std::endl;
if (result == 0)
break;
if (WM_QUIT == msg.message)
std::cout << "got WM_QUIT" << std::endl;
}
}
void MakeWindow()
{
auto hwnd = CreateWindowEx(0, "Button", "dummy", 0, 0, 0, 32, 32, NULL, NULL, NULL, NULL);
std::cout << std::endl << "Created Window" << std::endl << std::endl;
}
int main()
{
TestPump();
MakeWindow();
TestPump();
std::cin.get();
return EXIT_SUCCESS;
}
PeekMessage 文档在此处:https://msdn.microsoft.com/en-us/library/windows/desktop/ms644943(v=vs.85).aspx
我还没有找到任何使用 -1 HWND 过滤器的例子,但是 MSDN 说它会收到 HWND 为 NULL 的线程消息(我已经检查过 WM_QUIT),我相信 PostQuitMessage 与 WM_QUIT.
仅当我创建 Window.
时才会出现此问题
有没有我哪里做错了,或者有更好的方法吗?
这似乎是一个有趣的案例,所以我创建了一个 mcve,尽管我正在努力解释这种行为:
#include <Windows.h>
#include <CommCtrl.h>
#include <iostream>
#include <cassert>
void
Create_ThreadMessagePump(void)
{
::MSG msg;
::PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
::std::wcout << L"initialized thread message pump" << ::std::endl;
}
void
Create_Window(void)
{
auto const hwnd{::CreateWindowExW(0, WC_STATICW, L"dummy window", 0, 0, 0, 32, 32, NULL, NULL, NULL, NULL)};
(void) hwnd; // not used
assert(NULL != hwnd);
::std::wcout << L"created window" << ::std::endl;
}
void
Test_QuitMessageExtraction(void)
{
::PostQuitMessage(0);
::std::wcout << L"posted WM_QUIT" << ::std::endl;
for(;;)
{
::MSG msg;
auto const result{::PeekMessageW(&msg, (HWND) -1, 0, 0, PM_REMOVE)};
::std::wcout << L"PeekMessageW returned " << result << ::std::endl;
if(0 == result)
{
::std::wcout << L"no more messages to peek" << ::std::endl;
break;
}
if(WM_QUIT == msg.message)
{
::std::wcout << L"got WM_QUIT" << ::std::endl;
}
}
}
int
main()
{
//Create_ThreadMessagePump(); // does not change anything
Test_QuitMessageExtraction();
Create_Window();
Test_QuitMessageExtraction();
system("pause");
return(0);
}
输出:
posted WM_QUIT
PeekMessageW returned 1
got WM_QUIT
PeekMessageW returned 0
no more messages to peek
created window
posted WM_QUIT
PeekMessageW returned 0
no more messages to peek
问题似乎出在 WM_QUIT
和 PostQuitMessage()
的操作方式上。您可以在这里找到信息:
Why is there a special PostQuitMessage function?.
简而言之,当队列非空时,WM_QUIT
消息将不会被接收。即使您使用 -1 HWND
过滤掉其他消息,队列仍然是非空的,因此不会返回 WM_QUIT
。创建 window 会导致创建多个 HWND。
我正在尝试为我的项目创建独立的 window 包装器 类。它主要工作但无法弄清楚如何在我的主消息泵中获取 WM_QUIT 。为了学习Windows,我不想为此使用其他库。
这是正在发生的事情的一个简单示例。
#include <iostream>
#include <Windows.h>
void TestPump()
{
MSG msg = { 0 };
PostQuitMessage(0);
std::cout << "Posted WM_QUIT" << std::endl;
while (true)
{
BOOL result = PeekMessage(&msg, (HWND) -1, 0, 0, PM_REMOVE);
std::cout << "PeekMessage returned " << result << std::endl;
if (result == 0)
break;
if (WM_QUIT == msg.message)
std::cout << "got WM_QUIT" << std::endl;
}
}
void MakeWindow()
{
auto hwnd = CreateWindowEx(0, "Button", "dummy", 0, 0, 0, 32, 32, NULL, NULL, NULL, NULL);
std::cout << std::endl << "Created Window" << std::endl << std::endl;
}
int main()
{
TestPump();
MakeWindow();
TestPump();
std::cin.get();
return EXIT_SUCCESS;
}
PeekMessage 文档在此处:https://msdn.microsoft.com/en-us/library/windows/desktop/ms644943(v=vs.85).aspx
我还没有找到任何使用 -1 HWND 过滤器的例子,但是 MSDN 说它会收到 HWND 为 NULL 的线程消息(我已经检查过 WM_QUIT),我相信 PostQuitMessage 与 WM_QUIT.
仅当我创建 Window.
时才会出现此问题有没有我哪里做错了,或者有更好的方法吗?
这似乎是一个有趣的案例,所以我创建了一个 mcve,尽管我正在努力解释这种行为:
#include <Windows.h>
#include <CommCtrl.h>
#include <iostream>
#include <cassert>
void
Create_ThreadMessagePump(void)
{
::MSG msg;
::PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
::std::wcout << L"initialized thread message pump" << ::std::endl;
}
void
Create_Window(void)
{
auto const hwnd{::CreateWindowExW(0, WC_STATICW, L"dummy window", 0, 0, 0, 32, 32, NULL, NULL, NULL, NULL)};
(void) hwnd; // not used
assert(NULL != hwnd);
::std::wcout << L"created window" << ::std::endl;
}
void
Test_QuitMessageExtraction(void)
{
::PostQuitMessage(0);
::std::wcout << L"posted WM_QUIT" << ::std::endl;
for(;;)
{
::MSG msg;
auto const result{::PeekMessageW(&msg, (HWND) -1, 0, 0, PM_REMOVE)};
::std::wcout << L"PeekMessageW returned " << result << ::std::endl;
if(0 == result)
{
::std::wcout << L"no more messages to peek" << ::std::endl;
break;
}
if(WM_QUIT == msg.message)
{
::std::wcout << L"got WM_QUIT" << ::std::endl;
}
}
}
int
main()
{
//Create_ThreadMessagePump(); // does not change anything
Test_QuitMessageExtraction();
Create_Window();
Test_QuitMessageExtraction();
system("pause");
return(0);
}
输出:
posted WM_QUIT
PeekMessageW returned 1
got WM_QUIT
PeekMessageW returned 0
no more messages to peek
created window
posted WM_QUIT
PeekMessageW returned 0
no more messages to peek
问题似乎出在 WM_QUIT
和 PostQuitMessage()
的操作方式上。您可以在这里找到信息:
Why is there a special PostQuitMessage function?.
简而言之,当队列非空时,WM_QUIT
消息将不会被接收。即使您使用 -1 HWND
过滤掉其他消息,队列仍然是非空的,因此不会返回 WM_QUIT
。创建 window 会导致创建多个 HWND。