Как обрабатывать сообщения из нескольких окон - PullRequest
0 голосов
/ 26 апреля 2019

Итак, у меня работает несколько окон, и я хотел бы обработать сообщения для всех из них, чтобы они не зависали.До сих пор я пробовал несколько вещей:

1) Превращение в поток (глупо, но я пытался):

auto ProcessThread(
    std::vector<HWND> Windows
) -> void
{
    for (;;)
    {
        MSG Msg1 = decltype(Msg1){0x00};
        MSG Msg2 = decltype(Msg2){0x00};

        GetMessageW(&Msg1, Windows.at(0), 0, 0);
        GetMessageW(&Msg2, Windows.at(1), 0, 0);

        TranslateMessage(&Msg1);
        TranslateMessage(&Msg2);

        DispatchMessageW(&Msg1);
        DispatchMessageW(&Msg2);
    }

    return;
}

...

    std::vector<HWND> Windows = { lpScreen.m_WindowHandle, lpPopup.m_WindowHandle };
    HANDLE hThread = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(ProcessThread),
        &Windows, 0, nullptr);

    while (WAIT_TIMEOUT == WaitForSingleObject(hThread, 1000)) {}

    CloseHandle(hThread);

2) Просто набивать второй цикл сообщений

    MSG Msg1 = decltype(Msg1){0x00};
    MSG Msg2 = decltype(Msg2){0x00};

    while (GetMessageW(&Msg1, Hwnd1, 0, 0) && GetMessageW(&Msg2, Hwnd2, 0, 0))
    {
        TranslateMessage(&Msg1);
        TranslateMessage(&Msg2);

        DispatchMessageW(&Msg1);
        DispatchMessageW(&Msg2);
    }

3) Другие варианты второго


Пока все они сделали мои окна неподвижными и дали мне этот курсор загрузки.

Есть идеи?

1 Ответ

0 голосов
/ 27 апреля 2019

Есть несколько проблем с вашим кодом:

  1. ProcessThread() объявляется совершенно неправильным для CreateThread(), и компилятор обычно кричит вам об этом, но вы используетеошибочное приведение типа для успокоения компилятора вместо исправления ошибки.Таким образом, ProcessThread() не сможет правильно получить vector во время выполнения.Вместо этого ProcessThread() должно выглядеть так:

    DWORD WINAPI ProcessThread(LPVOID lpParam)
    {
        std::vector<HWND> *Windows = static_cast<std::vector<HWND>*>(lpParam);
        ...
        return 0;
    }
    
    ...
    
    HANDLE hThread = CreateThread(..., &ProcessThread, &Windows, ...);
    
  2. цикл сообщений в вашей ветке неверен.Вызывайте GetMessage() ONCE для каждой итерации цикла и вообще не указывайте фильтрацию HWND (см. Опасности фильтрации сообщений окна ).Следующее доступное сообщение будет извлечено из очереди сообщений, которую затем можно будет передать на DispatchMessage(), чтобы отправить сообщение на соответствующий WndProc для дальнейшей обработки.

    DWORD WINAPI ProcessThread(LPVOID lpParam)
    {
        std::vector<HWND> *Windows = static_cast<std::vector<HWND>*>(lpParam);
        MSG Msg;
    
        while (GetMessageW(&Msg, 0, 0, 0) > 0)
        {
            TranslateMessage(&Msg);
            DispatchMessageW(&Msg);
        }
    
        return 0;
    }
    
  3. Вы создаете рабочий поток, просто чтобы дождаться его завершения, не делая ничего другого параллельно.Это делает рабочий поток совершенно бесполезным.Вам нужно избавиться от этого потока, особенно если учесть, что ...

  4. ... вы запускаете цикл сообщений в отдельном потоке, а не в том, который создает окна.Вы не можете сделать это вообще!Окно имеет сродство к потоку .(Get|Peek)Message() принимает сообщения только для окон, связанных с вызывающим потоком, поэтому только поток, создающий окно, может получать сообщения для этого окна.

Вы слишком продуманны при разработке кода.Вы можете значительно упростить это до следующего:

std::vector<HWND> Windows = { lpScreen.m_WindowHandle, lpPopup.m_WindowHandle };
MSG Msg;

while (GetMessageW(&Msg, 0, 0, 0) > 0)
{
    TranslateMessage(&Msg);
    DispatchMessageW(&Msg);
}

Если lpScreen.m_WindowHandle и lpPopup.m_WindowHandle являются единственными окнами, доступными в вызывающем потоке, то вам даже не нужен vector вообще!

Однако, если вы заинтересованы в обработке сообщений только для определенных окон, это представляет проблему.Приведенный выше код будет получать сообщения для ВСЕХ окон в вызывающем потоке.Если это не то, что вы хотите, то вы МОЖЕТЕ (но не должны!) Фильтровать определенные окна в vector, например:

std::vector<HWND> Windows = { lpScreen.m_WindowHandle, lpPopup.m_WindowHandle };
MSG Msg;

for(auto h : Windows)
{
    while (PeekMessageW(&Msg, h, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&Msg);
        DispatchMessageW(&Msg);
    }
}

Но это может привести к голоданию сообщений для других окон,если вы не будете осторожны.

В противном случае вам просто придется использовать отдельный поток для СОЗДАНИЯ И ОБРАБОТКИ только интересующих вас окон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...