TN062 : Réflexion de Message pour les contrôles Windows

Cette note technique décrit la réflexion de message, une nouvelle fonctionnalité dans MFC 4.0. Il contient également des instructions pour créer un contrôle réutilisable simple qui utilise la réflexion de message.

Cette note technique ne traite pas le reflet du message qu'elle s'applique aux contrôles ActiveX (anciennement appelés contrôles OLE). Consultez l'article contrôles ActiveX : sous-classement d'un contrôle Windows dans le Guide du programmeur Visual C++.

Ce qui est le reflet du Message?

Contrôles Windows envoient souvent des messages de notification de windows de leurs parent. Par exemple, de nombreux contrôles envoient un message de notification de contrôle couleur (WM_CTLCOLOR ou une de ses variantes) à leurs parents afin de permettre au parent de fournir un pinceau pour peindre l'arrière-plan du contrôle.

Dans Windows et MFC antérieures à la version 4.0, la fenêtre parent, souvent une boîte de dialogue, est chargée de traiter ces messages. Cela signifie que le code pour gérer le message doit être dans la classe de la fenêtre parent et qu'il doit être dupliqué dans chaque classe qui doit gérer ce message. Dans le cas ci-dessus, chaque boîte de dialogue qui voulait que les contrôles avec des arrière-plans personnalisés devra gérer le message de notification de contrôle couleur. Il serait beaucoup plus facile à réutiliser le code si une classe de contrôle pourrait être écrite qui pourrait gérer sa propre couleur d'arrière-plan.

Dans MFC 4.0, le vieux mécanisme fonctionne toujours — windows parent peuvent gérer les messages de notification. En outre, cependant, MFC 4.0 facilite réutilisation en offrant une fonctionnalité appelée « message de réflexion » qui permet à ces messages de notification sera traitée dans la fenêtre du contrôle enfant ou de la fenêtre parent, ou les deux. Dans l'exemple de couleur fond de contrôle, vous pouvez maintenant écrire une classe de contrôle qui définit sa propre couleur d'arrière-plan par la gestion du message WM_CTLCOLOR réfléchi — sans s'appuyant sur le parent. (Notez que puisque la réflexion de message est mis en œuvre par les MFC, pas par Windows, la classe de fenêtre parent doit provenir d' CWnd de réflexion message de travailler).

Les anciennes versions de MFC fait quelque chose de semblable à la réflexion de message en fournissant des fonctions virtuelles pour quelques messages, tels que des messages pour les zones de liste owner-drawn (WM_DRAWITEMet ainsi de suite). Le nouveau mécanisme de réflexion du message est généralisée et compatible.

Réflexion de message est rétrocompatible avec le code écrit pour des versions antérieures à 4.0 de MFC.

Si vous avez fourni un gestionnaire d'événements pour un message spécifique, ou pour une série de messages, dans la classe de la fenêtre de votre parent, elle remplace reflètent des gestionnaires de messages pour le même message, pourvu que vous ne pas appeler la fonction de gestionnaire d'événements de classe de base dans votre propre gestionnaire d'événements. Par exemple, si vous gérez WM_CTLCOLOR dans votre classe de boîte de dialogue, votre manipulation substitueront les gestionnaires de messages réfléchis.

Si, dans votre classe de la fenêtre parent, vous fournissez un gestionnaire d'événements pour un message WM_NOTIFY spécifique ou une plage de messages WM_NOTIFY , votre gestionnaire d'événements sera appelée que si le contrôle enfant envoi de ces messages n'a pas un gestionnaire de messages réfléchis par le biais de ON_NOTIFY_REFLECT(). Si vous utilisez ON_NOTIFY_REFLECT_EX() dans la carte de votre message, votre gestionnaire de messages peut ou peut ne permettent pas la fenêtre parent pour traiter le message. Si le gestionnaire d'événements retourne TRUE, le message sera assurée par le parent, tandis qu'un appel qui renvoie que false ne permet pas au parent de gérer. Notez que le message réfléchi est géré avant le message de notification.

Lorsqu'un message WM_NOTIFY est envoyé, le contrôle est offert à la première occasion de manipuler. Si tout autre message réfléchi est envoyé, la fenêtre parente a la première occasion pour manipuler et le contrôle recevra le message réfléchi. Pour ce faire, il faudra une fonction de gestionnaire et une entrée appropriée dans la carte de message de classe du contrôle.

