2009-08-24 18 views
15

Wewnątrz mojej aplikacji chcę wysłać wiadomość do okna dialogowego z innego wątku. Chcę przekazać odwołanie klasy std :: exception do okna dialogowego.Jak wysłać ciąg przez PostMessage?

coś takiego:

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

Chcę otrzymywać wiadomości w mój dialog i pokazać błąd, który jest w the_exception.error_string()

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

minięciu std::string the_exception.error_string() użyciu PostMessage byłoby również ok, ja odgadnąć.

Odpowiedz

12

Nie można przekazać adresu ciągu w PostMessage, ponieważ ciąg jest prawdopodobnie wątkiem lokalnym na stosie. Zanim drugi wątek go podniesie, mógł zostać zniszczony.

Zamiast tego należy utworzyć nowy ciąg lub obiekt wyjątku za pośrednictwem nowego i przekazać jego adres do drugiego wątku (za pośrednictwem parametru WPARAM lub LPARAM w PostMessage). Drugi wątek jest właścicielem obiektu i jest odpowiedzialny za jego zniszczenie.

Oto przykładowy kod, który pokazuje w jaki sposób można to zrobić:

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

Witam, bardzo dziękuję za odpowiedź. zapomniałeś obsady na LPARAM PostMessage (MyhWnd, CWM_SOME_ERROR, 0, reinterpret_cast (nowy ciąg (the_exception.error_string))); A co powiesz na temat używania auto_ptr zamiast: std :: auto_ptr msg (reinterpret_cast (lParam)); Ponieważ pokazuje to przeniesienie własności. – rec

+0

ouch, złe formatowanie przerwa linii testowej przerwa linii testowej – rec

+1

Czy to nie jest wyciek pamięci? Gdzie niszczysz nowy ciąg()? –

1

Dopóki przebywasz w procesie, wystarczy podać void * wskaźnik i trochę troski o czas życia obiektu.

Jeśli jest SendMessage, możesz przekazać go w LPARAM jako void * cast, a klient odkaże go z powrotem do twojego typu łańcucha. Ponieważ SendMessage jest synchronous, jesteś bezpieczny:

Jeśli określony został stworzony przez okno wątek wywołujący procedura okna nazywa się natychmiast jako podprogramu. Jeśli określone okno zostało utworzone przez inny wątek, system przełącza się na ten wątek, a wywołuje odpowiednią procedurę okna: . Wiadomości wysyłane między wątkami są przetwarzane tylko wtedy, gdy wątek odbierający wykonuje komunikat kodu pobierania . Wysyłanie wątek jest zablokowany aż wątku odbierającego przetwarza wiadomość

Jeśli chcesz używać PostMessage będziesz musiał zrobić wyraźne rękę off ponieważ wywołanie jest asynchroniczna: zrobić kopię napisu na stertę i wywołanie wiadomości PostMessage, w której przekazałeś odpowiedzialność usunięcia do calee (okno dialogowe).

Jeśli wyjdziesz z procesu (MyhWnd należy do innego procesu), to zupełnie inna historia, a będziesz musiał przekazać swoją wiadomość w coś w rodzaju globalnego atomu.

+0

OK, czas iść do domu. Odpowiedziałem tak, jakby OP pytał o SendMessage, a cała sprawa dotyczyła PostMessage ... –

+1

Dobrze zauważyć, że SendMessage jest synchroniczny i nie musisz się martwić o przeniesienie własności.Jednak SendMessage może być ponownie wprowadzany, tj. Podczas połączenia z SendMessage wątek może pompować wiadomości, więc musisz uważać na stan, że przejście do innego wątku nie może być zmutowane w żadnym z twoich wndproc. – Michael

+0

IMO to jest poprawna odpowiedź: użyj SendMessage i skopiuj wiadomość w wątku otrzymującym po jej otrzymaniu. Nie musisz ustawiać bomby ze skomplikowanymi problemami PostMessage/synchronization dla prostego przekazu tekstowego (ciąg, który, jak sądzę, będzie raczej krótki). – Roel

0

Dopóki wiesz, że okno (lub wystąpienie CMyDlg) nadal będzie wokół po wysłaniu wiadomości, która może po prostu sklep ciąg błędu w zmiennej członkowskiej i odczytany z niego w module obsługi komunikatów.

Powiązane problemy