Partager via


À propos des messages et des files d’attente de messages

Contrairement aux applications basées sur MS-DOS, les applications Windows sont pilotées par les événements. Ils n’effectuent pas d’appels de fonction explicites (tels que les appels de bibliothèque runtime C) pour obtenir une entrée. À la place, ils attendent que le système leur transmette des données d’entrée.

Le système transmet toutes les entrées d’une application aux différentes fenêtres de l’application. Chaque fenêtre a une fonction, appelée procédure de fenêtre, que le système appelle chaque fois qu’il a une entrée pour la fenêtre. La procédure de fenêtre traite l’entrée et retourne le contrôle au système. Pour plus d’informations sur les procédures de fenêtre, consultez Procédures de fenêtre.

Si une fenêtre de niveau supérieur cesse de répondre aux messages pendant plus de plusieurs secondes, le système considère que la fenêtre ne répond pas. Dans ce cas, le système masque la fenêtre et la remplace par une fenêtre fantôme qui a le même ordre Z, emplacement, taille et attributs visuels. Cela permet à l’utilisateur de le déplacer, de le redimensionner ou même de fermer l’application. Toutefois, il s’agit des seules actions disponibles, car l’application ne répond pas réellement. Lorsqu’il est en mode débogueur, le système ne génère pas de fenêtre fantôme.

Cette section décrit les rubriques suivantes :

Messages de Windows

Le système transmet l’entrée à une procédure de fenêtre sous la forme d’un message. Les messages sont générés par le système et les applications. Le système génère un message à chaque événement d’entrée, par exemple, lorsque l’utilisateur tape, déplace la souris ou clique sur un contrôle tel qu’une barre de défilement. Le système génère également des messages en réponse aux modifications apportées par le système par une application, par exemple lorsqu’une application modifie le pool de ressources de police système ou redimensionne l’une de ses fenêtres. Une application peut générer des messages pour diriger ses propres fenêtres pour effectuer des tâches ou communiquer avec des fenêtres dans d’autres applications.

Le système envoie un message à une procédure de fenêtre avec un ensemble de quatre paramètres : un handle de fenêtre, un identificateur de message et deux valeurs appelées paramètres de message. Le handle de fenêtre identifie la fenêtre pour laquelle le message est destiné. Le système l’utilise pour déterminer quelle procédure de fenêtre doit recevoir le message.

Un identificateur de message est une constante nommée qui identifie l’objectif d’un message. Lorsqu’une procédure de fenêtre reçoit un message, elle utilise un identificateur de message pour déterminer comment traiter le message. Par exemple, l’identificateur de message WM_PAINT indique à la procédure de fenêtre que la zone cliente de la fenêtre a changé et doit être repeinte.

Les paramètres de message spécifient des données ou l’emplacement des données utilisées par une procédure de fenêtre lors du traitement d’un message. La signification et la valeur des paramètres du message dépendent du message. Un paramètre de message peut contenir un entier, des indicateurs de bits packés, un pointeur vers une structure contenant des données supplémentaires, et ainsi de suite. Lorsqu’un message n’utilise pas de paramètres de message, ils sont généralement définis sur NULL. Une procédure de fenêtre doit vérifier l’identificateur du message pour déterminer comment interpréter les paramètres du message.

Types de messages

Cette section décrit les deux types de messages :

Messages définis par le système

Le système envoie ou publie un message défini par le système lorsqu’il communique avec une application. Il utilise ces messages pour contrôler les opérations des applications et fournir des informations d’entrée et d’autres informations aux applications à traiter. Une application peut également envoyer ou publier des messages définis par le système. Les applications utilisent généralement ces messages pour contrôler l’opération des fenêtres de contrôle créées à l’aide de classes de fenêtre préinscritées.

