Informazioni sui messaggi e sulle code di messaggi

A differenza delle applicazioni basate su MS-DOS, le applicazioni basate su Windows sono basate su eventi. Non effettuano chiamate di funzione esplicite (ad esempio le chiamate della libreria di runtime C) per ottenere l'input. Attendono invece che il sistema passi l'input a loro.

Il sistema passa tutti gli input per un'applicazione alle varie finestre dell'applicazione. Ogni finestra ha una funzione, denominata procedura finestra, che il sistema chiama ogni volta che ha input per la finestra. La routine della finestra elabora l'input e restituisce il controllo al sistema. Per altre informazioni sulle procedure delle finestre, vedere Procedure di finestra.

Se una finestra di primo livello smette di rispondere ai messaggi per più di diversi secondi, il sistema considera la finestra non risponde. In questo caso, il sistema nasconde la finestra e lo sostituisce con una finestra fantasma con lo stesso ordine Z, posizione, dimensioni e attributi visivi. Ciò consente all'utente di spostarlo, ridimensionarlo o anche chiudere l'applicazione. Tuttavia, queste sono le uniche azioni disponibili perché l'applicazione non risponde. Quando nella modalità debugger il sistema non genera una finestra fantasma.

Questa sezione illustra gli argomenti seguenti:

Messaggi di Windows

Il sistema passa l'input a una routine di finestra sotto forma di messaggio. I messaggi vengono generati sia dal sistema che dalle applicazioni. Il sistema genera un messaggio in ogni evento di input, ad esempio quando l'utente digita, sposta il mouse o fa clic su un controllo, ad esempio una barra di scorrimento. Il sistema genera anche messaggi in risposta alle modifiche apportate dal sistema generato da un'applicazione, ad esempio quando un'applicazione modifica il pool di risorse del tipo di carattere di sistema o ridimensiona una delle relative finestre. Un'applicazione può generare messaggi per indirizzare le proprie finestre per eseguire attività o comunicare con finestre in altre applicazioni.

Il sistema invia un messaggio a una routine di finestra con un set di quattro parametri: un handle di finestra, un identificatore di messaggio e due valori denominati parametri del messaggio. L'handle della finestra identifica la finestra per cui è previsto il messaggio. Il sistema lo usa per determinare quale procedura finestra deve ricevere il messaggio.

Un identificatore di messaggio è una costante denominata che identifica lo scopo di un messaggio. Quando una routine di finestra riceve un messaggio, usa un identificatore di messaggio per determinare come elaborare il messaggio. Ad esempio, l'identificatore di messaggio WM_PAINT indica alla routine della finestra che l'area client della finestra è stata modificata e deve essere riinteduta.

I parametri del messaggio specificano i dati o la posizione dei dati usati da una routine di finestra durante l'elaborazione di un messaggio. Il significato e il valore dei parametri del messaggio dipendono dal messaggio. Un parametro di messaggio può contenere un numero intero, flag di bit compressi, un puntatore a una struttura contenente dati aggiuntivi e così via. Quando un messaggio non usa parametri di messaggio, in genere sono impostati su NULL. Una routine della finestra deve controllare l'identificatore del messaggio per determinare come interpretare i parametri del messaggio.

Tipi di messaggi

Questa sezione descrive i due tipi di messaggi:

messaggi System-Defined

Il sistema invia o pubblica un messaggio definito dal sistema quando comunica con un'applicazione. Usa questi messaggi per controllare le operazioni delle applicazioni e fornire input e altre informazioni per l'elaborazione delle applicazioni. Un'applicazione può anche inviare o pubblicare messaggi definiti dal sistema. Le applicazioni usano in genere questi messaggi per controllare l'operazione delle finestre di controllo create usando classi di finestre preregisterate.

Ogni messaggio definito dal sistema ha un identificatore di messaggio univoco e una costante simbolica corrispondente (definita nei file di intestazione SDK )software development kit (SDK) che indica lo scopo del messaggio. Ad esempio, la costante WM_PAINT richiede che una finestra dipinga il contenuto.

