2012-11-13 13 views
6

Ho 2 app, una è nascosta ("hW"), un'altra è app console ("CA") , da che suppongo di inviare comandi a hW. Nella console app sto ottenendo maniglia hW, e qui è una domanda: se sto correndo:PostMessage (hwnd, WM_SETTEXT, ..) non funziona mentre PostMessage (hwnd, WM_QUIT, ..) fa

PostMessage(hwnd, WM_QUIT, NULL, NULL); 

tutto funziona bene, il messaggio arriva a hW e la spegne Ma se sto inviando

PostMessage(hwnd, WM_SETTEXT, NULL, (LPARAM)"texttext"); 

messaggio non arriva a hW affatto. Spy ++ mostra anche che il messaggio non arriva a hW. C'è qualcosa di specifico su WM_SETTEXT, che lo impedisce? Grazie in anticipo.

OK. trovato risposta qui 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.
Inoltre, sembra

SendMessage(hwnd, WM_QUIT, NULL, NULL); 

non fa nulla per indirizzare app.Even in semplice applicazione test come

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

mentre

PostMessage(hNote, WM_QUIT, NULL, NULL); 

opere.
Tutto ciò non sembra logico per me ... Esiste qualche funzione universale che funzioni correttamente con qualsiasi tipo di messaggio?

+1

Suppongo che il messaggio venga immediatamente respinto perché il puntatore specificato non è garantito per essere valido al momento della spedizione. È necessario lavorare su questo utilizzando un messaggio definito dall'utente/registrato in cui si è responsabili della gestione della stringa del payload. Oppure, passare il controllo altrimenti nel thread della finestra e 'SendMessage' da lì. –

+0

È necessario utilizzare SendMessage() qui. E usa una stringa Unicode, di solito. –

+0

Grazie. capito ora. ma volevo inviare un testo non predefinito in un messaggio asincrono. – user1821599

risposta

0

Quello che stai cercando di fare è comunicare due processi separati, i messaggi normali non funzioneranno, ma ce n'è uno che potrebbe fare il trucco: il messaggio WM_COPYDATA. Una domanda correlata può essere trovata here

+0

Per esattamente la stessa ragione per cui 'PostMessage' non può essere usato con' WM_SETTEXT' attraverso un processo, né può essere usato per consegnare 'WM_COPYDATA'. http://blogs.msdn.com/b/oldnewthing/archive/2011/09/16/10208976.aspx –

+0

Hai ragione !, ho completamente dimenticato il vero problema che sta inviando il messaggio tramite 'PostMessage' invece di' SendMessage'. La tua risposta è quella giusta – csanchez

1

A partire dall'ultima domanda: no non esiste una funzione di messaggio universale che farà ciò che si desidera.

Analizziamo i vostri casi:

  1. WM_SETTEXT: Questo messaggio richiede un puntatore, quindi non è possibile inviare in modo sicuro tra i processi, in quanto saranno hanno separato gli indirizzi di memoria, e un puntatore da un processo non avrebbe senso all'altro. È possibile possibile utilizzare SendMessage() perché Windows conosce il messaggio, copia i dati dietro le quinte e esegue l'hacking aggiuntivo. Ma con PostMessage() non c'è (non può essere) tale magia.

  2. WM_QUIT: questo è un messaggio speciale che interrompe i loop di messaggi. In breve, tutto ciò che fa è GetMessage restituire FALSE in modo che il ciclo di messaggio standard (1) termini. Ma, ah! che funzionerà solo se lo hai PostMessage(). Quando si invia un messaggio a SendMessage(), viene inviato direttamente alla relativa funzione della finestra, senza nemmeno fermarsi nella coda dei messaggi. E le finestre non fanno nulla con WM_QUIT, perché semplicemente non se lo aspettano. In realtà, anche quando postato, questo messaggio non raggiungerà la finestra, in quanto il solito ciclo non chiama DispatchMessage() per questo.Questo è il motivo per cui viene solitamente pubblicato nella discussione, senza finestra, e quindi esiste una funzione che fa tutto questo: PostQuitMessage().

(1) ciclo di messaggi standard:

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

Come una nota, è possibile utilizzare diversi trucchi per spostare i dati tra processi:

  1. Usa WM_COPYDATA. AFAIK non può essere utilizzato con PostMessage(), ma forse è possibile creare due thread nel processo di destinazione in modo che il primo riceva lo WM_COPYDATA e lo restituisca rapidamente, quindi lo inserisce per essere accodato dal secondo thread.

  2. Utilizzare la memoria condivisa (cercare CreateFileMapping()) e PostMessage() un offset in quella memoria. Probabilmente dovresti usare un messaggio definito dall'utente WM_APP + x invece di uno di sistema. Tuttavia, fai attenzione ai problemi di sincronizzazione, ti servirà un mutex o qualcosa del genere.

  3. Tubi con nome! (il mio preferito)

  4. Zoccoli.

8

Diversi messaggi hanno requisiti diversi. Alcuni devono essere inviati in coda. E alcuni devono essere consegnati in modo sincrono. Quindi il sistema è progettato per richiedere entrambi i meccanismi di consegna.

Nel caso di WM_SETTEXT, deve sempre essere consegnato in modo sincrono. Questo perché il gestore di finestre deve essere in grado di gestire la durata dei dati di testo. Raymond Chen ha parlato di questo problema: Why can't I PostMessage the WM_COPYDATA message, but I can SendMessageTimeout it with a tiny timeout?

C'è un pericolo con la chiamata SendMessage quando la finestra è in un altro processo. Se viene bloccato l'altro processo, anche il processo non verrà bloccato. Perché SendMessage è sincrono.

La soluzione è chiamare SendMessageTimeout. Questo marshal i tuoi dati di stringa nell'altro processo. E puoi impostare un timeout per assicurarti che, nell'eventualità che l'altro processo venga bloccato, il tuo processo può evitare quel destino.

+0

E se vuoi davvero che sia asincrono puoi sempre eseguire 'SendMessageTimeout()' su un thread. –

Problemi correlati