2012-11-13 10 views
6

Mam 2 aplikacje, jedna to ukryte okno ("hW"), druga to konsola ("CA") , od , które przypuszczam wysłać polecenia do hW. W aplikacji konsoli Dostaję HW rączkę, a tu jest pytanie: jeśli biegnę:PostMessage (hwnd, WM_SETTEXT, ..) nie działa, gdy PostMessage (hwnd, WM_QUIT, ..) ma

PostMessage(hwnd, WM_QUIT, NULL, NULL); 

wszystko działa poprawnie, wiadomość dotrze do HW i wyłącza go .Ale jeśli wyślę

wiadomość nie dostaje się do hW w ogóle. Spy ++ pokazuje również, że wiadomość nie dociera do hW. Czy jest coś szczególnego w WM_SETTEXT, co zapobiega temu? Z góry dziękuję.

OK. znaleźć odpowiedź tutaj http://cboard.cprogramming.com/windows-programming/72589-wm_settext-postmessage.html

 
Turns out the API tries to protect me against scope issues; PostMessage() 
always fails with WM_SETTEXT, or any other system-defined message that has 
a pointer as a parameter.Which gets me to SendMessage(), which is not good, 
because i wanted asynchronous messaging....


P.P.S.
Również wygląda

SendMessage(hwnd, WM_QUIT, NULL, NULL); 

nie robi nic, aby kierować app.Even w prostej aplikacji testowej jak

HWND hNote; 
if (!(hNote=FindWindow(L"Notepad",NULL))) 
     exit(1); 
SendMessage(hNote, WM_QUIT, NULL, NULL); 

podczas

PostMessage(hNote, WM_QUIT, NULL, NULL); 

prac.
Wszystko, co wydaje mi się nielogiczne ... Czy istnieje jakaś uniwersalna funkcja, która działa poprawnie z każdym rodzajem wiadomości?

+1

Przypuszczam, że Twoja wiadomość zostanie natychmiast odrzucona, ponieważ wskazany przez Ciebie wskaźnik nie jest gwarantowany w momencie wysyłki. Musisz popracować nad tym przy użyciu zdefiniowanego przez użytkownika/zarejestrowanego komunikatu, w którym jesteś odpowiedzialny za zarządzanie łańcuchem danych. Lub przekaż kontrolę w inny sposób do wątku okna i stamtąd "SendMessage". –

+0

Musisz użyć SendMessage() tutaj. Używaj zwykle ciągu Unicode. –

+0

Dziękuję. mam to teraz. ale chciał wysłać nie predefiniowany tekst w asynchronicznej wiadomości. – user1821599

Odpowiedz

0

Co próbujesz zrobić, to zakomunikować dwa oddzielne procesy, zwykłe wiadomości nie będą działać, ale jest jedna, która może załatwić sprawę: wiadomość WM_COPYDATA. Powiązane pytanie można znaleźć: here

+0

Z dokładnie tego samego powodu, który oznacza, że ​​'PostMessage' nie może być używany z' WM_SETTEXT' w całym procesie, nie można go również użyć do dostarczenia 'WM_COPYDATA'. http://blogs.msdn.com/b/oldnewthing/archive/2011/09/16/10208976.aspx –

+0

Masz rację !, całkowicie zapomniałem o prawdziwym problemie wysyłającym wiadomość poprzez 'PostMessage' zamiast' SendMessage'. Twoja odpowiedź jest poprawna – csanchez

1

Począwszy od ostatniego pytania: nie, nie ma uniwersalnej funkcji wiadomości, która zrobi to, co chcesz.

Przeanalizujmy swoje przypadki:

  1. WM_SETTEXT: To wiadomość pobiera wskaźnik, więc nie można zakładać go bezpiecznie pomiędzy procesami, ponieważ będą one oddzielone adresów pamięci, a wskaźnik z jednego procesu nie miałoby sensu do drugiego. Możesz może użyć SendMessage(), ponieważ Windows wie o wiadomości, kopiuje dane za kulisami i robi dodatkowe hakowanie. Ale z PostMessage() nie ma (nie może być) takich magii.

  2. WM_QUIT: Jest to specjalna wiadomość, która powoduje zerwanie pętli wiadomości. Krótko mówiąc, wszystko to sprawia, że ​​standardowa pętla komunikatów (1) kończy się. Ale, ach! to zadziała tylko wtedy, gdy będzie to PostMessage(). Gdy otrzymasz wiadomość, zostanie ona wysłana bezpośrednio do odpowiedniej funkcji okna, nawet bez zatrzymywania się w kolejce komunikatów. A okna nie robią nic z WM_QUIT, ponieważ po prostu nie oczekują tego. W rzeczywistości, nawet po opublikowaniu, ta wiadomość nie dotrze do okna, ponieważ zwykła pętla nie nazywa się dla niej DispatchMessage().Z tego powodu zazwyczaj jest on publikowany w wątku bez okna, a więc istnieją funkcje, które wykonują to wszystko: PostQuitMessage().

(1) Standardowa pętla wiadomość:

while (GetMessage(&msg, 0, 0, 0)) 
    DispatchMessage(&msg); 

jako przypis, można zastosować kilka sztuczek, aby przenosić dane pomiędzy procesami:

  1. Zastosowanie WM_COPYDATA. AFAIK nie może być używany z PostMessage(), ale może możesz utworzyć dwa wątki w procesie docelowym, tak aby pierwszy odbierał WM_COPYDATA i szybko wraca, a następnie umieszcza go w kolejce do drugiego wątku.

  2. Użyj pamięci współdzielonej (wyszukaj CreateFileMapping()) i PostMessage() przesunięcie do tej pamięci. Prawdopodobnie powinieneś użyć komunikatu zdefiniowanego przez użytkownika WM_APP + x zamiast systemowego. Jednak uważaj na problemy z synchronizacją, będziesz potrzebował muteksa lub czegoś podobnego.

  3. Nazwane rury! (moje ulubione)

  4. Gniazdka.

8

Różne wiadomości mają różne wymagania. Niektóre muszą być wysłane do kolejki. A niektóre trzeba dostarczać synchronicznie. Dlatego system jest zaprojektowany tak, aby wymagał obu mechanizmów dostarczania.

W przypadku WM_SETTEXT, zawsze musi być dostarczona synchronicznie. To dlatego, że menedżer okien musi być w stanie zarządzać czasem życia danych tekstowych. Raymond Chen mówił o tym problemie: Why can't I PostMessage the WM_COPYDATA message, but I can SendMessageTimeout it with a tiny timeout?

Istnieje niebezpieczeństwo z wywołaniem SendMessage, gdy okno jest w innym procesie. Jeśli drugi proces zostanie zawieszony, twój proces również nie będzie zawieszony. Ponieważ SendMessage jest synchroniczny.

Rozwiązaniem jest zadzwonić pod numer SendMessageTimeout. Spowoduje to przeniesienie danych ciągu do innego procesu. Możesz ustawić limit czasu, aby upewnić się, że w przypadku zawieszenia innego procesu Twój proces może zapobiec temu losowi.

+0

A jeśli naprawdę chcesz, aby była asynchroniczna, zawsze możesz wykonać 'SendMessageTimeout()' na wątku. –

Powiązane problemy