Le costanti simboliche specificano la categoria a cui appartengono i messaggi definiti dal sistema. Il prefisso della costante identifica il tipo di finestra che può interpretare ed elaborare il messaggio. Di seguito sono riportati i prefissi e le relative categorie di messaggi.

Prefisso Categoria di messaggi Documentazione
ABM e ABN Barra degli strumenti desktop dell'applicazione Messaggi e notifiche della shell
ACM e ACN Controllo Animation Notifiche di controllo animazione e messaggi di controllo animazione
BCM, CNN, BM e BN Controllo Button Messaggi di controllo pulsante e notifiche di controllo pulsante
CB e CBN ComboBox (controllo) Notifiche di controllo ComboBox e ComboBox
CBEM e CBEN Controllo ComboBoxEx Notifiche ComboBoxEx e ComboBoxEx
CCM Controllo generale Messaggi di controllo
CDM Finestra di dialogo comune Messaggi della finestra di dialogo comuni
DFM Menu di scelta rapida predefinito Messaggi e notifiche della shell
DL Casella di riepilogo trascinamento Trascina notifiche casella di riepilogo
DM Controllo pulsante push predefinito Finestra di dialogo Messaggi
DTM e DTN Controllo selezione data e ora Notifiche selezione data e ora
EM e EN Controllo Edit Modificare i messaggi di controllo, modificare le notifiche di controllo, i messaggi di modifica avanzati e le notifiche di modifica avanzata
HDM e HDN Controllo intestazione Messaggi di controllo intestazione e notifiche di controllo intestazione
HKM Controllo tasto di scelta rapida Messaggi di controllo dei tasti di scelta rapida
IPM e IPN controllo indirizzo IP Messaggi di indirizzo IP e notifiche degli indirizzi IP
LB e LBN Controllo casella di riepilogo Notifiche casella di riepilogo e messaggi casella di riepilogo
LM Controllo SysLink Messaggi di controllo SysLink
LVM e LVN Controllo visualizzazione elenco Visualizzare messaggi elenco e notifiche di visualizzazione elenco
MCM e MCN Controllo calendario mese Messaggi del calendario mese e notifiche del calendario mensile
gestione basata su criteri Barra di stato Messaggi della barra di stato
PGM e PGN Controllo Pager Messaggi di controllo pager e notifiche del controllo pager
PSM e PSN Finestra delle proprietà Notifiche del foglio proprietà e messaggi della finestra delle proprietà
RB e RBN Controllo barra di ripetizione Messaggi di controllo della barra di ripristino e notifiche di controllo della barra di ripristino
SB e SBN Finestra barra di stato Messaggi della barra di stato e notifiche della barra di stato
SBM Controllo Scroll Bar Messaggi della barra di scorrimento
SMC Menu Shell Messaggi e notifiche della shell
STM e STN Controllo statico Messaggi di controllo statici e notifiche di controllo statico
TB e TBN Barra degli strumenti Notifiche di controllo della barra degli strumenti e messaggi della barra degli strumenti
TBM e TRBN Controllo Trackbar Messaggi di controllo della barra di traccia e notifiche di controllo della barra di rilevamento
TCM e TCN Controllo Tab Notifiche di controllo tabulazioni e messaggi di controllo tabulazioni
TDM e TDN Finestra di dialogo attività Messaggi della finestra di dialogo attività e notifiche della finestra di dialogo attività
TTM e TTN Controllo descrizione comando Messaggi di controllo della descrizione comando e notifiche per la descrizione comando
TVM e TVN Controllo visualizzazione albero Visualizzazione albero messaggi e notifiche di visualizzazione albero
UDM e UDN Controllo up-down Notifiche up-down e up-down
WM Generale
Messaggi negli Appunti
Notifiche degli Appunti
Notifiche della finestra di dialogo comuni
Notifiche cursori
Messaggio copia dati
Messaggi di Gestione finestre desktop
messaggi Gestione dispositivi
Finestra di dialogo Notifiche
Messaggi di Scambio di dati dinamici
Notifiche di Exchange di dati dinamiche
Notifiche di hook
Messaggi dell'acceleratore di tastiera
Notifiche dell'acceleratore di tastiera
Messaggi di input della tastiera
Notifiche di input da tastiera
Notifiche menu
Notifiche di input del mouse
Più messaggi di interfaccia documento
Notifiche di input non elaborate
Notifiche della barra di scorrimento
Notifiche timer
Messaggi della finestra
Notifiche finestra

