How to change pane text of status bar from a thread in MFC?

后端 未结 3 1154
忘掉有多难
忘掉有多难 2021-01-05 16:44

I have a dialog in MFC with a CStatusBar. In a separate thread, I want to change the pane text of status bar. However MFC complains with asserts? How is it done? An example

相关标签:
3条回答
  • 2021-01-05 17:04

    You should use a message (either with Send- or PostMessage) to notify the UI thread that the status bar text should be updated. Don't try to update UI elements from a worker thread, it's bound to give you pain.

    0 讨论(0)
  • 2021-01-05 17:06

    You could post a private message to the main frame window and 'ask' it to update the status bar. The thread would need the main window handle (don't use the CWnd object as it won't be thread safe). Here is some sample code:

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

    The code is from memory as I don't have access to compiler here at home, so apologies now for any errors.

    Instead of using WM_USER you could register your own Windows message:

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

    Make the above a static member of CMainFrame for example.

    If using string resources is too basic then have the thread allocate the string on the heap and make sure the CMainFrame update function deletes it, e.g.:

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

    Not perfect, but it's a start.

    0 讨论(0)
  • 2021-01-05 17:13

    Maybe this can help you: How to access UI elements from a thread in MFC.

    I don't code C++/MFC myself but I had experienced the similar problem in C# which is known as Cross-thread GUI update.

    0 讨论(0)
提交回复
热议问题