La macro carte-message pour les messages réfléchis est légèrement différente pour les notifications régulières : il est _REFLECT ajouté à son nom usuel. Par exemple, pour gérer un message WM_NOTIFY chez le parent, vous utilisez la macro ON_NOTIFY dans le parent. Pour gérer le message réfléchi dans le contrôle enfant, utilisez la macro ON_NOTIFY_REFLECT dans la table des messages du contrôle enfant. Dans certains cas, les paramètres sont différents, aussi bien. Notez que ClassWizard peut généralement ajouter les entrées de table des messages pour vous et fournir des implémentations de squelette de fonction avec les paramètres corrects.

Voir TN061 : ON_NOTIFY et Messages WM_NOTIFY pour plus d'informations sur le nouveau message WM_NOTIFY.

Message-carte entrées et les Prototypes de fonction du gestionnaire d'événements pour les Messages réfléchis

Pour gérer un message de notification de contrôle réfléchi, utiliser les macros message-carte et les prototypes de fonction répertoriées dans le tableau ci-dessous.

ClassWizard peut généralement ajouter ces entrées de message-carte pour vous et fournir des implémentations de fonction squelette. Voir définir un gestionnaire de messages pour un Message reflétait dans le Guide du programmeur Visual C++ pour plus d'informations sur la façon de définir des gestionnaires d'événements pour refléter messages.

Pour convertir le nom du message le nom de la macro réfléchie, faites précéder ON_ et ajouter _REFLECT. Par exemple, WM_CTLCOLOR devient ON_WM_CTLCOLOR_REFLECT. (Pour voir les messages peuvent être réfléchis, faire la conversion inverse sur les entrées de macro dans le tableau ci-dessous.)

Les trois exceptions à la règle ci-dessus sont comme suit:

Dans chacun des cas particuliers ci-dessus, vous devez spécifier le nom de la fonction de membre du gestionnaire d'événements. Dans les autres cas, vous devez utiliser le nom standard de votre fonction de gestionnaire d'événements.

La signification des paramètres et valeurs de retour des fonctions sont documentés sous le nom de fonction ou le nom de fonction avec le nom. Par exemple, CtlColor est documentée dans OnCtlColor. Plusieurs gestionnaires de messages réfléchis besoin moins de paramètres que les gestionnaires similaires dans une fenêtre parente. Juste correspondre les noms dans le tableau ci-dessous avec les noms des paramètres formels dans la documentation.

Entrée de la carte Prototype de fonction
ON_CONTROL_REFLECT ( wNotifyCode, memberFxn ) afx_msg voidmemberFxn ( );
ON_NOTIFY_REFLECT ( wNotifyCode, memberFxn ) afx_msg voidmemberFxn(NMHDR * pNotifyStruct, LRESULT * résultat );
ON_UPDATE_COMMAND_UI_REFLECT ( memberFxn ) afx_msg voidmemberFxn(CCmdUI * pCmdUI );
ON_WM_CTLCOLOR_REFLECT) afx_msg CtlColor HBRUSH (CDC * pDC, UINT nCtlColor );
ON_WM_DRAWITEM_REFLECT) afx_msg void DrawItem (LPDRAWITEMSTRUCT lpDrawItemStruct );
ON_WM_MEASUREITEM_REFLECT) afx_msg void MeasureItem (LPMEASUREITEMSTRUCT lpMeasureItemStruct );
ON_WM_DELETEITEM_REFLECT) afx_msg void DeleteItem (LPDELETEITEMSTRUCT lpDeleteItemStruct );
ON_WM_COMPAREITEM_REFLECT) afx_msg int CompareItem (LPCOMPAREITEMSTRUCT lpCompareItemStruct );
ON_WM_CHARTOITEM_REFLECT) afx_msg int CharToItem (UINT nKey, UINT nIndex );
ON_WM_VKEYTOITEM_REFLECT) afx_msg int VKeyToItem (UINT nKey, UINT nIndex );
ON_WM_HSCROLL_REFLECT) afx_msg void HScroll (UINT nSBCode, UINT ONL );
ON_WM_VSCROLL_REFLECT) afx_msg void DéfilementV (UINT nSBCode, UINT ONL );
ON_WM_PARENTNOTIFY_REFLECT) afx_msg void ParentNotify (UINT , LPARAM lParam message );

Les macros ON_NOTIFY_REFLECT et ON_CONTROL_REFLECT ont des variations qui permettent de gérer un message donné plus d'un objet (comme le contrôle et son parent).