I messaggi della finestra generale coprono un'ampia gamma di informazioni e richieste, inclusi i messaggi per l'input del mouse e della tastiera, l'input e la finestra di dialogo, la creazione e la gestione delle finestre e Dynamic Data Exchange (DDE).

messaggi Application-Defined

Un'applicazione può creare messaggi da usare dalle proprie finestre o per comunicare con finestre in altri processi. Se un'applicazione crea i propri messaggi, la procedura della finestra che li riceve deve interpretare i messaggi e fornire l'elaborazione appropriata.

I valori dell'identificatore di messaggio vengono usati come segue:

  • Il sistema riserva i valori di identificatore di messaggio nell'intervallo 0x0000 tramite 0x03FF (il valore di WM_USER - 1) per i messaggi definiti dal sistema. Le applicazioni non possono usare questi valori per i messaggi privati.
  • I valori nell'intervallo 0x0400 (il valore di WM_USER) tramite 0x7FFF sono disponibili per gli identificatori di messaggio per le classi finestra private.
  • Se l'applicazione è contrassegnata come versione 4.0, è possibile usare i valori dell'identificatore di messaggio nell'intervallo 0x8000 (WM_APP) tramite 0xBFFF per i messaggi privati.
  • Il sistema restituisce un identificatore di messaggio nell'intervallo 0xC000 tramite 0xFFFF quando un'applicazione chiama la funzione RegisterWindowMessage per registrare un messaggio. L'identificatore del messaggio restituito da questa funzione è garantito che sia univoco in tutto il sistema. L'uso di questa funzione impedisce conflitti che possono verificarsi se altre applicazioni usano lo stesso identificatore di messaggio per scopi diversi.

Routing dei messaggi

Il sistema usa due metodi per instradare i messaggi a una procedura di finestra: la pubblicazione di messaggi in una coda first-in first-out denominata coda di messaggi, un oggetto memoria definito dal sistema che archivia temporaneamente i messaggi e l'invio di messaggi direttamente a una routine finestra.

Un messaggio inviato a una coda di messaggi viene chiamato messaggio in coda. Si tratta principalmente del risultato dell'input dell'utente immesso tramite il mouse o la tastiera, ad esempio WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN e messaggi di WM_CHAR . Altri messaggi in coda includono i messaggi timer, paint e quit: WM_TIMER, WM_PAINT e WM_QUIT. La maggior parte degli altri messaggi, che vengono inviati direttamente a una routine finestra, sono chiamati messaggi non accodati.

Messaggi in coda

Il sistema può visualizzare qualsiasi numero di finestre alla volta. Per instradare l'input del mouse e della tastiera alla finestra appropriata, il sistema usa code di messaggi.

Il sistema gestisce una singola coda di messaggi di sistema e una coda di messaggi specifica del thread per ogni thread GUI. Per evitare il sovraccarico della creazione di una coda di messaggi per thread non GUI, tutti i thread vengono creati inizialmente senza una coda di messaggi. Il sistema crea una coda di messaggi specifica del thread solo quando il thread effettua la prima chiamata a una delle funzioni utente specifiche; nessuna chiamata di funzione GUI comporta la creazione di una coda di messaggi.

Ogni volta che l'utente sposta il mouse, fa clic sui pulsanti del mouse o digita sulla tastiera, il driver di dispositivo per il mouse o la tastiera converte l'input in messaggi e li inserisce nella coda dei messaggi di sistema. Il sistema rimuove i messaggi, uno alla volta, dalla coda dei messaggi di sistema, li esamina per determinare la finestra di destinazione e quindi li inserisce nella coda di messaggi del thread che ha creato la finestra di destinazione. La coda di messaggi di un thread riceve tutti i messaggi del mouse e della tastiera per le finestre create dal thread. Il thread rimuove i messaggi dalla coda e indirizza il sistema a inviarli alla procedura di finestra appropriata per l'elaborazione.

