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

Contrairement aux applications MS-DOS, les applications Windows sont pilotées par les événements. Ils n’effectuent pas d’appels de fonction explicites (tels que des appels de bibliothèque d’exécution C) pour obtenir une entrée. Au lieu de cela, ils attendent que le système leur transmette l’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 les mêmes attributs d’ordre Z, d’emplacement, de taille et de visuel. 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. En mode débogueur, le système ne génère pas de fenêtre fantôme.

Cette section traite des rubriques suivantes :

Windows Messages

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 à la fois 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 au 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 pour 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 la procédure de fenêtre qui 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 empaquetés, un pointeur vers une structure contenant des données supplémentaires, etc. 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 case activée l’identificateur de 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 System-Defined

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 entrées et d’autres informations que les applications doivent 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 le fonctionnement des fenêtres de contrôle créées à l’aide de classes de fenêtres 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, le WM_PAINT demande constamment qu’une fenêtre peigne 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 les catégories de messages associées.

Préfixe Catégorie de message Documentation
ABM et ABN Barre d’outils Application Desktop Messages et notifications de l’interpréteur de commandes
ACM et ACN Contrôle Animation Messages de contrôle d’animation et notifications de contrôle d’animation
BCM, BCN, BM et BN contrôle 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 Contrôle ComboBoxEx Messages ComboBoxEx et notifications ComboBoxEx
CCM Contrôle général Messages de contrôle
CDM Boîte de dialogue commune Messages de boîte de dialogue courants
DFM Menu contextuel par défaut Messages et notifications de l’interpréteur de commandes
DL Faire glisser la zone de liste Faire glisser les notifications de zone de liste
DM Contrôle de bouton push par défaut Messages de 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 Contrôle Edit Modifier les messages de contrôle, modifier les notifications de contrôle, modifier les messages enrichis et les 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 la touche chaude Messages de contrôle de touche chaude
IPM et IPN IP address (contrôle) Messages d’adresse IP et notifications d’adresse IP
LB et LBN Contrôle de zone de liste Messages de zone de liste et notifications de zone de liste
LM Contrôle SysLink Messages de contrôle SysLink
LVM et LVN Contrôle d’affichage liste Messages d’affichage deliste et notifications d’affichage de liste
MCM et MCN Contrôle calendrier du mois Messages du calendrier du mois et notifications du calendrier du mois
PBM Barre de progression Messages de barre de progression
PGM et PGN Contrôle du pagineur Messages de contrôle du pagineur 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ôle de barre d’armature Messages de contrôle rebar et notifications de contrôle de barre d’armature
SB et SBN Fenêtre de barre d’état Messages de barre d’état et notifications de barre d’état
SBM Contrôle de barre de défilement Messages de la barre de défilement
SMC Menu De l’interpréteur de commande Messages et notifications de l’interpréteur de commandes
STM et STN Contrôle statique Messages de contrôle statique et notifications de contrôle statiques
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 Trackbar 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 Tâche Messages de boîte de dialogue de tâche et notifications de boîte de dialogue de tâche
TTM et TTN Contrôle d’info-bulle Messages de contrôle d’info-bulle et notifications de contrôle d’info-bulle
TVM et TVN Contrôle tree-view Messages d’arborescence et notifications d’arborescence
UDM et UDN Contrôle up-down Messages up-down et notifications up-down
WM Général
Messages du Presse-papiers
Notifications du Presse-papiers
Notifications courantes de boîte de dialogue
Notifications de curseur
Message de copie de données
Messages du Gestionnaire de fenêtres du bureau
messages Gestion des appareils
Notifications de boîte de dialogue
Messages d’échange de données dynamiques
Notifications d’échange de données dynamiques
Hook Notifications
Messages de l’accélérateur de clavier
Notifications de l’accélérateur de clavier
Messages d’entrée du clavier
Notifications d’entrée clavier
Menu Notifications
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 de fenêtre généraux couvrent un large éventail d’informations et de demandes, y compris les messages relatifs à l’entrée de la souris et du clavier, aux entrées de menu et de boîte de dialogue, à la création et à la gestion des fenêtres et à l’échange de données dynamique (DDE).

messages Application-Defined

Une application peut créer des messages à utiliser par ses propres fenêtres ou pour 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 les valeurs d’identificateur de message dans la plage 0x0000 jusqu’à 0x03FF (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) à 0x7FFF sont disponibles pour les identificateurs de message pour les classes de fenêtre privées.
  • Si votre application est marquée version 4.0, vous pouvez utiliser des valeurs d’identificateur de message dans la plage 0x8000 (WM_APP) jusqu’à 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 comme unique dans l’ensemble du 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 : la publication de messages dans une file d’attente de premier entrant et premier sorti appelée file d’attente de messages, un objet de mémoire défini par le système qui stocke temporairement des messages et l’envoi de 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. Ils sont principalement le résultat d’une entrée utilisateur entrée par le biais de la souris ou du clavier, telles que des messages WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN et WM_CHAR . Les autres messages mis en file d’attente incluent les messages de minuterie, de peinture et de démission : 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 sans file d’attente.

