2009-04-19 18 views
11

In un'applicazione C++ Win32, viene avviato un loop di messaggi che recupera i messaggi da una coda, li traduce e li invia. Alla fine, ogni messaggio raggiunge il nostro WndProc in cui è possibile gestire l'evento associato.Come viene implementata la programmazione basata sugli eventi di Win32?

Capisco quella parte. Quello che non capisco è il mezzo tra cose da fare. In particolare:

  1. Diversi tipi di gestori di interrupt del sistema operativo devono posizionare i messaggi nella suddetta "coda dei messaggi", ma dove si trova questa coda nello spazio di indirizzamento del processo? Come viene esposto al codice del gestore di interrupt?
  2. Che cosa significa "tradurre" il messaggio? Che cosa fa davvero la chiamata a TranslateMessage()?
  3. Una volta inviato da DispatchMessage(), quello che tutti i luoghi significa il messaggio swing prima di raggiungere il mio WndProc (vale a dire che cosa fa il sistema operativo fare con esso)?

Se qualcuno conosce le risposte a quanto sopra, accontenta gentilmente la mia curiosità. Grazie.

risposta

6

Il sistema operativo mantiene una coda di messaggi, dove mette gli eventi (ad esempio, da interruzioni o da altre fonti). Quindi invia i messaggi da quella coda a tutte le finestre, a seconda del messaggio (ad esempio, non invierà messaggi chiave a una finestra che non ha lo stato attivo).

Le applicazioni possono disporre di una propria coda per elaborare i messaggi. Queste code vengono create on request (solo se necessario).

Tradurre un messaggio viene utilizzato per creare messaggi che non sono gli eventi 'reali'. Ad esempio, il messaggio WM_CONTEXTMENU viene "tradotto" da un clic del mouse o dal tasto del menu di scelta rapida o da MAIUSC-F10. WM_CHAR viene tradotto dai messaggi WM_KEYDOWN. E naturalmente molti altri messaggi vengono "tradotti" in questo modo.

Un messaggio viene inviato a ogni finestra che dovrebbe riceverlo. Il sistema operativo decide in base al tipo di messaggio se una finestra dovrebbe ricevere quel messaggio o meno. La maggior parte dei messaggi sono attesi dal sistema, cioè il messaggio non verrà pubblicato in un'altra finestra finché non verrà elaborato dalla finestra.Ciò ha un grande impatto per i messaggi broadcast: se una finestra non ritorna quando si gestisce quel messaggio, la coda è blocked e altre finestre non riceveranno più il messaggio.

+3

Questo è tutto sbagliato. Le parti di esso che sono corrette, sono corrette solo se la domanda riguardava Win16 in cui l'intero sistema operativo e le applicazioni erano pianificate in modo cooperativo su un singolo thread. –

1

