2009-08-24 5 views
15

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

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

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 также будет хорошо, я Угадай.

ответ

12

Вы не можете передать адрес строки в 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; 
} 
+1

Привет, большое спасибо за ваш ответ. вы забыли бросок для LPARAM PostMessage (MyhWnd, CWM_SOME_ERROR, 0, reinterpret_cast (новая строка (the_exception.error_string))); А как насчет использования auto_ptr вместо: std :: auto_ptr msg (reinterpret_cast (lParam)); Потому что это показывает передачу права собственности. – rec

+0

ouch, плохое форматирование проверка линии разрыва проверка линии перерыва – rec

+1

Это не утечка памяти? Где вы уничтожаете новую строку()? –

1

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

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

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

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

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

+0

ОК, время, чтобы вернуться домой. Я ответил так, как будто OP спрашивал о SendMessage, и все дело в том, что PostMessage ... –

+1

Приятно отметить, что SendMessage синхронно, и вам не нужно беспокоиться о передаче права собственности.Тем не менее, SendMessage может быть повторно подключен, то есть во время вызова SendMessage ваш поток может пересылать сообщения, поэтому вам нужно быть осторожным, чтобы ваше переключение в другой поток не могло быть изменено в любом из ваших wndprocs. – Michael

+0

IMO это правильный ответ: используйте SendMessage и скопируйте сообщение в принимающий поток после его получения. Не нужно настраивать бомбу сложными проблемами PostMessage/synchronization для простого прохода строки (строка, которая, как я полагаю, будет довольно короткой). – Roel

0

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