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

后端 未结 3 1153
忘掉有多难
忘掉有多难 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: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(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(pParam);
        ASSERT(hMainFrame != NULL);
        CString* pString = new CString;
        *pString = _T("Hello, world!");
        ::PostMessage(hMainFrame, WM_USER, 0, reinterpret_cast(pString));
        return 0;
    }
    
    LRESULT CMainFrame::OnUser(WPARAM, LPARAM lParam)
    {
        CString* pString = reinterpret_cast(lParam);
        ASSERT(pString != NULL);
        m_wndStatusBar.SetPaneText(0, *pString);
        delete pString;
        return 0;
    }
    

    Not perfect, but it's a start.

提交回复
热议问题