6

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

4

3 回答 3

5

您可以将私人消息发布到主框架窗口并“要求”它更新状态栏。线程需要主窗口句柄(不要使用 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;
}

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

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

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

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

于 2008-12-24T12:05:19.480 回答
3

也许这可以帮助您:如何从 MFC 中的线程访问 UI 元素。

我自己没有编写 C++/MFC 代码,但我在 C# 中遇到过类似的问题,即所谓的跨线程 GUI 更新。

于 2008-12-24T10:23:53.740 回答
3

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

于 2008-12-24T12:01:06.900 回答