Как отправить строку через PostMessage?

Внутри моего приложения я хочу отправить сообщение в диалог из другого потока. Я хочу передать в диалог ссылку на производный класс std::exception.

Что-то вроде этого:

try {
       //do stuff
}
catch (MyException& the_exception) {
    PostMessage(MyhWnd, CWM_SOME_ERROR, 0, 0); //send the_exception or the_exception.error_string() here
}

Я хочу получить сообщение в моем диалоговом окне и показать ошибку, которая находится в the_exception.error_string()

LPARAM CMyDlg::SomeError(WPARAM, LPARAM)
{
    show_error( ?????
    return 0;
}

прохождение std::string the_exception.error_string() использование PostMessage также было бы хорошо, я думаю.

3 ответа

Решение

Вы не можете передать адрес строки в PostMessage, так как строка, вероятно, является локальной в стеке. К тому времени, когда другой поток заберет его, он мог быть уничтожен.

Вместо этого вы должны создать новую строку или объект исключения через new и передать его адрес другому потоку (через параметр WPARAM или LPARAM в PostMessage.) Затем другой поток владеет объектом и отвечает за его уничтожение.

Вот пример кода, который показывает, как это можно сделать:

try
{
    //do stuff
}
catch (MyException& the_exception)
{
    PostMessage(MyhWnd, CWM_SOME_ERROR, 0, new string(the_exception.error_string));
}


LPARAM CMyDlg::SomeError(WPARAM, LPARAM lParam)
{
    // Put in shared_ptr so it is automatically destroyed.
    shared_ptr<string> msg = reinterpret_cast<string*>(lParam);

    // Do stuff with message

    return 0;
}

Пока вы находитесь в процессе, достаточно просто передать указатель void* и немного позаботиться о времени жизни объекта.

Если это SendMessage, вы можете передать его в LPARAM как приведение типа void*, и клиент передаст его обратно в ваш строковый тип. Поскольку SendMessage является синхронным, вы в безопасности:

Если указанное окно было создано вызывающим потоком, оконная процедура вызывается немедленно как подпрограмма. Если указанное окно было создано другим потоком, система переключается на этот поток и вызывает соответствующую оконную процедуру. Сообщения, отправленные между потоками, обрабатываются только тогда, когда принимающий поток выполняет код поиска сообщений. Отправляющий поток блокируется, пока принимающий поток не обработает сообщение.

Если вы хотите использовать PostMessage, то вам придется выполнить явную передачу, потому что вызов асинхронный: создайте копию строки в куче и, вызвав PostMessage, вы передали ответственность за удаление в calee (диалоговое окно),

Если вы выходите из процесса (MyhWnd принадлежит к другому процессу), тогда это совсем другая история, и вам придется преобразовать ваше сообщение в нечто вроде глобального атома.

Пока вы знаете, что ваше окно (или экземпляр CMyDlg) будет по-прежнему после публикации сообщения, вы можете просто сохранить строку ошибки в переменной-члене и прочитать ее в обработчике сообщений.

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