Отдельное окно сообщения насосов и получения WM_QUIT

Я пытаюсь создать независимые классы окна-оболочки для моего проекта. Это в основном работает, но не могу понять, как получить 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.

Проблема возникает только при создании окна.

Есть ли что-то, что я делаю не так, или есть лучшие методы?

0

Решение

Это кажется интересным случаем, поэтому я создал 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
0

Другие решения

Кажется, проблема в том, как WM_QUIT а также PostQuitMessage() работает. Вы можете найти информацию здесь:

Почему существует специальная функция PostQuitMessage?.

Короче говоря, WM_QUIT сообщение не будет получено, пока очередь не пуста. Даже если вы отфильтровываете другие сообщения, используя -1 HWND, очередь все еще не пуста, и, таким образом, WM_QUIT не возвращается Создание окна приводит к созданию нескольких HWND.

0

По вопросам рекламы [email protected]