Ad eccezione del messaggio di WM_PAINT , del messaggio WM_TIMER e del messaggio WM_QUIT , il sistema invia sempre messaggi alla fine di una coda di messaggi. Ciò garantisce che una finestra riceva i messaggi di input nella sequenza FIFO (First Out) corretta. Il messaggio WM_PAINT , il messaggio WM_TIMER e il messaggio WM_QUIT , tuttavia, vengono mantenuti nella coda e vengono inoltrati alla routine della finestra solo quando la coda non contiene altri messaggi. Inoltre, più messaggi WM_PAINT per la stessa finestra vengono combinati in un singolo messaggio di WM_PAINT , consolidando tutte le parti non valide dell'area client in un'unica area. La combinazione di WM_PAINT messaggi riduce il numero di volte in cui una finestra deve ridisegnare il contenuto dell'area client.

Il sistema invia un messaggio alla coda dei messaggi di un thread compilando una struttura MSG e copiandolo nella coda dei messaggi. Le informazioni in MSG includono: l'handle della finestra per cui è previsto il messaggio, l'identificatore del messaggio, i due parametri del messaggio, l'ora di pubblicazione del messaggio e la posizione del cursore del mouse. Un thread può pubblicare un messaggio nella propria coda di messaggi o nella coda di un altro thread usando la funzione PostMessage o PostThreadMessage .

Un'applicazione può rimuovere un messaggio dalla coda usando la funzione GetMessage . Per esaminare un messaggio senza rimuoverlo dalla coda, un'applicazione può usare la funzione PeekMessage . Questa funzione riempie MSG con informazioni sul messaggio.

Dopo aver rimosso un messaggio dalla coda, un'applicazione può usare la funzione DispatchMessage per indirizzare il sistema a inviare il messaggio a una routine finestra per l'elaborazione. DispatchMessage accetta un puntatore a MSG compilato da una chiamata precedente alla funzione GetMessage o PeekMessage . DispatchMessage passa l'handle della finestra, l'identificatore del messaggio e i due parametri del messaggio alla routine della finestra, ma non passa il tempo in cui il messaggio è stato inserito o la posizione del cursore del mouse. Un'applicazione può recuperare queste informazioni chiamando le funzioni GetMessageTime e GetMessagePos durante l'elaborazione di un messaggio.

Un thread può usare la funzione WaitMessage per restituire il controllo ad altri thread quando non contiene messaggi nella coda dei messaggi. La funzione sospende il thread e non restituisce finché non viene inserito un nuovo messaggio nella coda dei messaggi del thread.

È possibile chiamare la funzione SetMessageExtraInfo per associare un valore alla coda di messaggi del thread corrente. Chiamare quindi la funzione GetMessageExtraInfo per ottenere il valore associato all'ultimo messaggio recuperato dalla funzione GetMessage o PeekMessage .

Messaggi non accodati

I messaggi non accodati vengono inviati immediatamente alla routine della finestra di destinazione, ignorando la coda dei messaggi di sistema e la coda di messaggi thread. Il sistema invia in genere messaggi non accodati per notificare a una finestra di eventi che lo interessano. Ad esempio, quando l'utente attiva una nuova finestra dell'applicazione, il sistema invia alla finestra una serie di messaggi, tra cui WM_ACTIVATE, WM_SETFOCUS e WM_SETCURSOR. Questi messaggi notificano alla finestra che è stato attivato, che l'input della tastiera viene indirizzato alla finestra e che il cursore del mouse è stato spostato all'interno dei bordi della finestra. I messaggi non accodati possono risultare anche quando un'applicazione chiama determinate funzioni di sistema. Ad esempio, il sistema invia il messaggio WM_WINDOWPOSCHANGED dopo che un'applicazione usa la funzione SetWindowPos per spostare una finestra.

Alcune funzioni che inviano messaggi non accodati sono BroadcastSystemMessage, BroadcastSystemMessageEx, SendMessage, SendMessageTimeout e SendNotifyMessage.