Non assolutamente positivo su questo ma la mia migliore congettura dice:

  1. La coda è un oggetto di sistema a cui si accede con le chiamate API Win32. Non è affatto nel tuo spazio di indirizzamento del processo. Quindi gli handler di interrupt possono accedervi (probabilmente attraverso l'HAL (Hardware Abstraction Layer) del kernel).

  2. In Win16, quella chiamata prese i vari sotto parti di un messaggio più grande e li purè in un tutto. Quindi TranslateMessage aggiungerebbe WM_KEYPRESS quando ha trovato la corrispondente sequenza WM_KEYDOWN WM_KEYUP. Dovrebbe inoltre trasformare vari messaggi di clic sui pulsanti in messaggi di doppio clic in base alle impostazioni interne e ai timestamp dei messaggi. Se lo fa ancora in Win32, non lo so.

  3. DispatchMessage è probabilmente dove ganci dei messaggi finestra Ottieni elaborati. Quindi, se c'è un gancio sulla tua finestra, viene chiamato qui o quando viene chiamato GetMessage. Non ne sono sicuro. Oltre a questo, DispatchMessage cerca solo l'indirizzo WndProc associato alla finestra e lo chiama. Non c'è molto altro da fare.

Spero che questo aiuti.

6

Dipende da come viene inviato il messaggio e da come viene gestito.

Quando si chiama SendMessage, se la finestra di destinazione è di proprietà del thread corrente, la chiamata ignora la coda messaggi per la finestra e il gestore di finestre chiama direttamente il windowproc sulla finestra di destinazione. Se la finestra di destinazione è di proprietà di un altro thread, il gestore di finestre chiama in modo efficace PostMessage e pompa i messaggi della finestra finché la finestra di destinazione non viene restituita dalla finestra proc.

Quando si chiama PostMessage, il gestore finestre esegue il marshalling dei parametri del messaggio e inserisce l'oggetto corrispondente nella coda messaggi per la finestra di destinazione. Alla successiva chiamata a GetMessage, il messaggio viene rimosso dalla coda dei messaggi.

Il gestore finestre registra anche eventi di input non elaborati dai dispositivi di input (tastiera e/o mouse) e genera messaggi per tali eventi di input. Quindi inserisce tali messaggi nella coda come appropriato (l'elaborazione degli eventi di input è complicata perché dipende da quali messaggi sono già nella coda dei messaggi per la finestra).

Come indicato da Stefan, TranslateMessage traduce solo le chiavi di accelerazione, ad esempio converte sequenze di tasti in messaggi WM_COMMAND.

1

Per affrontare l'ultima subquestion, un messaggio inviato andrà al vostro WindowProc dopo che è stato convogliato attraverso tutti i ganci (WH_CALLWNDPROC)

4

Diversi tipi di gestori di interrupt del sistema operativo deve essere trasmettere i messaggi in detta coda dei messaggi' ', ma dove all'interno dello spazio di indirizzamento del processo risiede questa coda? Come viene esposto al codice del gestore di interrupt?

Le finestre sono associate ai thread. Ogni thread con una finestra ha una coda di thread nello spazio degli indirizzi del processo. Il sistema operativo ha una coda interna nel proprio spazio indirizzo per gli eventi generati dall'hardware. Usando i dettagli dell'evento e altre informazioni sullo stato (ad es., Quale finestra ha il focus), il sistema operativo traduce gli eventi hardware in messaggi che vengono quindi inseriti nella coda dei thread appropriata.

I messaggi inviati vengono inseriti direttamente nella coda di thread per la finestra di destinazione.

I messaggi inviati vengono generalmente elaborati direttamente (ignorando la coda).

I dettagli diventano pelosi. Ad esempio, le code di thread sono più che elenchi di messaggi, inoltre mantengono alcune informazioni di stato. Alcuni messaggi (come WM_PAINT) non sono realmente accodati, ma sintetizzati dalle informazioni di stato aggiuntive quando si interroga la coda ed è vuoto. I messaggi inviati a finestre di proprietà di altri thread vengono effettivamente inviati alla coda del destinatario anziché essere elaborati direttamente, ma il sistema lo fa apparire come un normale invio di blocco dal punto di vista del chiamante. L'ilarità si verifica se questo può causare deadlock (a causa di mandate circolari al thread originale).

I libri di Jeffrey Richter hanno molti (tutti?) Dei dettagli cruenti. La mia edizione è vecchia (Windows avanzato). L'edizione corrente sembra essere chiamata Windows via C/C++.

Il sistema operativo esegue MOLTO lavoro per rendere il flusso dei messaggi razionale (e relativamente semplice) al chiamante.

Che cosa significa "tradurre" il messaggio? Che cosa fa veramente la chiamata a TranslateMessage()?

Controlla i messaggi chiave virtuali e, quando riconosce una combinazione di tasti giù/chiave, aggiunge messaggi di carattere. Se non chiami TranslateMessage, non riceverai messaggi di caratteri come WM_CHAR.

Sospetto che invii il messaggio di carattere direttamente prima di tornare (al contrario di pubblicarli). Non ho mai controllato, ma mi sembra di ricordare che i messaggi WM_CHAR arrivano poco prima del WM_KEYUP.

Una volta inviato da DispatchMessage(), quali sono tutte le posizioni in cui il messaggio oscilla prima di raggiungere il mio WndProc (cioè cosa fa il sistema operativo con esso)?

DispatchMessage passa il messaggio al WndProc per la finestra di destinazione. Lungo la strada, alcuni ganci possono avere la possibilità di vedere il messaggio (e possibilmente interferire con esso).

Problemi correlati