Condividi tramite


Informazioni su messaggi e code di messaggio

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

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

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

In questa sezione vengono illustrati gli argomenti seguenti:

Messaggi di Windows

Il sistema passa l'input a una routine finestra sotto forma di messaggio . I messaggi vengono generati sia dal sistema che dalle applicazioni. Il sistema genera un messaggio a 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 inoltre messaggi in risposta alle modifiche apportate al sistema da un'applicazione, ad esempio quando un'applicazione modifica il pool di risorse del tipo di carattere di sistema o ne ridimensiona una delle finestre. Un'applicazione può generare messaggi per indirizzare le proprie finestre per eseguire attività o per comunicare con le finestre in altre applicazioni.

Il sistema invia un messaggio a una procedura 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 a cui è destinato il messaggio. Il sistema lo usa per determinare quale routine 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 del messaggio WM_PAINT indica alla routine della finestra che l'area client della finestra è stata modificata e deve essere aggiornata.

I parametri del messaggio specificano i dati o la posizione dei dati utilizzati da una routine 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 vengono impostati su NULL. Una routine della finestra deve controllare l'identificatore del messaggio per determinare come interpretare i parametri del messaggio.

Tipi di messaggio

Questa sezione descrive i due tipi di messaggi:

System-Defined Messaggi

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 finestra preregistrate.

Ogni messaggio definito dal sistema ha un identificatore di messaggio univoco e una costante simbolica corrispondente (definita nei file di intestazione di Software Development Kit (SDK) che indica lo scopo del messaggio. Ad esempio, la costante WM_PAINT richiede che una finestra dipinga il relativo 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 animazione Messaggi di controllo animazione e notifiche di controllo animazione
BCM, BCN, BMe BN Controllo del Pulsante Messaggi di controllo dei pulsanti e Notifiche di controllo dei pulsanti
CB e CBN Controllo del ComboBox e notifiche di controllo ComboBox
CBEM e CBEN Controllo ComboBoxEx Messaggi ComboBoxEx e Notifiche ComboBoxEx
CCM Controllo generale messaggi di controllo
CDM Finestra di dialogo Comune messaggi comuni della finestra di dialogo
DFM Menu di scelta rapida predefinito Messaggi e Notifiche della Shell
DL Casella di elenco trascinabile Notifiche di trascinamento della casella di elenco
DM Controllo pulsante predefinito Messaggi Finestra di dialogo
DTM e DTN Controllo selezione data e ora Messaggi di selezione data e ora e Notifiche di selezione data e ora
EM e EN Modifica controllo Messaggi di controllo modifica, Notifiche di controllo modifica, Messaggi di modifica avanzatae Notifiche di modifica avanzata
HDM e HDN Controllo intestazione Messaggi di controllo dell'intestazione e notifiche di controllo dell'intestazione
HKM Controllo dei tasti di scelta rapida Messaggi di controllo dei tasti di scelta rapida
IPM e IPN Controllo degli indirizzi IP messaggi degli indirizzi IP e notifiche degli indirizzi IP
LB e LBN Controllo casella di riepilogo messaggi delle caselle di riepilogo e notifiche delle caselle di riepilogo
LM Controllo SysLink Messaggi di Controllo SysLink
LVM e LVN Controllo visualizzazione elenco visualizzazione elenco messaggi e visualizzazione elenco notifiche
MCM e MCN Controllo calendario mese Messaggi del Calendario Mensile e Notifiche del Calendario Mensile
PBM Barra di progresso messaggi della barra di avanzamento
PGM e PGN Controllo di navigazione Messaggi di controllo pager e notifiche di controllo pager
PSM e PSN Scheda delle proprietà Messaggi delle finestre delle proprietà e Notifiche delle finestre delle proprietà
RB e RBN Controllo Rebar Messaggi di controllo dei ferri e Notifiche di controllo dei ferri
SB SBN e Finestra barra di stato e notifiche della barra di stato
SBM Controllo barra di scorrimento I 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 messaggi di controllo della barra degli strumenti e notifiche di controllo della barra degli strumenti
TBM e TRBN Controllo Trackbar Messaggi di controllo della barra di avanzamento e notifiche di controllo della barra di avanzamento
TCM e TCN Controllo Struttura a schede Messaggi di controllo scheda e Notifiche di controllo scheda
TDM e TDN Finestra di dialogo delle attività Messaggi della finestra di dialogo attività e Notifiche della finestra di dialogo attività
TTM e TTN Controllo tooltip Messaggi di controllo per descrizione comando e Notifiche di controllo per descrizione comando
TVM e TVN Controllo visualizzazione albero Messaggi della visualizzazione ad albero e notifiche della visualizzazione ad albero
UDM e UDN Controllo su e giù Up-Down Messaggi e Up-Down Notifiche
WM Generale
Messaggi degli Appunti
Notifiche degli Appunti
notifiche comuni della finestra di dialogo
Notifiche del cursore
Messaggio di copia dati
Messaggi della gestione finestre del desktop
Messaggi di Gestione dei Dispositivi
Finestra di dialogo Notifiche
messaggi di Scambio di dati dinamici
Notifiche di Dynamic Data Exchange
Notifiche Hook
messaggi dell'acceleratore di tastiera
Le Notifiche dell'Acceleratore di Tastiera
Messaggi di Input da Tastiera
notifiche di input da tastiera
Menu Notifiche
notifiche di input del mouse
Messaggi dell'interfaccia multipla del documento
Notifiche di input grezzo
Notifica Barra di Scorrimento
Notifiche del Timer
Messaggi Finestra
notifiche finestra

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

Application-Defined Messaggi

Un'applicazione può creare messaggi da usare dalle proprie finestre o per comunicare con le 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 valori di identificatore di messaggio nell'intervallo 0x0000 attraverso 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 di 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.

Instradamento dei messaggi

Il sistema usa due metodi per instradare i messaggi a una routine finestra: la registrazione 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 invia messaggi direttamente a una routine della 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_KEYDOWNe WM_CHAR messaggi. Altri messaggi in coda includono i messaggi timer, paint e quit: WM_TIMER, WM_PAINTe WM_QUIT. La maggior parte degli altri messaggi, inviati direttamente a una routine finestra, vengono chiamati messaggi non accodati.

Messaggi in coda

Il sistema può visualizzare un numero qualsiasi di finestre alla volta. Per inviare 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 di 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. In questo modo, una finestra riceve i messaggi di input nella corretta sequenza FIFO (Primo a entrare, primo a uscire). 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 di 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 di messaggi di un thread riempiendo una struttura MSG e poi copiandola nella coda di messaggi. Le informazioni contenute 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 funzionePostMessageo PostThreadMessage.

Un'applicazione può rimuovere un messaggio dalla sua 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 funzioneDispatchMessageper indirizzare il sistema a inviare il messaggio a una routine finestra per l'elaborazione. DispatchMessage accetta un puntatore a MSG che è stato 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 funzioniGetMessageTimee GetMessagePos durante l'elaborazione di un messaggio.

Un thread può usare la funzioneWaitMessageper 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 funzionesetMessageExtraInfoper associare un valore alla coda di messaggi del thread corrente. Chiamare quindi la funzione diGetMessageExtraInfoper ottenere il valore associato all'ultimo messaggio recuperato dalla funzioneGetMessageo PeekMessage.

Messaggi non in coda

I messaggi non accodati vengono inviati immediatamente alla procedura della finestra di destinazione, saltando la coda dei messaggi di sistema e la coda di messaggi del 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_SETFOCUSe 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 entro i bordi della finestra. I messaggi non accodati possono verificarsi anche quando un'applicazione chiama determinate funzioni di sistema. Ad esempio, il sistema invia il messaggio di WM_WINDOWPOSCHANGED dopo che un'applicazione usa la funzioneSetWindowPosper spostare una finestra.

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

Gestione dei messaggi

Un'applicazione deve rimuovere ed elaborare i messaggi inseriti nelle code dei messaggi dei suoi thread. Un'applicazione a thread singolo usa in genere un ciclo di messaggi nella 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, TranslateMessagee DispatchMessage. Si noti che se si verifica un errore, GetMessage restituisce -1, pertanto la necessità di un test speciale.

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 funzioneGetMessagerecupera un messaggio dalla coda e lo copia in una struttura di tipo MSG. Restituisce un valore diverso da zero, a meno che non venga rilevato il messaggio di WM_QUIT, nel qual caso restituisce false e termina il ciclo. In un'applicazione a thread singolo, la chiusura 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 principale dell'applicazione.

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

Il ciclo di messaggi di un thread deve includere TranslateMessage se il thread deve ricevere l'input di caratteri dalla tastiera. Il sistema genera messaggi di chiave virtuale (WM_KEYDOWN e WM_KEYUP) ogni volta che l'utente preme un tasto. Un messaggio di chiave virtuale contiene un codice di chiave virtuale che identifica il tasto premuto, ma non il relativo valore di 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 nella coda dei messaggi dell'applicazione. Il messaggio di caratteri può quindi essere eliminato durante una successiva iterazione del ciclo di messaggi e inviato a una procedura finestra.

La funzione DispatchMessage invia un messaggio alla procedura della finestra associata all'handle di finestra specificato nella struttura MSG. Se l'handle di finestra è HWND_TOPMOST, DispatchMessage invia il messaggio alle procedure di tutte le finestre di primo livello del sistema. Se l'handle di 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 di inviarli alle finestre appropriate. Il ciclo di messaggi termina quando la funzioneGetMessagerimuove il messaggio di WM_QUIT dalla coda di 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; questo perché 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 per cercare 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 ulteriori informazioni sui tasti di accelerazione, vedere Tasti di Accelerazione.

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

La procedura finestra

Una routine finestra è una funzione che riceve ed elabora tutti i messaggi inviati alla finestra. Ogni classe finestra ha 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 restituire 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 finestra elabora solo alcuni messaggi e passa gli altri al sistema chiamando DefWindowProc.

Poiché una routine 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 routine della finestra può esaminare l'handle di finestra passato con un messaggio. Per altre informazioni sulle procedure di finestra, vedere Window Procedures.

Filtro messaggi

Un'applicazione può scegliere messaggi specifici da recuperare dalla coda di messaggi (ignorando altri messaggi) usando la funzioneGetMessageo PeekMessage per specificare un filtro di messaggio. Il filtro è un intervallo di identificatori di messaggio (specificati da un primo e ultimo identificatore), un handle di finestra o entrambi. GetMessage e PeekMessage usano un filtro dei messaggi per selezionare i messaggi da recuperare dalla coda. Il filtro dei messaggi è utile se un'applicazione deve cercare nella coda dei messaggi i messaggi che sono arrivati più avanti nella coda. È utile anche se un'applicazione deve elaborare 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 utilizzate per recuperare tutti i messaggi del mouse.

Qualsiasi applicazione che filtra i messaggi deve garantire che un messaggio che soddisfi il filtro messaggi possa essere pubblicato. Ad esempio, se un'applicazione filtra un messaggio di WM_CHAR in una finestra che non riceve l'input da tastiera, la funzioneGetMessagenon restituisce. In questo modo l'applicazione viene "bloccata".

Pubblicazione e invio di messaggi

Qualsiasi applicazione può pubblicare e inviare messaggi. Analogamente al 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 finestra. Per pubblicare messaggi, un'applicazione usa la funzionePostMessage. Un'applicazione può inviare un messaggio chiamando ilSendMessage, BroadcastSystemMessage, SendMessageCallback, SendMessageTimeout, SendNotifyMessageo funzione SendDlgItemMessage.

Inserimento di messaggi

Un'applicazione invia in genere un messaggio per notificare a una finestra specifica di eseguire un'attività. PostMessage crea una strutturaMSG per il messaggio e lo copia nella coda dei messaggi. Il ciclo di messaggi 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 quando si chiama 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 di messaggi. Si tratta di un modo per creare un messaggio che si applica all'intera applicazione, anziché a una finestra specifica.

In alcuni casi, potresti voler inviare un messaggio a tutte le finestre di primo livello del sistema. Un'applicazione può pubblicare un messaggio in 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 invia sempre un messaggio. Questo non vale quando la coda dei messaggi è piena. Un'applicazione deve controllare il valore restituito della funzione PostMessage per determinare se il messaggio è stato pubblicato e, in caso contrario, ripubblicarlo.

Invio di messaggi

Un'applicazione invia in genere un messaggio per notificare a una routine finestra di eseguire immediatamente un'attività. La funzione SendMessage invia il messaggio alla procedura 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 spesso comunicano inviando messaggi l'uno all'altro. Ad esempio, una finestra padre con un controllo di modifica come finestra figlio può impostare il testo del controllo inviando un messaggio. Il controllo può notificare la finestra padre delle modifiche apportate al testo dall'utente inviando messaggi alla finestra padre.

La funzioneSendMessageCallbackinvia 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 funzioneSendAsyncProc.

In alcuni casi, è possibile inviare un messaggio a tutte le finestre di primo livello del sistema. Ad esempio, se l'applicazione modifica l'ora di sistema, deve notificare a tutte le finestre di primo livello la 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 funzioneBroadcastSystemMessagee specificando BSM_APPLICATIONS nel parametro lpdwRecipients.

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

Stallo dei messaggi

Un thread che chiama la funzioneSendMessageper inviare un messaggio a un altro thread non può continuare l'esecuzione fino a quando non viene restituita la routine della finestra che riceve il messaggio. 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 venga restituito SendMessage. Se il thread di ricezione è collegato alla stessa coda del mittente, potrebbe causare un deadlock nell'applicazione. Si noti che gli hook del journal collegano i thread alla stessa coda.

Si noti che il thread ricevente non deve produrre il controllo 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 diSendNotifyMessageo SendMessageTimeout. In caso contrario, una routine 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 routine 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 comporti il passaggio del controllo del thread.

Trasmissione di messaggi

Ogni messaggio è costituito da un identificatore di messaggio e da 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.

Un messaggio trasmesso è 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 diffusione a tutti i membri di ogni tipo specificato.

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

Il sistema trasmette i messaggi ai destinatari in questo ordine: driver di dispositivo a livello di sistema, driver di rete, driver di rete, driver installabili 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, non è garantito che nessun driver riceva un determinato messaggio prima di qualsiasi altro driver. Ciò significa che un messaggio destinato a un driver specifico deve avere un identificatore di messaggio univoco a livello globale in modo che nessun altro driver lo elabori involontariamente.

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

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

Nota

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

Messaggi di interrogazione

È possibile creare messaggi personalizzati e usarli per coordinare le attività tra le applicazioni e altri componenti del sistema. Ciò è particolarmente utile se hai creato i tuoi driver installabili o driver di dispositivo a livello di sistema. I messaggi personalizzati possono contenere informazioni da e verso il driver e le applicazioni che usano il driver.

Per sondare i destinatari per ottenere il permesso di compiere una determinata azione, usare un messaggio di interrogazione . È possibile generare messaggi di query personalizzati impostando il valore di BSF_QUERY nel parametro dwFlags quando si chiama BroadcastSystemMessage. Ogni destinatario del messaggio di query deve restituire TRUE affinché la funzione invii il messaggio al destinatario successivo. Se un destinatario restituisce BROADCAST_QUERY_DENY, la trasmissione termina immediatamente e la funzione restituisce zero.