简体   繁体   中英

Handle tab stop using DispatchMessage() without blocking the thread through message loop?

I have a function export OpenUI() in a DLL for UI view which creates the modeless main dialog and also has a modeless child dialog.

I am calling the function export OpenUI() from a separate DLL which is my controller.

How can I possibly execute more code after the function call if the message loop in OpenUI() prevents the function to return unless the dialog is closed? I cannot remove the message loop because tab stop will not work without it.

I need the function export to return immediately after execution therefore I cannot use a modal dialog. Creating a subthread is also not an option because it caused issues in my application.

Any help is highly appreciated. Thank you.

Pseudocode for my controller 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;
    }

Pseudocode for my UI view 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
}

You have to have an active message loop, there's no way around that. One way to do it is to have one new function that would PeekMessage and execute the loop code only once. PeekMessage returns non-zero value if subsequent call to GetMessage would actually get a message and not block instead. ProcessOneMessage may look something like this:

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;
}

So, in your main code you have to call this function often (once every 10 ms should be fine). Whatever the code does it must call the function once in 10 ms. You will have a live window and run your code at the same time. But once the function returns TRUE the window was closed and you must not call the function again. For more info search for PeekMessage. The code is taken from this link: https://jeffpar.github.io/kbarchive/kb/074/Q74042/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM