Как изменить текст панели состояния из потока в MFC?

У меня есть диалог в MFC с CStatusBar. В отдельном потоке я хочу изменить текст панели состояния. Однако MFC жалуется на утверждения? Как это делается? Пример кода будет большим.

3 ответа

Вы можете отправить личное сообщение в окно основного фрейма и "попросить" его обновить строку состояния. Для потока потребуется ручка главного окна (не используйте объект 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;
}
</hwnd>

Код из памяти, так как у меня нет доступа к компилятору здесь, поэтому приносим извинения за любые ошибки.

Вместо использования 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;
}
</cstring*></lparam></hwnd>

Не идеально, но это начало.


Возможно, это может вам помочь: Как получить доступ к элементам пользовательского интерфейса из потока в MFC.

Я не кодирую сам С++/MFC, но я столкнулся с аналогичной проблемой в С#, которая называется обновлением графического интерфейса Cross-thread.


Вы должны использовать сообщение (либо с Send- или PostMessage), чтобы уведомить поток пользовательского интерфейса, что текст строки состояния должен быть обновлен. Не пытайтесь обновлять элементы пользовательского интерфейса из рабочего потока, он должен дать вам боль.

licensed under cc by-sa 3.0 with attribution.