Entrée de la carte Prototype de fonction
ON_NOTIFY_REFLECT_EX ( wNotifyCode, memberFxn ) afx_msg BOOLmemberFxn(NMHDR * pNotifyStruct, LRESULT * résultat );
ON_CONTROL_REFLECT_EX ( wNotifyCode, memberFxn ) afx_msg BOOLmemberFxn ( );

Manipulation des Messages réfléchi : Un exemple d'un contrôle réutilisable

Cet exemple simple crée un contrôle réutilisable appelé CYellowEdit . Le contrôle fonctionne de la même comme un contrôle d'édition ordinaire sauf qu'il affiche le texte en noir sur fond jaune. Il serait facile d'ajouter des fonctions membres qui permettraient le CYellowEdit contrôle pour afficher les différentes couleurs.

Pour tester cet exemple, faire les étapes suivantes:

  1. Créer une nouvelle boîte de dialogue dans une application existante. Pour plus d'informations, voir , éditeur de la boîte de dialogue dans le Guide d'utilisation de Visual C++.

    Vous devez avoir une application pour développer le contrôle réutilisable. Si vous n'avez pas une application existante à utiliser, créer une application de dialogue à l'aide de AppWizard.

  2. Votre projet est chargé dans Visual C++, utilisez ClassWizard pour créer une nouvelle classe appelée CYellowEdit basé sur CEdit. Laissez la case « Ajouter au composant Gallery » cochée.

  3. Ajoutez trois variables de membre à votre CYellowEdit classe. Les deux premiers seront variables COLORREF pour tenir la couleur du texte et la couleur d'arrière-plan. Le troisième sera un objet CBrush qui se tiendra le pinceau pour peindre l'arrière-plan. L'objet CBrush vous permet de créer le pinceau une fois, simplement le référencement après qu'et pour détruire le pinceau automatiquement lorsque le CYellowEdit contrôle est détruit.

  4. Initialiser les variables de membre en écrivant le constructeur comme suit:
    CYellowEdit::CYellowEdit()
    {
    m_clrText = RGB (0, 0, 0) ;
    m_clrBkgnd = RGB (255, 255, 0) ;
    m_brBkgnd.CreateSolidBrush (m_clrBkgnd) ;
    }
    
  5. À l'aide de ClassWizard, ajoutez un gestionnaire pour le message WM_CTLCOLOR réfléchi à votre CYellowEdit classe. Notez que le signe égal du nom du message dans la liste des messages, que vous pouvez gérer indique que le message soit reflété. Ceci est décrit dans définir un gestionnaire de messages pour un Message reflétait dans le Guide du programmeur Visual C++.

    ClassWizard ajoute la fonction macro et le squelette de message-carte suivante pour vous:

    ON_WM_CTLCOLOR_REFLECT()
    
    / / Note : autre code sera entre...
    
    HBRUSH CYellowEdit::CtlColor(CDC* pDC, UINT nCtlColor) {
    / / TODO : modifier tous les attributs de la DC ici
    
    / / TODO : retourner une brosse non NULL si la
    / / Gestionnaire du parent ne doit pas être appelé
    retourner la valeur NULL ;
    }
    
  6. Remplacer le corps de la fonction avec le code suivant. Le code spécifie la couleur du texte, la couleur d'arrière-plan de texte et la couleur d'arrière-plan pour le reste de la commande.
    pDC-gt ;SetTextColor (m_clrText) ;    / / texte
    pDC - > SetBkColor (m_clrBkgnd) ;    / / arrière-plan de texte
    Return m_brBkgnd ;                / / arrière-plan ctl
    
  7. Créer un contrôle d'édition dans votre boîte de dialogue, puis les attacher à une variable de membre en double-cliquant sur le contrôle d'édition tout en retenant une clé de contrôle. Dans la boîte de dialogue Ajouter la Variable de membre, terminer le nom de variable et choisir « Contrôle » pour la catégorie, puis « CYellowEdit » pour le type de variable. N'oubliez pas de définir l'ordre de tabulation dans la boîte de dialogue. Aussi, assurez-vous d'inclure le fichier d'en-tête pour le CYellowEdit contrôle dans fichier d'en-tête du votre boîte de dialogue.

  8. Générer et exécuter votre application. Le contrôle d'édition auront un fond jaune.

  9. Vous pouvez maintenant utiliser la Galerie de composants pour ajouter votre CYellowEdit classe à d'autres projets de contrôle.

&Notes techniques par le numéro |nbsp ; Notes techniques par catégorie

Index