Gestione dei messaggi

Un'applicazione deve rimuovere ed elaborare i messaggi inviati alle code di messaggi dei thread. Un'applicazione a thread singolo usa in genere un ciclo di messaggi nella relativa funzione WinMain per rimuovere e inviare messaggi alle procedure di finestra appropriate per l'elaborazione. Le applicazioni con più thread possono includere un ciclo di messaggi in ogni thread che crea una finestra. Le sezioni seguenti descrivono il funzionamento di un ciclo di messaggi e spiegano il ruolo di una routine finestra:

Ciclo di messaggi

Un ciclo di messaggi semplice è costituito da una chiamata di funzione a ognuna di queste tre funzioni: GetMessage, TranslateMessage e DispatchMessage. Si noti che se si verifica un errore, GetMessage restituisce –1, pertanto la necessità di eseguire test speciali.

MSG msg;
BOOL bRet;

while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

La funzione GetMessage recupera un messaggio dalla coda e lo copia in una struttura di tipo MSG. Restituisce un valore diverso da zero, a meno che non incontri il messaggio WM_QUIT , nel qual caso restituisce FALSE e termina il ciclo. In un'applicazione a thread singolo, la fine del ciclo di messaggi è spesso il primo passaggio per chiudere l'applicazione. Un'applicazione può terminare il proprio ciclo usando la funzione PostQuitMessage , in genere in risposta al messaggio WM_DESTROY nella procedura della finestra della finestra principale dell'applicazione.

Se si specifica un handle di finestra come secondo parametro di GetMessage, solo i messaggi per la finestra specificata vengono recuperati dalla coda. GetMessage può anche filtrare i messaggi nella coda, recuperando solo i messaggi che rientrano in un intervallo specificato. Per altre informazioni sul filtro dei messaggi, vedere Filtro messaggi.

Il ciclo di messaggi di un thread deve includere TranslateMessage se il thread deve ricevere l'input di carattere dalla tastiera. Il sistema genera messaggi di chiave virtuale (WM_KEYDOWN e WM_KEYUP) ogni volta che l'utente preme un tasto. Un messaggio con chiave virtuale contiene un codice di chiave virtuale che identifica il tasto premuto, ma non il valore del carattere. Per recuperare questo valore, il ciclo di messaggi deve contenere TranslateMessage, che converte il messaggio di chiave virtuale in un messaggio di carattere (WM_CHAR) e lo inserisce nuovamente nella coda dei messaggi dell'applicazione. Il messaggio di caratteri può quindi essere rimosso dopo un'iterazione successiva del ciclo di messaggi e inviato a una routine di finestra.

La funzione DispatchMessage invia un messaggio alla routine della finestra associata all'handle di finestra specificato nella struttura MSG . Se l'handle di finestra è HWND_TOPMOST, DispatchMessage invia il messaggio alle procedure della finestra di tutte le finestre di primo livello del sistema. Se l'handle della finestra è NULL, DispatchMessage non esegue alcuna operazione con il messaggio.

Il thread principale di un'applicazione avvia il ciclo di messaggi dopo l'inizializzazione dell'applicazione e la creazione di almeno una finestra. Dopo l'avvio, il ciclo di messaggi continua a recuperare i messaggi dalla coda dei messaggi del thread e per inviarli alle finestre appropriate. Il ciclo di messaggi termina quando la funzione GetMessage rimuove il messaggio WM_QUIT dalla coda dei messaggi.

Per una coda di messaggi è necessario un solo ciclo di messaggi, anche se un'applicazione contiene molte finestre. DispatchMessage invia sempre il messaggio alla finestra appropriata; ciò è dovuto al fatto che ogni messaggio nella coda è una struttura MSG che contiene l'handle della finestra a cui appartiene il messaggio.

È possibile modificare un ciclo di messaggi in diversi modi. Ad esempio, è possibile recuperare i messaggi dalla coda senza inviarli a una finestra. Ciò è utile per le applicazioni che pubblicano messaggi che non specificano una finestra. È anche possibile indirizzare GetMessage alla ricerca di messaggi specifici, lasciando altri messaggi nella coda. Ciò è utile se è necessario ignorare temporaneamente l'ordine FIFO consueto della coda di messaggi.

