MFC:更新功能区栏元素以反映操作进度

时间:2014-08-30 00:37:35

标签: multithreading visual-c++ mfc ribbon

我正在制作一个模拟工具,它在用户定义的迭代次数上运行模拟(在单独的线程中),可以在功能区栏上的编辑控件中输入。我想重复使用它来显示模拟过程中的当前迭代。我还将CMFCRibbonProgressBar用于显示进度。功能区栏使用资源编辑器创建。

问题是如何让进度条和迭代计数器及时更新而不会导致GUI无响应?

ON_UPDATE_COMMAND_UI例程的传统方法需要窗口中的活动,例如移动鼠标。

所以我可能需要一个可以更新此控件的线程。简单地创建一个线程并尝试从concurrency :: parallel_invoke更新控件的事情是不合适的。前者根本不起作用,后者起作用,但会导致GUI冻结。

我在我的文档中存储指针以简化对控件的访问。 https://stackoverflow.com/a/25429446?noredirect=1

我的一般想法是(伪代码)

beginUpdatingThread()
{
while(simulating)
{
updateEditControl();
updateProgressBar();
sleep_40_ms();//conserves the resorces as there is no sense to update more frequent than 25 times per second
}
}

实施此方法的正确方法是什么?

2 个答案:

答案 0 :(得分:0)

ASSERT(m_hWnd!=NULL);

MSG msg;

while (simulating)
{
  // Handle dialog messages
  while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  {
    if(!IsDialogMessage(&msg))
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);  
    }
  }
}

答案 1 :(得分:0)

我通过向执行更新的主窗口添加方法解决了这个问题。现在,从上面更新的线程不断地将消息发布到主窗口以执行更新:

auto h = static_cast<CMainFrame*>(AfxGetMainWnd())->m_hWnd;
    //here code for starting simulation in a separate thread

    std::thread updating([this,h]{

        while (simulating)
        { 
            ::PostMessage(h, WM_UPDATE_VISUALS, sumulator.getCurrentIteration(), 0);

        std::this_thread::sleep_for(std::chrono::milliseconds(40));
        }
        ::PostMessage(h, WM_UPDATE_VISUALS, num_iterations, 0);
    });
updating.detach()

我首先通过引用来捕获h,然后快速过期,从而犯了一个微妙的错误 但最后,上面的代码正是我想要实现的目标