Messages mis en file d’attente

Le système peut afficher n’importe quel nombre de fenêtres à la fois. Pour acheminer 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 graphique. Pour éviter la surcharge liée à la 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 tape 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 demande au système de 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 premier entrant, premier sorti (FIFO) appropriée. Toutefois, le message WM_PAINT , le message WM_TIMER et le message WM_QUIT sont conservés dans la file d’attente et ne sont transférés vers la procédure de fenêtre que 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 , consolidant toutes les parties non valides de la zone client en 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 des 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 à laquelle le message a été publié 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 vers une procédure de fenêtre pour traitement. DispatchMessage prend un pointeur vers MSG qui a été 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 l’heure à laquelle 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 des 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 sans file d’attente

Les messages sans file d’attente sont envoyés immédiatement à la procédure de fenêtre de destination, en contournant la file d’attente de messages système et la file d’attente de messages de thread. Le système envoie généralement des messages sans file d’attente pour notifier une fenêtre des événements qui l’affectent. Par exemple, lorsque l’utilisateur active une nouvelle fenêtre d’application, le système envoie à la fenêtre 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é à l’intérieur des bordures de la fenêtre. Les messages sans 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.

Les fonctions qui envoient des messages sans 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, d’où la nécessité du 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. Il retourne une valeur différente de zéro, sauf s’il rencontre le message WM_QUIT , auquel cas il retourne FALSE et met fin à 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 main 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, 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 à 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 à clé virtuelle en message de caractère (WM_CHAR) et le replace 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 distribué à 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 du système. Si le handle de fenêtre a la valeur NULL, DispatchMessage ne fait rien avec le message.

Le thread main d’une application démarre sa boucle de message après l’initialisation de l’application et la création d’au moins une fenêtre. Une fois démarrée, 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 des 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 ; En effet, chaque message de la file d’attente est une structure MSG qui contient le handle de la fenêtre à laquelle le message appartient.

Vous pouvez modifier une boucle de message de différentes manières. Par exemple, vous pouvez récupérer des messages de la file d’attente sans les distribuer à une fenêtre. Cela est utile pour les applications qui publient des messages ne spécifiant 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 des messages.

Une application qui utilise des touches d’accélérateur doit être en mesure de traduire les messages du 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 Accélérateurs de clavier.

Si un thread utilise une boîte de dialogue sans mode, la boucle de message doit inclure la fonction IsDialogMessage afin que la boîte de dialogue puisse recevoir l’entrée du 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 du 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. Pour ce faire, la procédure de fenêtre appelle 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 retourner cette valeur comme son propre résultat de message. La plupart des procédures de fenêtre ne traitent que quelques messages et passent 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 des messages pour plusieurs fenêtres différentes. Pour identifier la fenêtre spécifique affectée par le message, une procédure de fenêtre peut examiner le handle 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 messages. 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 messages pour sélectionner les messages à récupérer à partir de la file d’attente. Le filtrage des messages est utile si une application doit rechercher dans la file d’attente des messages qui sont 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 clavier, la fonction GetMessage ne retourne pas. Cela « bloque » effectivement l’application.

Publication et envoi de messages

N’importe quelle 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 passant les données du 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 avertir une fenêtre spécifique d’effectuer une tâche. PostMessage crée une structure MSG pour le message et copie le message dans la file d’attente des 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. Étant donné qu’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 case activée la valeur de retour de la fonction PostMessage pour déterminer si le message a été publié et, si ce n’est pas le cas, le republier.

sending 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 s’envoyant des messages l’un à l’autre. Par exemple, une fenêtre parente qui a un contrôle d’édition comme 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 apportées au texte effectuées par l’utilisateur en envoyant des messages au parent.

La fonction SendMessageCallback envoie également un message à la procédure de fenêtre correspondant à la fenêtre donnée. Toutefois, cette fonction retourne immédiatement. 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 informer toutes les fenêtres de niveau supérieur de 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 vers 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 si elle traite un message envoyé par un autre thread. Cette fonctionnalité est utile lorsque le traitement des messages dépend de l’origine du message.

Interblocages de messages

Un thread qui appelle la fonction SendMessage pour envoyer un message à un autre thread ne peut pas continuer à s’exécuter tant que la procédure de fenêtre qui reçoit le message n’est pas retournée. Si le thread de réception génère le contrôle pendant le traitement du message, le thread d’envoi ne peut pas continuer à s’exécuter, car il attend le retour de SendMessage . Si le thread de réception est attaché à la même file d’attente que l’expéditeur, un blocage de l’application peut se produire. (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 produire le contrôle explicitement ; L’appel de l’une des fonctions suivantes peut faire en sorte qu’un thread génère implicitement le 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 qu’elle a 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 provoque le contrôle du thread.

Messages de diffusion

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érique de niveau 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 au sein des pilotes de périphérique au niveau du système ou des 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 pour le lecteur de disque de disquette détecte une modification 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 de niveau 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 comme 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 des messages via 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.

Notes

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

Messages de requête

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ériques au niveau du système. Vos messages personnalisés peuvent transporter des informations à destination et en provenance de votre pilote et des 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.