Un'applicazione che usa i tasti di scelta rapida deve essere in grado di convertire i messaggi della tastiera in messaggi di comando. A tale scopo, il ciclo di messaggi dell'applicazione deve includere una chiamata alla funzione TranslateAccelerator . Per altre informazioni sui tasti di scelta rapida, vedere Tasti di scelta rapida.

Se un thread usa una finestra di dialogo senza modalità, il ciclo di messaggi deve includere la funzione IsDialogMessage in modo che la finestra di dialogo possa ricevere l'input da tastiera.

Routine finestra

Una routine finestra è una funzione che riceve ed elabora tutti i messaggi inviati alla finestra. Ogni classe finestra dispone di una routine finestra e ogni finestra creata con tale classe usa la stessa routine della finestra per rispondere ai messaggi.

Il sistema invia un messaggio a una routine finestra passando i dati del messaggio come argomenti alla routine. La procedura della finestra esegue quindi un'azione appropriata per il messaggio; controlla l'identificatore del messaggio e, durante l'elaborazione del messaggio, usa le informazioni specificate dai parametri del messaggio.

Una routine della finestra in genere non ignora un messaggio. Se non elabora un messaggio, deve inviare di nuovo il messaggio al sistema per l'elaborazione predefinita. La procedura della finestra esegue questa operazione chiamando la funzione DefWindowProc , che esegue un'azione predefinita e restituisce un risultato del messaggio. La routine della finestra deve quindi restituire questo valore come risultato del proprio messaggio. La maggior parte delle procedure di finestra elabora solo alcuni messaggi e passa gli altri al sistema chiamando DefWindowProc.

Poiché una procedura di finestra è condivisa da tutte le finestre appartenenti alla stessa classe, può elaborare i messaggi per diverse finestre. Per identificare la finestra specifica interessata dal messaggio, una procedura della finestra può esaminare l'handle della finestra passato con un messaggio. Per altre informazioni sulle procedure delle finestre, vedere Procedure di finestra.

Filtro messaggi

Un'applicazione può scegliere messaggi specifici da recuperare dalla coda di messaggi (ignorando altri messaggi) usando la funzione GetMessage o PeekMessage per specificare un filtro dei messaggi. Il filtro è un intervallo di identificatori di messaggio (specificato da un primo e ultimo identificatore), un handle di finestra o entrambi. GetMessage e PeekMessage usano un filtro messaggi per selezionare i messaggi da recuperare dalla coda. Il filtro dei messaggi è utile se un'applicazione deve cercare la coda dei messaggi che sono arrivati più avanti nella coda. È anche utile se un'applicazione deve elaborare i messaggi di input (hardware) prima di elaborare i messaggi pubblicati.

Le costanti WM_KEYFIRST e WM_KEYLAST possono essere usate come valori di filtro per recuperare tutti i messaggi da tastiera; le costanti WM_MOUSEFIRST e WM_MOUSELAST possono essere usate per recuperare tutti i messaggi del mouse.

Qualsiasi applicazione che filtra i messaggi deve assicurarsi che sia possibile pubblicare un messaggio che soddisfi il filtro dei messaggi. Ad esempio, se un'applicazione filtra un messaggio di WM_CHAR in una finestra che non riceve l'input della tastiera, la funzione GetMessage non restituisce. Questa operazione "blocca" in modo efficace l'applicazione.

Registrazione e invio di messaggi

Qualsiasi applicazione può pubblicare e inviare messaggi. Come il sistema, un'applicazione pubblica un messaggio copiandolo in una coda di messaggi e invia un messaggio passando i dati del messaggio come argomenti a una routine di finestra. Per pubblicare messaggi, un'applicazione usa la funzione PostMessage . Un'applicazione può inviare un messaggio chiamando la funzione SendMessage, BroadcastSystemMessage, SendMessageCallback, SendMessageTimeout, SendNotifyMessage o SendDlgItemMessage .

