Обрабатывать табуляцию с помощью DispatchMessage (), не блокируя поток через цикл сообщений? - PullRequest
0 голосов
/ 31 октября 2018

У меня есть функция экспорта 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
}

1 Ответ

0 голосов
/ 05 ноября 2018

Вы должны иметь активную петлю сообщений, нет пути к этому. Один из способов сделать это - иметь одну новую функцию, которая будет 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/

...