Chaque message défini par le système a un identificateur de message unique et une constante symbolique correspondante (définie dans les fichiers d’en-tête du kit de développement logiciel (SDK) qui indique l’objectif du message. Par exemple, la constante WM_PAINT demande qu’une fenêtre peint son contenu.

Les constantes symboliques spécifient la catégorie à laquelle appartiennent les messages définis par le système. Le préfixe de la constante identifie le type de fenêtre qui peut interpréter et traiter le message. Voici les préfixes et leurs catégories de messages associées.

Préfixe Catégorie de message Documentation
ABM et ABN Barre d’outils d’application de bureau Messages et notifications Shell
ACM et ACN Contrôle d’animation Messages de contrôle d’animation et notifications de contrôle d’animation
BCM, BCN, BM et BN Contrôle de bouton Messages de contrôle de bouton et notifications de contrôle de bouton
CB et CBN ComboBox, contrôle Messages de contrôle ComboBox et notifications de contrôle ComboBox
CBEM et CBEN ComboBoxEx, contrôle Messages ComboBoxEx et notifications ComboBoxEx
CCM Contrôle général contrôler les messages
CDM Boîte de dialogue commune Messages de boîte de dialogue courants
DFM Menu contextuel par défaut Messages and notifications Shell
DL Faire glisser la zone de liste Notifications de la boîte de liste déroulante
DM Contrôle de bouton Push par défaut Messages de la boîte de dialogue
DTM et DTN Contrôle du sélecteur de date et d’heure Messages du sélecteur de date et d’heure et notifications du sélecteur de date et d’heure
EM et EN Modifier le contrôle Modifier les messages de contrôle, Modifier les notifications de contrôle, Messages d'édition enrichie, et Notifications d'édition enrichie
HDM et HDN Contrôle d’en-tête Messages de contrôle d’en-tête et notifications de contrôle d’en-tête
HKM Contrôle de touche d’accès rapide Messages de contrôle de touche d’accès rapide
IPM et IPN Contrôle d’adresse IP Messages d’adresse IP et notifications d’adresse IP
LB et LBN Contrôle de zone de liste Messages de boîte de liste et notifications de boîte de liste
LM Contrôle SysLink messages de contrôle SysLink
LVM et LVN Contrôle d’affichage de liste Messages en vue de liste et Notifications en vue de liste
MCM et MCN Contrôle du calendrier mensuel Messages de calendrier mensuels et notifications de calendrier mensuelles
PBM Barre de progression Messages de Barre de Progression
PGM et PGN Contrôle de pagination Messages de contrôle du pager et notifications de contrôle du pager
PSM et PSN Feuille de propriétés Messages de feuille de propriétés et notifications de feuille de propriétés
RB et RBN Contrôles rebar Messages de contrôle de barre d'armature et Notifications de contrôle de barre d'armature
SB et SBN Fenêtre barre d’état Messages de barre d’état et notifications de barre d’état
SBM Contrôle de barre de défilement messages de barre de défilement
SMC Menu Shell Messages et notifications Shell
STM et STN Contrôle statique Messages de contrôle statique et notifications de contrôle statique
TB et TBN Barre d’outils Messages de contrôle de barre d’outils et notifications de contrôle de barre d’outils
TBM et TRBN Contrôle de barre de défilement Messages de contrôle Trackbar et notifications de contrôle Trackbar
TCM et TCN Contrôle Tab Messages de contrôle d'onglet et notifications de contrôle d'onglet
TDM et TDN Boîte de dialogue des tâches Messages de boîte de dialogue de tâche et notifications de boîte de dialogue de tâche
TTM et TTN Contrôle des info-bulles Messages de contrôle des info-bulles et Notifications de contrôle des info-bulles
TVM et TVN Contrôle d’arborescence Messages en vue arborescente et notifications en vue arborescente
UDM et UDN Contrôle haut-bas Up-Down Messages et Up-Down Notifications
WM Généralités
Messages du Presse-papiers
Notifications du Presse-papiers
Notifications de boîte de dialogue courantes
Notifications du curseur
Message de copie de données
Messages du Gestionnaire de fenêtres de bureau
messages de gestion des appareils
notifications de boîte de dialogue
Messages d’échange de données dynamiques
Notifications d’échange de données dynamiques
Notifications de hook
messages de l’accélérateur de clavier
notifications de l’accélérateur clavier
messages d’entrée clavier
notifications d’entrée au clavier
Notifications de menu
Notifications d’entrée de souris
Messages d’interface de document multiples
notifications d’entrée brutes
notifications de barre de défilement
Notifications du minuteur
messages de fenêtre
notifications de fenêtre

Les messages généraux de fenêtre couvrent un large éventail d’informations et de demandes, notamment les messages pour l’entrée de souris et le clavier, le menu et la boîte de dialogue, la création et la gestion des fenêtres et l’échange de données dynamiques (DDE).

Messages définis par l’application

Une application peut créer des messages à utiliser par ses propres fenêtres ou communiquer avec des fenêtres dans d’autres processus. Si une application crée ses propres messages, la procédure de fenêtre qui les reçoit doit interpréter les messages et fournir un traitement approprié.

Les valeurs d’identificateur de message sont utilisées comme suit :

  • Le système réserve des valeurs d’identificateur de message dans la plage 0x0000 via 0x03FF (la valeur de WM_USER – 1) pour les messages définis par le système. Les applications ne peuvent pas utiliser ces valeurs pour les messages privés.
  • Les valeurs de la plage 0x0400 (valeur de WM_USER) via 0x7FFF sont disponibles pour les identificateurs de message pour les classes de fenêtre privée.
  • Si votre application est marquée comme version 4.0, vous pouvez utiliser des valeurs d’identificateur de message dans la plage 0x8000 (WM_APP) via 0xBFFF pour les messages privés.
  • Le système retourne un identificateur de message dans la plage 0xC000 via 0xFFFF lorsqu’une application appelle la fonction RegisterWindowMessage pour inscrire un message. L’identificateur de message retourné par cette fonction est garanti être unique dans tout le système. L’utilisation de cette fonction empêche les conflits qui peuvent survenir si d’autres applications utilisent le même identificateur de message à des fins différentes.

Routage des messages

Le système utilise deux méthodes pour acheminer les messages vers une procédure de fenêtre : publier des messages dans une file d’attente de première entrée et de première sortie appelée file d’attente de messages, objet mémoire défini par le système qui stocke temporairement les messages et envoie des messages directement à une procédure de fenêtre.

Un message publié dans une file d’attente de messages est appelé message mis en file d’attente. Il s’agit principalement du résultat de l’entrée de l’utilisateur par le biais de la souris ou du clavier, comme WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN et WM_CHAR messages. D’autres messages mis en file d’attente incluent les messages de minuterie, de dessin et de sortie : WM_TIMER, WM_PAINT et WM_QUIT. La plupart des autres messages, qui sont envoyés directement à une procédure de fenêtre, sont appelés messages non mis en file d’attente.

Messages mis en file d’attente

Le système peut afficher n’importe quel nombre de fenêtres à la fois. Pour router l’entrée de la souris et du clavier vers la fenêtre appropriée, le système utilise des files d’attente de messages.

Le système gère une file d’attente de messages système unique et une file d’attente de messages spécifique au thread pour chaque thread d’interface utilisateur. Pour éviter la surcharge de création d’une file d’attente de messages pour les threads non-GUI, tous les threads sont créés initialement sans file d’attente de messages. Le système crée une file d’attente de messages spécifique au thread uniquement lorsque le thread effectue son premier appel à l’une des fonctions utilisateur spécifiques ; aucun appel de fonction GUI n’entraîne la création d’une file d’attente de messages.

Chaque fois que l’utilisateur déplace la souris, clique sur les boutons de la souris ou les types sur le clavier, le pilote de périphérique de la souris ou du clavier convertit l’entrée en messages et les place dans la file d’attente des messages système. Le système supprime les messages, un par un, de la file d’attente des messages système, les examine pour déterminer la fenêtre de destination, puis les publie dans la file d’attente des messages du thread qui a créé la fenêtre de destination. La file d’attente de messages d’un thread reçoit tous les messages de souris et de clavier pour les fenêtres créées par le thread. Le thread supprime les messages de sa file d’attente et dirige le système pour les envoyer à la procédure de fenêtre appropriée pour le traitement.

À l’exception du message WM_PAINT , du message WM_TIMER et du message WM_QUIT , le système publie toujours des messages à la fin d’une file d’attente de messages. Cela garantit qu’une fenêtre reçoit ses messages d’entrée dans la séquence de première sortie (FIFO) appropriée. Le message WM_PAINT , le message WM_TIMER et le message WM_QUIT , toutefois, sont conservés dans la file d’attente et sont transférés à la procédure de fenêtre uniquement lorsque la file d’attente ne contient aucun autre message. En outre, plusieurs messages WM_PAINT pour la même fenêtre sont combinés en un seul message WM_PAINT , en regroupant toutes les parties non valides de la zone cliente dans une seule zone. La combinaison de WM_PAINT messages réduit le nombre de fois où une fenêtre doit redessiner le contenu de sa zone cliente.

Le système publie un message dans la file d’attente de messages d’un thread en remplissant une structure MSG , puis en le copiant dans la file d’attente de messages. Les informations contenues dans MSG incluent : le handle de la fenêtre pour laquelle le message est destiné, l’identificateur du message, les deux paramètres de message, l’heure de publication du message et la position du curseur de la souris. Un thread peut publier un message dans sa propre file d’attente de messages ou dans la file d’attente d’un autre thread à l’aide de la fonction PostMessage ou PostThreadMessage .

Une application peut supprimer un message de sa file d’attente à l’aide de la fonction GetMessage . Pour examiner un message sans le supprimer de sa file d’attente, une application peut utiliser la fonction PeekMessage . Cette fonction remplit MSG avec des informations sur le message.

Après avoir supprimé un message de sa file d’attente, une application peut utiliser la fonction DispatchMessage pour diriger le système afin d’envoyer le message à une procédure de fenêtre pour le traitement. DispatchMessage prend un pointeur vers MSG rempli par un appel précédent à la fonction GetMessage ou PeekMessage . DispatchMessage transmet le handle de fenêtre, l’identificateur de message et les deux paramètres de message à la procédure de fenêtre, mais il ne passe pas le temps où le message a été publié ou la position du curseur de la souris. Une application peut récupérer ces informations en appelant les fonctions GetMessageTime et GetMessagePos lors du traitement d’un message.

Un thread peut utiliser la fonction WaitMessage pour donner le contrôle à d’autres threads lorsqu’il n’a aucun message dans sa file d’attente de messages. La fonction suspend le thread et ne retourne pas tant qu’un nouveau message n’est pas placé dans la file d’attente de messages du thread.

Vous pouvez appeler la fonction SetMessageExtraInfo pour associer une valeur à la file d’attente de messages du thread actuel. Appelez ensuite la fonction GetMessageExtraInfo pour obtenir la valeur associée au dernier message récupéré par la fonction GetMessage ou PeekMessage .

Messages non mis en file d’attente

Les messages non mis en file d’attente sont envoyés immédiatement à la procédure de fenêtre de destination, en contournant la file d’attente des messages système et celle des messages de thread. Le système envoie généralement des messages non mis en file d’attente pour notifier une fenêtre d’événements qui l’affectent. Par exemple, lorsque l’utilisateur active une nouvelle fenêtre d’application, le système envoie une série de messages, notamment WM_ACTIVATE, WM_SETFOCUS et WM_SETCURSOR. Ces messages informent la fenêtre qu’elle a été activée, que l’entrée du clavier est dirigée vers la fenêtre et que le curseur de la souris a été déplacé dans les bordures de la fenêtre. Les messages non mis en file d’attente peuvent également se produire lorsqu’une application appelle certaines fonctions système. Par exemple, le système envoie le message WM_WINDOWPOSCHANGED après qu’une application utilise la fonction SetWindowPos pour déplacer une fenêtre.

Certaines fonctions qui envoient des messages non mis en file d’attente sont BroadcastSystemMessage, BroadcastSystemMessageEx, SendMessage, SendMessageTimeout et SendNotifyMessage.

Gestion des messages

Une application doit supprimer et traiter les messages publiés dans les files d’attente de messages de ses threads. Une application monothread utilise généralement une boucle de message dans sa fonction WinMain pour supprimer et envoyer des messages aux procédures de fenêtre appropriées pour le traitement. Les applications avec plusieurs threads peuvent inclure une boucle de message dans chaque thread qui crée une fenêtre. Les sections suivantes décrivent le fonctionnement d’une boucle de message et expliquent le rôle d’une procédure de fenêtre :

Boucle de message

Une boucle de message simple se compose d’un appel de fonction à chacune de ces trois fonctions : GetMessage, TranslateMessage et DispatchMessage. Notez qu’en cas d’erreur, GetMessage retourne –1, ce qui nécessite le test spécial.

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 fonction GetMessage récupère un message de la file d’attente et le copie dans une structure de type MSG. Elle retourne une valeur différente de zéro, sauf si elle rencontre le message WM_QUIT , auquel cas elle retourne FALSE et termine la boucle. Dans une application monothread, la fin de la boucle de message est souvent la première étape de la fermeture de l’application. Une application peut mettre fin à sa propre boucle à l’aide de la fonction PostQuitMessage , généralement en réponse au message WM_DESTROY dans la procédure de fenêtre de la fenêtre principale de l’application.

Si vous spécifiez un handle de fenêtre comme deuxième paramètre de GetMessage, seuls les messages de la fenêtre spécifiée sont récupérés à partir de la file d’attente. GetMessage peut également filtrer les messages dans la file d’attente, en récupérant uniquement les messages qui se trouvent dans une plage spécifiée. Pour plus d’informations sur le filtrage des messages, consultez Filtrage des messages.

La boucle de message d’un thread doit inclure TranslateMessage si le thread doit recevoir une entrée de caractère à partir du clavier. Le système génère des messages de clé virtuelle (WM_KEYDOWN et WM_KEYUP) chaque fois que l’utilisateur appuie sur une touche. Un message de clé virtuelle contient un code de clé virtuelle qui identifie la touche qui a été enfoncée, mais pas sa valeur de caractère. Pour récupérer cette valeur, la boucle de message doit contenir TranslateMessage, qui traduit le message de clé virtuelle en un message de caractère (WM_CHAR) et le place dans la file d’attente des messages de l’application. Le message de caractère peut ensuite être supprimé lors d’une itération ultérieure de la boucle de message et envoyé à une procédure de fenêtre.

La fonction DispatchMessage envoie un message à la procédure de fenêtre associée au handle de fenêtre spécifié dans la structure MSG . Si le handle de fenêtre est HWND_TOPMOST, DispatchMessage envoie le message aux procédures de fenêtre de toutes les fenêtres de niveau supérieur dans le système. Si le handle de fenêtre a la valeur NULL, DispatchMessage ne fait rien avec le message.

Le thread principal d’une application démarre sa boucle de message après avoir initialisé l’application et créé au moins une fenêtre. Une fois qu’elle a démarré, la boucle de message continue de récupérer les messages de la file d’attente de messages du thread et de les distribuer aux fenêtres appropriées. La boucle de message se termine lorsque la fonction GetMessage supprime le message WM_QUIT de la file d’attente de messages.

Une seule boucle de message est nécessaire pour une file d’attente de messages, même si une application contient de nombreuses fenêtres. DispatchMessage distribue toujours le message dans la fenêtre appropriée ; Cela est dû au fait que chaque message de la file d’attente est une structure MSG qui contient le handle de la fenêtre à laquelle appartient le message.

Vous pouvez modifier une boucle de message de différentes façons. Par exemple, vous pouvez récupérer des messages de la file d’attente sans les envoyer à une fenêtre. Cela est utile pour les applications qui publient des messages qui ne spécifient pas de fenêtre. Vous pouvez également diriger GetMessage pour rechercher des messages spécifiques, en laissant d’autres messages dans la file d’attente. Cela est utile si vous devez contourner temporairement l’ordre FIFO habituel de la file d’attente de messages.

Une application qui utilise des touches d’accélérateur doit être en mesure de traduire les messages clavier en messages de commande. Pour ce faire, la boucle de message de l’application doit inclure un appel à la fonction TranslateAccelerator . Pour plus d’informations sur les touches d’accélérateur, consultez Raccourcis clavier.

Si un thread utilise une boîte de dialogue non modale, la boucle de message doit inclure la fonction IsDialogMessage afin que la boîte de dialogue puisse recevoir les entrées au clavier.

Procédure de fenêtre

Une procédure de fenêtre est une fonction qui reçoit et traite tous les messages envoyés à la fenêtre. Chaque classe de fenêtre a une procédure de fenêtre et chaque fenêtre créée avec cette classe utilise cette même procédure de fenêtre pour répondre aux messages.

Le système envoie un message à une procédure de fenêtre en transmettant les données de message en tant qu’arguments à la procédure. La procédure de fenêtre effectue ensuite une action appropriée pour le message ; il vérifie l’identificateur du message et, lors du traitement du message, utilise les informations spécifiées par les paramètres du message.

Une procédure de fenêtre n’ignore généralement pas un message. S’il ne traite pas de message, il doit renvoyer le message au système pour le traitement par défaut. La procédure de fenêtre effectue cette opération en appelant la fonction DefWindowProc , qui effectue une action par défaut et retourne un résultat de message. La procédure de fenêtre doit ensuite renvoyer cette valeur en tant que résultat de son propre message. La plupart des procédures de fenêtre traitent seulement quelques messages et transmettent les autres au système en appelant DefWindowProc.

Étant donné qu’une procédure de fenêtre est partagée par toutes les fenêtres appartenant à la même classe, elle peut traiter les messages pour plusieurs fenêtres différentes. Pour identifier la fenêtre spécifique affectée par le message, une routine de fenêtre peut examiner le descripteur de fenêtre passé avec un message. Pour plus d’informations sur les procédures de fenêtre, consultez Procédures de fenêtre.

Filtrage des messages

Une application peut choisir des messages spécifiques à récupérer à partir de la file d’attente de messages (tout en ignorant d’autres messages) à l’aide de la fonction GetMessage ou PeekMessage pour spécifier un filtre de message. Le filtre est une plage d’identificateurs de message (spécifiés par un premier et dernier identificateur), un handle de fenêtre ou les deux. GetMessage et PeekMessage utilisent un filtre de message pour sélectionner les messages à récupérer dans la file d’attente. Le filtrage des messages est utile si une application doit rechercher dans la file d’attente des messages arrivés plus tard dans la file d’attente. Il est également utile si une application doit traiter les messages d’entrée (matériel) avant de traiter les messages publiés.

Les constantes WM_KEYFIRST et WM_KEYLAST peuvent être utilisées comme valeurs de filtre pour récupérer tous les messages clavier ; les constantes WM_MOUSEFIRST et WM_MOUSELAST peuvent être utilisées pour récupérer tous les messages de souris.

Toute application qui filtre les messages doit s’assurer qu’un message satisfaisant au filtre de message peut être publié. Par exemple, si une application filtre un message WM_CHAR dans une fenêtre qui ne reçoit pas d’entrée au clavier, la fonction GetMessage ne retourne pas. Cela « bloque » efficacement l’application.

Publication et envoi de messages

Toute application peut publier et envoyer des messages. Comme le système, une application publie un message en le copiant dans une file d’attente de messages et envoie un message en transmettant les données de message en tant qu’arguments à une procédure de fenêtre. Pour publier des messages, une application utilise la fonction PostMessage . Une application peut envoyer un message en appelant la fonction SendMessage, BroadcastSystemMessage, SendMessageCallback, SendMessageTimeout, SendNotifyMessage ou SendDlgItemMessage .

Publication de messages

Une application publie généralement un message pour notifier une fenêtre spécifique pour effectuer une tâche. PostMessage crée une structure MSG pour le message et copie le message dans la file d’attente de messages. La boucle de message de l’application récupère finalement le message et le distribue à la procédure de fenêtre appropriée.

Une application peut publier un message sans spécifier de fenêtre. Si l’application fournit un handle de fenêtre NULL lors de l’appel de PostMessage, le message est publié dans la file d’attente associée au thread actuel. Comme aucun handle de fenêtre n’est spécifié, l’application doit traiter le message dans la boucle de message. Il s’agit d’une façon de créer un message qui s’applique à l’ensemble de l’application, au lieu d’une fenêtre spécifique.

Parfois, vous pouvez publier un message dans toutes les fenêtres de niveau supérieur du système. Une application peut publier un message dans toutes les fenêtres de niveau supérieur en appelant PostMessage et en spécifiant HWND_TOPMOST dans le paramètre hwnd .

Une erreur de programmation courante consiste à supposer que la fonction PostMessage publie toujours un message. Cela n’est pas vrai lorsque la file d’attente de messages est pleine. Une application doit vérifier la valeur de retour de la fonction PostMessage pour déterminer si le message a été publié et, s’il n’a pas été, le republier.

Envoi de messages

Une application envoie généralement un message pour notifier une procédure de fenêtre pour effectuer une tâche immédiatement. La fonction SendMessage envoie le message à la procédure de fenêtre correspondant à la fenêtre donnée. La fonction attend que la procédure de fenêtre termine le traitement, puis retourne le résultat du message. Les fenêtres parent et enfant communiquent souvent en envoyant des messages les uns aux autres. Par exemple, une fenêtre parente qui a un contrôle d’édition en tant que fenêtre enfant peut définir le texte du contrôle en lui envoyant un message. Le contrôle peut notifier la fenêtre parente des modifications de texte effectuées par l’utilisateur en envoyant des messages à la fenêtre parente.

La fonction SendMessageCallback envoie également un message à la procédure de fenêtre correspondant à la fenêtre donnée. Toutefois, cette fonction effectue un retour instantané. Une fois que la procédure de fenêtre traite le message, le système appelle la fonction de rappel spécifiée. Pour plus d’informations sur la fonction de rappel, consultez la fonction SendAsyncProc .

Parfois, vous souhaiterez peut-être envoyer un message à toutes les fenêtres de niveau supérieur du système. Par exemple, si l’application modifie l’heure système, elle doit notifier toutes les fenêtres de niveau supérieur sur la modification en envoyant un message WM_TIMECHANGE . Une application peut envoyer un message à toutes les fenêtres de niveau supérieur en appelant SendMessage et en spécifiant HWND_TOPMOST dans le paramètre hwnd . Vous pouvez également diffuser un message à toutes les applications en appelant la fonction BroadcastSystemMessage et en spécifiant BSM_APPLICATIONS dans le paramètre lpdwRecipients .

En utilisant la fonction InSendMessage ou InSendMessageEx , une procédure de fenêtre peut déterminer s’il traite un message envoyé par un autre thread. Cette fonctionnalité est utile lorsque le traitement des messages dépend de l’origine du message.

Blocages de messages

Un thread qui appelle la fonction SendMessage pour envoyer un message à un autre thread ne peut pas continuer à s’exécuter jusqu’à ce que la procédure de fenêtre qui reçoit le message retourne. Si le thread de réception génère le contrôle lors du traitement du message, le thread d’envoi ne peut pas continuer à s’exécuter, car il attend que SendMessage retourne. Si le thread de réception est attaché à la même file d’attente que l’expéditeur, il peut provoquer un blocage d’application. (Notez que les hooks de journal attachent des threads à la même file d’attente.)

Notez que le thread de réception n’a pas besoin de générer le contrôle explicitement ; l’appel de l’une des fonctions suivantes peut entraîner un thread à générer implicitement un contrôle.

Pour éviter les blocages potentiels dans votre application, envisagez d’utiliser les fonctions SendNotifyMessage ou SendMessageTimeout . Sinon, une procédure de fenêtre peut déterminer si un message reçu a été envoyé par un autre thread en appelant la fonction InSendMessage ou InSendMessageEx . Avant d’appeler l’une des fonctions de la liste précédente lors du traitement d’un message, la procédure de fenêtre doit d’abord appeler InSendMessage ou InSendMessageEx. Si cette fonction retourne TRUE, la procédure de fenêtre doit appeler la fonction ReplyMessage avant toute fonction qui entraîne le contrôle du thread.

Diffusion de messages

Chaque message se compose d’un identificateur de message et de deux paramètres, wParam et lParam. L’identificateur de message est une valeur unique qui spécifie l’objectif du message. Les paramètres fournissent des informations supplémentaires spécifiques au message, mais le paramètre wParam est généralement une valeur de type qui fournit plus d’informations sur le message.

Une diffusion de message est simplement l’envoi d’un message à plusieurs destinataires dans le système. Pour diffuser un message à partir d’une application, utilisez la fonction BroadcastSystemMessage , en spécifiant les destinataires du message. Au lieu de spécifier des destinataires individuels, vous devez spécifier un ou plusieurs types de destinataires. Ces types sont des applications, des pilotes installables, des pilotes réseau et des pilotes de périphériques au niveau du système. Le système envoie des messages de diffusion à tous les membres de chaque type spécifié.

Le système diffuse généralement des messages en réponse aux modifications qui se produisent dans les pilotes de périphérique au niveau du système ou les composants associés. Le pilote ou le composant associé diffuse le message aux applications et à d’autres composants pour les informer de la modification. Par exemple, le composant responsable des lecteurs de disque diffuse un message chaque fois que le pilote de périphérique du lecteur de disque de floppy détecte un changement de média, par exemple lorsque l’utilisateur insère un disque dans le lecteur.

Le système diffuse des messages aux destinataires dans cet ordre : pilotes de périphérique au niveau du système, pilotes réseau, pilotes installables et applications. Cela signifie que les pilotes de périphérique au niveau du système, s’ils sont choisis en tant que destinataires, obtiennent toujours la première occasion de répondre à un message. Dans un type de destinataire donné, aucun pilote n’est garanti pour recevoir un message donné avant tout autre pilote. Cela signifie qu’un message destiné à un pilote spécifique doit avoir un identificateur de message global unique afin qu’aucun autre pilote ne le traite involontairement.

Vous pouvez également diffuser des messages dans toutes les fenêtres de niveau supérieur en spécifiant HWND_BROADCAST dans la fonction SendMessage, SendMessageCallback, SendMessageTimeout ou SendNotifyMessage .

Les applications reçoivent les messages par le biais de la procédure de fenêtre de leurs fenêtres de niveau supérieur. Les messages ne sont pas envoyés aux fenêtres enfants. Les services peuvent recevoir des messages via une procédure de fenêtre ou leurs gestionnaires de contrôle de service.

Remarque

Les pilotes de périphérique au niveau du système utilisent une fonction de niveau système associée pour diffuser des messages système.

Interroger des messages

Vous pouvez créer vos propres messages personnalisés et les utiliser pour coordonner les activités entre vos applications et d’autres composants du système. Cela est particulièrement utile si vous avez créé vos propres pilotes installables ou pilotes de périphérique au niveau du système. Vos messages personnalisés peuvent transporter des informations vers et depuis votre pilote et les applications qui utilisent le pilote.

Pour interroger les destinataires pour obtenir l’autorisation d’effectuer une action donnée, utilisez un message de requête. Vous pouvez générer vos propres messages de requête en définissant la valeur BSF_QUERY dans le paramètre dwFlags lors de l’appel de BroadcastSystemMessage. Chaque destinataire du message de requête doit retourner TRUE pour que la fonction envoie le message au destinataire suivant. Si un destinataire retourne BROADCAST_QUERY_DENY, la diffusion se termine immédiatement et la fonction retourne un zéro.