Registrazione di messaggi

Un'applicazione pubblica in genere un messaggio per inviare una notifica a una finestra specifica per eseguire un'attività. PostMessage crea una struttura MSG per il messaggio e copia il messaggio nella coda del messaggio. Il ciclo del messaggio dell'applicazione recupera il messaggio e lo invia alla procedura di finestra appropriata.

Un'applicazione può pubblicare un messaggio senza specificare una finestra. Se l'applicazione fornisce un handle di finestra NULL durante la chiamata a PostMessage, il messaggio viene inviato alla coda associata al thread corrente. Poiché non viene specificato alcun handle di finestra, l'applicazione deve elaborare il messaggio nel ciclo del messaggio. Si tratta di un modo per creare un messaggio che si applica all'intera applicazione, anziché a una finestra specifica.

A volte, potresti voler inviare un messaggio a tutte le finestre di primo livello nel sistema. Un'applicazione può inviare un messaggio a tutte le finestre di primo livello chiamando PostMessage e specificando HWND_TOPMOST nel parametro hwnd .

Un errore di programmazione comune consiste nel presupporre che la funzione PostMessage inserisce sempre un messaggio. Non è vero quando la coda del messaggio è piena. Un'applicazione deve controllare il valore restituito della funzione PostMessage per determinare se il messaggio è stato pubblicato e, se non è stato, ripubblicarlo.

sending messages

Un'applicazione invia in genere un messaggio per inviare una notifica a una routine della finestra per eseguire immediatamente un'attività. La funzione SendMessage invia il messaggio alla routine della finestra corrispondente alla finestra specificata. La funzione attende fino al completamento dell'elaborazione della routine della finestra e quindi restituisce il risultato del messaggio. Le finestre padre e figlio comunicano spesso inviando messaggi tra loro. Ad esempio, una finestra padre con un controllo di modifica come finestra figlio può impostare il testo del controllo inviando un messaggio a esso. Il controllo può inviare una notifica alla finestra padre delle modifiche apportate al testo eseguito dall'utente inviando messaggi di nuovo all'elemento padre.

La funzione SendMessageCallback invia anche un messaggio alla routine della finestra corrispondente alla finestra specificata. Tuttavia, questa funzione restituisce immediatamente. Dopo che la routine della finestra elabora il messaggio, il sistema chiama la funzione di callback specificata. Per altre informazioni sulla funzione di callback, vedere la funzione SendAsyncProc .

In alcuni casi, è possibile inviare un messaggio a tutte le finestre di primo livello nel sistema. Ad esempio, se l'applicazione modifica il tempo di sistema, deve inviare una notifica a tutte le finestre di primo livello sulla modifica inviando un messaggio di WM_TIMECHANGE . Un'applicazione può inviare un messaggio a tutte le finestre di primo livello chiamando SendMessage e specificando HWND_TOPMOST nel parametro hwnd . È anche possibile trasmettere un messaggio a tutte le applicazioni chiamando la funzione BroadcastSystemMessage e specificando BSM_APPLICATIONS nel parametro lpdwRecipients .

Usando la funzione InSendMessage o InSendMessageEx, una routine della finestra può determinare se elabora un messaggio inviato da un altro thread. Questa funzionalità è utile quando l'elaborazione dei messaggi dipende dall'origine del messaggio.

Deadlock dei messaggi

Thread che chiama la funzione SendMessage per inviare un messaggio a un altro thread non può continuare l'esecuzione fino a quando la routine della finestra che riceve il messaggio restituisce. Se il thread ricevente restituisce il controllo durante l'elaborazione del messaggio, il thread di invio non può continuare l'esecuzione, perché è in attesa che SendMessage venga restituito. Se il thread di ricezione è collegato alla stessa coda del mittente, può causare un deadlock dell'applicazione. Si noti che il journal collega i thread alla stessa coda.

Si noti che il thread di ricezione non deve essere controllato in modo esplicito; la chiamata di una delle funzioni seguenti può causare il controllo implicito di un thread.

