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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
0
10 781
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

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

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

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

Вам следует PostMessage, а не SendMessage. Причина, по которой MFC и C# жалуются на эти вещи, заключается в том, что SendMessage является блокирующим вызовом и может вызывать взаимоблокировки.

Joel 24.12.2008 18:21
Ответ принят как подходящий

Вы можете опубликовать личное сообщение в главном окне фрейма и «попросить» его обновить строку состояния. Потоку потребуется дескриптор главного окна (не используйте объект 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 - это немного сложнее для частного сообщения приложения, поскольку оно гарантирует уникальность во всей системе, а в этом нет необходимости.

Joel 24.12.2008 18:19

Диапазон сообщений WM_APP еще лучше.

Jabberwocky 09.05.2012 11:15

Другие вопросы по теме