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





Может это вам поможет: Как получить доступ к элементам пользовательского интерфейса из потока в MFC.
Я сам не кодирую C++ / MFC, но у меня возникла аналогичная проблема на C#, которая известна как обновление графического интерфейса между потоками.
Вы должны использовать сообщение (с Send- или PostMessage), чтобы уведомить поток пользовательского интерфейса о том, что текст строки состояния должен быть обновлен. Не пытайтесь обновить элементы пользовательского интерфейса из рабочего потока, это обязательно доставит вам боль.
Вы можете опубликовать личное сообщение в главном окне фрейма и «попросить» его обновить строку состояния. Потоку потребуется дескриптор главного окна (не используйте объект 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;
}
Не идеально, но это начало.
Диапазон сообщений WM_USER - правильный ответ. RegisterWindowMessage - это немного сложнее для частного сообщения приложения, поскольку оно гарантирует уникальность во всей системе, а в этом нет необходимости.
Диапазон сообщений WM_APP еще лучше.
Вам следует PostMessage, а не SendMessage. Причина, по которой MFC и C# жалуются на эти вещи, заключается в том, что SendMessage является блокирующим вызовом и может вызывать взаимоблокировки.