【问题标题】:How to change pane text of status bar from a thread in MFC?如何从 MFC 中的线程更改状态栏的窗格文本?
【发布时间】:2010-09-28 07:32:25
【问题描述】:

我在 MFC 中有一个带有 CStatusBar 的对话框。在一个单独的线程中,我想更改状态栏的窗格文本。然而 MFC 抱怨断言?它是如何完成的?一个示例代码会很棒。

【问题讨论】:

    标签: c++ multithreading mfc thread-safety


    【解决方案1】:

    您可以在主框架窗口中发布私人消息并“要求”它更新状态栏。线程需要主窗口句柄(不要使用 CWnd 对象,因为它不是线程安全的)。下面是一些示例代码:

    static UINT CMainFrame::UpdateStatusBarProc(LPVOID pParam);
    
    void CMainFrame::OnCreateTestThread()
    {
        // Create the thread and pass the window handle
        AfxBeginThread(UpdateStatusBarProc, m_hWnd);
    }
    
    LRESULT CMainFrame::OnUser(WPARAM wParam, LPARAM)
    {
        // Load string and update status bar
        CString str;
        VERIFY(str.LoadString(wParam));
        m_wndStatusBar.SetPaneText(0, str);
        return 0;
    }
    
    // Thread proc
    UINT CMainFrame::UpdateStatusBarProc(LPVOID pParam)
    {
        const HWND hMainFrame = reinterpret_cast<HWND>(pParam);
        ASSERT(hMainFrame != NULL);
        ::PostMessage(hMainFrame, WM_USER, IDS_STATUS_STRING);
        return 0;
    }
    

    代码来自内存,因为我在家里无法访问编译器,所以现在为任何错误道歉。

    您可以注册自己的 Windows 消息,而不是使用 WM_USER

    UINT WM_MY_MESSAGE = ::RegisterWindowsMessage(_T("WM_MY_MESSAGE"));
    

    例如,将上述内容设为CMainFrame 的静态成员。

    如果使用字符串资源太简单,那么让线程在堆上分配字符串并确保 CMainFrame 更新函数将其删除,例如:

    // Thread proc
    UINT CMainFrame::UpdateStatusBarProc(LPVOID pParam)
    {
        const HWND hMainFrame = reinterpret_cast<HWND>(pParam);
        ASSERT(hMainFrame != NULL);
        CString* pString = new CString;
        *pString = _T("Hello, world!");
        ::PostMessage(hMainFrame, WM_USER, 0, reinterpret_cast<LPARAM>(pString));
        return 0;
    }
    
    LRESULT CMainFrame::OnUser(WPARAM, LPARAM lParam)
    {
        CString* pString = reinterpret_cast<CString*>(lParam);
        ASSERT(pString != NULL);
        m_wndStatusBar.SetPaneText(0, *pString);
        delete pString;
        return 0;
    }
    

    并不完美,但这是一个开始。

    【讨论】:

    • WM_USER 范围的消息是这里的正确答案。 RegisterWindowMessage 对于私有应用程序消息来说有点繁重,因为它保证了整个系统的唯一性,而这里不需要。
    • WM_APP 的消息范围更胜一筹。
    【解决方案2】:

    也许这可以帮助你:How to access UI elements from a thread in MFC.

    我自己不编写 C++/MFC 代码,但我在 C# 中遇到过类似的问题,称为跨线程 GUI 更新。

    【讨论】:

      【解决方案3】:

      您应该使用消息(使用 Send- 或 PostMessage)来通知 UI 线程应该更新状态栏文本。不要尝试从工作线程中更新 UI 元素,这势必会给您带来痛苦。

      【讨论】:

      • 你应该 PostMessage,而不是 SendMessage。 MFC和C#抱怨这些事情的原因是SendMessage是一个阻塞调用,会导致死锁。
      猜你喜欢
      • 1970-01-01
      • 2016-06-15
      • 1970-01-01
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      • 2019-06-15
      • 2020-03-25
      • 2014-06-14
      相关资源
      最近更新 更多