Обрабатывать остановку табуляции с помощью DispatchMessage() без блокировки потока в цикле сообщений?

У меня есть функция экспорта OpenUI() в DLL для представления пользовательского интерфейса, которая создает немодальный основной диалог, а также имеет немодальный дочерний диалог.

Я вызываю функцию экспорта OpenUI() из отдельной DLL, которая является моим контроллером.

Как я могу выполнить больше кода после вызова функции, если цикл обработки сообщений в OpenUI() предотвращает возврат функции, если диалоговое окно не закрыто? Я не могу удалить цикл сообщений, потому что без него не будет работать табуляция.

Мне нужно, чтобы экспорт функции возвращался сразу после выполнения, поэтому я не могу использовать модальный диалог. Создание подпотока также не вариант, потому что это вызвало проблемы в моем приложении.

Любая помощь высоко ценится. Спасибо.

Псевдокод для DLL моего контроллера

 typedef int(*DLL_OPENUI)();
    int func()
    {
        HINSTANCE hinst_dll = LoadLibrary(dll_path);
        DLL_OPENUI DllOpenUI = (DLL_OPENUI)GetProcAddress(hinst_dll, "OpenUI");
        int ret = DllOpenUI();

        //...execute more code here

        return ret;
    }

Псевдокод для DLL моего пользовательского интерфейса

__declspec(dllexport) OpenUI()
{
    hwnd_main = CreateDialog(hinst, IDD_MAIN, MainDlgProc);
    ShowWindow(hwnd_main, SW_SHOW);

    MSG msg;
    while ((GetMessage(&msg, NULL, 0, 0) > 0))
    {
        if (!IsDialogMessage(hwnd, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return 0;
}

LRESULT CALLBACK  MainDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message) 
    {
        case WM_INITDIALOG:
        OnInitDialog();
        break;
    }
}

void OnInitDialog()
{
    CreateDialog(hinst, IDD_NAV_PANE, hwnd_main, NavPaneProc);
    CreateDialog(hinst, IDD_NAV_TABS, hwnd_main, NavTabsProc);
    CreateDialog(hinst, IDD_TAB_1, hwnd_main, TabOneProc);
    CreateDialog(hinst, IDD_TAB_2, hwnd_main, TabTwoProc);
    CreateDialog(hinst, IDD_TAB_3, hwnd_main, TabThreeProc);
    CreateDialog(hinst, IDD_DETAILS_PANE_BG, hwnd_main, BackgroundProc);
    CreateDialog(hinst, IDD_DETAILS_PANE, hwnd_main, DetailsPaneProc);

    //...execute more code below
}

person Marss    schedule 31.10.2018    source источник
comment
Пример кода говорит тысячу слов   -  person paddy    schedule 31.10.2018
comment
Установить хук с SetWindowsHookEx, вызвать из него IsDialogMessage.   -  person Igor Tandetnik    schedule 31.10.2018
comment
Большинство фреймворков, предлагающих немодальные диалоги, имеют своего рода вызов сообщения PreHandle, который потребители должны вызывать из своего цикла сообщений.   -  person Chris Becke    schedule 31.10.2018
comment
@падди Прости. Я отредактировал свой пост и добавил псевдокод   -  person Marss    schedule 31.10.2018
comment
Экспорт функции должен возвращаться сразу после выполнения экспорта функции, поэтому я решил не включать цикл обработки сообщений.   -  person Marss    schedule 31.10.2018
comment
Вы спрашиваете о предлагаемом решении, а не о реальной проблеме, которую пытаетесь решить. Поток, которому принадлежат окна, естественно, должен отправлять сообщения. Спрос на способ отправки сообщений без отправки сообщений не даст вам ответа. Первый шаг к решению — ознакомиться с анатомией приложения Windows. Программирование Windows®, пятое издание Петцольда научит вас .   -  person IInspectable    schedule 31.10.2018
comment
@IInspectable Я понимаю. Я перефразировал свой вопрос для лучшего понимания проблемы   -  person Marss    schedule 05.11.2018


Ответы (1)


У вас должна быть активная петля сообщений, от этого никуда не деться. Один из способов сделать это — создать одну новую функцию, которая будет PeekMessage выполнять код цикла только один раз. PeekMessage возвращает ненулевое значение, если последующий вызов GetMessage на самом деле получит сообщение, а не заблокирует его. ProcessOneMessage может выглядеть примерно так:

BOOL ProcessOneMessage(HWND hwnd)
{
    MSG msg;
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
       if (msg.message == WM_QUIT)
          return TRUE;

       TranslateMessage(&msg);
       DispatchMessage(&msg);
    }

    return FALSE;
}

Итак, в вашем основном коде вы должны часто вызывать эту функцию (раз в 10 мс должно быть хорошо). Что бы ни делал код, он должен вызывать функцию раз в 10 мс. У вас будет живое окно, и вы одновременно запустите свой код. Но как только функция вернет TRUE, окно будет закрыто, и вы не должны снова вызывать функцию. Для получения дополнительной информации найдите PeekMessage. Код взят по этой ссылке: https://jeffpar.github.io/kbarchive/kb/074/Q74042/

person Dialecticus    schedule 05.11.2018