【问题标题】:Handle tab stop using DispatchMessage() without blocking the thread through message loop?使用 DispatchMessage() 处理制表位而不通过消息循环阻塞线程?
【发布时间】:2019-04-04 03:02:08
【问题描述】:

我在用于 UI 视图的 DLL 中有一个函数 export OpenUI(),它创建了无模式的主对话框,也有一个无模式的子对话框。

我从一个单独的 DLL 调用函数 export OpenUI(),这是我的控制器。

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

我的 UI 视图 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
}

【问题讨论】:

  • 一个代码示例说一千个单词
  • SetWindowsHookEx安装一个钩子,从它调用IsDialogMessage
  • 大多数提供无模式对话框的框架都有某种“PreHandle”消息调用,消费者必须从他们的消息循环中调用。
  • @paddy 对不起。我编辑了我的帖子并添加了伪代码
  • 您询问的是您提出的解决方案,而不是您要解决的实际问题。拥有窗口的线程自然必须调度消息。要求一种在不发送消息的情况下发送消息的方法不会给你答案。解决方案的第一步是熟悉 Windows 应用程序的结构。 Petzold 的Programming Windows®, Fifth Edition 会教你。

标签: c++ windows winapi visual-c++ win32gui


【解决方案1】:

你必须有一个活跃的消息循环,这是没有办法的。一种方法是使用一个新函数PeekMessage 并且只执行一次循环代码。如果随后对GetMessage 的调用实际上会收到一条消息而不是阻塞,则PeekMessage 返回非零值。 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/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    • 2011-12-30
    • 2020-09-01
    • 2014-05-25
    • 2021-05-01
    • 1970-01-01
    相关资源
    最近更新 更多