Per evitare potenziali deadlock nell'applicazione, è consigliabile usare le funzioni SendNotifyMessage o SendMessageTimeout . In caso contrario, una routine della finestra può determinare se un messaggio ricevuto è stato inviato da un altro thread chiamando la funzione InSendMessage o InSendMessageEx. Prima di chiamare una delle funzioni nell'elenco precedente durante l'elaborazione di un messaggio, la procedura della finestra deve prima chiamare InSendMessage o InSendMessageEx. Se questa funzione restituisce TRUE, la procedura della finestra deve chiamare la funzione ReplyMessage prima di qualsiasi funzione che causa il controllo di rendimento del thread.

Trasmissione di messaggi

Ogni messaggio è costituito da un identificatore di messaggio e due parametri, wParam e lParam. L'identificatore del messaggio è un valore univoco che specifica lo scopo del messaggio. I parametri forniscono informazioni aggiuntive specifiche del messaggio, ma il parametro wParam è in genere un valore di tipo che fornisce altre informazioni sul messaggio.

Una trasmissione di messaggi è semplicemente l'invio di un messaggio a più destinatari nel sistema. Per trasmettere un messaggio da un'applicazione, usare la funzione BroadcastSystemMessage , specificando i destinatari del messaggio. Anziché specificare singoli destinatari, è necessario specificare uno o più tipi di destinatari. Questi tipi sono applicazioni, driver installabili, driver di rete e driver di dispositivo a livello di sistema. Il sistema invia messaggi di trasmissione a tutti i membri di ogni tipo specificato.

Il sistema trasmette in genere messaggi in risposta alle modifiche che si svolgono all'interno di driver di dispositivo a livello di sistema o componenti correlati. Il driver o il componente correlato trasmette il messaggio alle applicazioni e ad altri componenti per notificarli alla modifica. Ad esempio, il componente responsabile delle unità disco trasmette un messaggio ogni volta che il driver del dispositivo per l'unità disco floppy rileva una modifica del supporto, ad esempio quando l'utente inserisce un disco nell'unità.

Il sistema trasmette messaggi ai destinatari in questo ordine: driver di dispositivo a livello di sistema, driver di rete, driver di rete, driver di installazione e applicazioni. Ciò significa che i driver di dispositivo a livello di sistema, se scelti come destinatari, ottengono sempre la prima opportunità di rispondere a un messaggio. All'interno di un determinato tipo di destinatario, nessun driver viene garantito di ricevere un messaggio specificato prima di qualsiasi altro driver. Ciò significa che un messaggio destinato a un driver specifico deve avere un identificatore di messaggio univoco globale in modo che nessun altro driver lo elabora in modo involontario.

È anche possibile trasmettere messaggi a tutte le finestre di primo livello specificando HWND_BROADCAST nella funzione SendMessage, SendMessageCallback, SendMessageTimeout o SendNotifyMessageMessage .

Le applicazioni ricevono messaggi tramite la procedura della finestra delle finestre di primo livello. I messaggi non vengono inviati a finestre figlio. I servizi possono ricevere messaggi tramite una routine finestra o i gestori di controllo del servizio.

Nota

I driver di dispositivo a livello di sistema usano una funzione correlata a livello di sistema per trasmettere i messaggi di sistema.

Messaggi di query

È possibile creare messaggi personalizzati e usarli per coordinare le attività tra le applicazioni e altri componenti nel sistema. Ciò è particolarmente utile se sono stati creati i driver installati o i driver di dispositivo a livello di sistema. I messaggi personalizzati possono trasportare informazioni da e verso il driver e le applicazioni che usano il driver.

Per eseguire il polling dei destinatari per l'autorizzazione per eseguire un'azione specificata, usare un messaggio di query. È possibile generare messaggi di query personalizzati impostando il valore BSF_QUERY nel parametro dwFlags quando si chiama BroadcastSystemMessage. Ogni destinatario del messaggio di query deve restituire TRUE per la funzione per inviare il messaggio al destinatario successivo. Se qualsiasi destinatario restituisce BROADCAST_QUERY_DENY, la trasmissione termina immediatamente e la funzione restituisce uno zero.