Partager via


Contrôles ActiveX MFC : utilisation des polices

Si votre contrôle ActiveX affiche du texte, vous pouvez autoriser l’utilisateur de contrôle à modifier l’apparence du texte en modifiant une propriété de police. Les propriétés de police sont implémentées en tant qu’objets de police et peuvent être l’un des deux types suivants : stock ou personnalisé. Les propriétés de police stock sont des propriétés de police pré-implémentées que vous pouvez ajouter à l’aide de l’Assistant Ajouter une propriété. Les propriétés de police personnalisée ne sont pas pré-implémentées et le développeur du contrôle détermine le comportement et l’utilisation de la propriété.

Cet article aborde les thèmes suivants :

Utilisation de la propriété Police Stock

Les propriétés de police stock sont pré-implémentées par la classe COleControl. En outre, une page de propriétés de police standard est également disponible, ce qui permet à l’utilisateur de modifier différents attributs de l’objet de police, tels que son nom, sa taille et son style.

Accédez à l’objet de police via les fonctions GetFont, SetFont et InternalGetFont de COleControl. L’utilisateur de contrôle accède à l’objet de police par le biais des GetFont fonctions et SetFont des fonctions de la même manière que toute autre propriété Get/Set. Lorsque l’accès à l’objet de police est requis à partir d’un contrôle, utilisez la InternalGetFont fonction.

Comme indiqué dans les contrôles ActiveX MFC : Propriétés, l’ajout de propriétés de stock est facile avec l’Assistant Ajout de propriété. Vous choisissez la propriété Font et l’Assistant Ajouter une propriété insère automatiquement l’entrée de police de stock dans la carte de répartition du contrôle.

Pour ajouter la propriété Font stock à l’aide de l’Assistant Ajouter une propriété

  1. Chargez votre projet de contrôle.

  2. Dans l’Affichage de classes, développez le nœud Bibliothèque de votre contrôle.

  3. Cliquez sur le nœud Interface de votre contrôle (le deuxième nœud du nœud Bibliothèque) pour ouvrir le menu contextuel.

  4. Dans le menu contextuel, cliquez sur Ajouter , puis sur Ajouter une propriété.

    L’Assistant Ajouter une propriété s’ouvre.

  5. Dans la zone Nom de la propriété, cliquez sur Police.

  6. Cliquez sur Terminer.

L’Assistant Ajouter une propriété ajoute la ligne suivante à la carte de répartition du contrôle, située dans le fichier d’implémentation de la classe de contrôle :

DISP_STOCKPROP_FONT()

En outre, l’Assistant Ajouter une propriété ajoute la ligne suivante au contrôle. Fichier IDL :

[id(DISPID_FONT)] IFontDisp* Font;

La propriété de légende boursier est un exemple de propriété de texte qui peut être dessinée à l’aide des informations de propriété de police stock. L’ajout de la propriété de légende de stock au contrôle utilise des étapes similaires à celles utilisées pour la propriété Font stock.

Pour ajouter la propriété de légende boursier à l’aide de l’Assistant Ajouter une propriété

  1. Chargez votre projet de contrôle.

  2. Dans l’Affichage de classes, développez le nœud Bibliothèque de votre contrôle.

  3. Cliquez sur le nœud Interface de votre contrôle (le deuxième nœud du nœud Bibliothèque) pour ouvrir le menu contextuel.

  4. Dans le menu contextuel, cliquez sur Ajouter , puis sur Ajouter une propriété.

    L’Assistant Ajouter une propriété s’ouvre.

  5. Dans la zone Nom de la propriété, cliquez sur Légende.

  6. Cliquez sur Terminer.

L’Assistant Ajouter une propriété ajoute la ligne suivante à la carte de répartition du contrôle, située dans le fichier d’implémentation de la classe de contrôle :

DISP_STOCKPROP_CAPTION()

Modification de la fonction OnDraw

Implémentation par défaut d’utilisation de OnDraw la police système Windows pour tout le texte affiché dans le contrôle. Cela signifie que vous devez modifier le OnDraw code en sélectionnant l’objet de police dans le contexte de l’appareil. Pour ce faire, appelez COleControl ::SelectStockFont et transmettez le contexte de l’appareil du contrôle, comme illustré dans l’exemple suivant :

CFont* pOldFont;
TEXTMETRIC tm;
const CString& strCaption = InternalGetText();

pOldFont = SelectStockFont(pdc);
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
pdc->Ellipse(rcBounds);
pdc->GetTextMetrics(&tm);
pdc->SetTextAlign(TA_CENTER | TA_TOP);
pdc->ExtTextOut((rcBounds.left + rcBounds.right) / 2,
(rcBounds.top + rcBounds.bottom - tm.tmHeight) / 2,
ETO_CLIPPED, rcBounds, strCaption, strCaption.GetLength(), NULL);

pdc->SelectObject(pOldFont);

Une fois la OnDraw fonction modifiée pour utiliser l’objet de police, tout texte du contrôle s’affiche avec des caractéristiques de la propriété Font stock du contrôle.

Utilisation des propriétés de police personnalisées dans votre contrôle

En plus de la propriété Font stock, le contrôle ActiveX peut avoir des propriétés de police personnalisées. Pour ajouter une propriété de police personnalisée, vous devez :

Implémentation d’une propriété police personnalisée

Pour implémenter une propriété Police personnalisée, vous utilisez l’Assistant Ajouter une propriété pour ajouter la propriété, puis apporter des modifications au code. Les sections suivantes décrivent comment ajouter la propriété personnalisée HeadingFont au contrôle Sample.

Pour ajouter la propriété Police personnalisée à l’aide de l’Assistant Ajouter une propriété
  1. Chargez votre projet de contrôle.

  2. Dans l’Affichage de classes, développez le nœud Bibliothèque de votre contrôle.

  3. Cliquez sur le nœud Interface de votre contrôle (le deuxième nœud du nœud Bibliothèque) pour ouvrir le menu contextuel.

  4. Dans le menu contextuel, cliquez sur Ajouter , puis sur Ajouter une propriété.

    L’Assistant Ajouter une propriété s’ouvre.

  5. Dans la zone Nom de la propriété, tapez un nom pour la propriété. Pour cet exemple, utilisez HeadingFont.

  6. Pour Type d’implémentation, cliquez sur Méthodes Get/Set.

  7. Dans la zone Type de propriété, sélectionnez IDispatch* pour le type de la propriété.

  8. Cliquez sur Terminer.

L’Assistant Ajouter une propriété crée le code pour ajouter la HeadingFont propriété personnalisée à la CSampleCtrl classe et à l’EXEMPLE. Fichier IDL. Étant donné qu’il HeadingFont s’agit d’un type de propriété Get/Set, l’Assistant Ajouter une propriété modifie la carte de répartition de la CSampleCtrl classe pour inclure une entrée de macro DISP_PROPERTY_EX_ID DISP_PROPERTY_EX :

DISP_PROPERTY_EX_ID(CMyAxFontCtrl, "HeadingFont", dispidHeadingFont,
   GetHeadingFont, SetHeadingFont, VT_DISPATCH)

La macro DISP_PROPERTY_EX associe le nom de la HeadingFont propriété à ses méthodes Get et Set correspondantes CSampleCtrl , GetHeadingFont et SetHeadingFont. Le type de la valeur de propriété est également spécifié ; dans ce cas, VT_FONT.

L’Assistant Ajouter une propriété ajoute également une déclaration dans le fichier d’en-tête de contrôle (. H) pour les GetHeadingFont fonctions et SetHeadingFont ajoute leurs modèles de fonction dans le fichier d’implémentation de contrôle (. CPP) :

IDispatch* CWizardGenCtrl::GetHeadingFont(void)
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());

   // TODO: Add your dispatch handler code here

   return NULL;
}

void CWizardGenCtrl::SetHeadingFont(IDispatch* /*pVal*/)
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());

   // TODO: Add your property handler code here

   SetModifiedFlag();
}

Enfin, l’Assistant Ajouter une propriété modifie le contrôle. Fichier IDL en ajoutant une entrée pour la HeadingFont propriété :

[id(1)] IDispatch* HeadingFont;

Modifications apportées au code de contrôle

Maintenant que vous avez ajouté la HeadingFont propriété au contrôle, vous devez apporter des modifications aux fichiers d’en-tête et d’implémentation du contrôle pour prendre entièrement en charge la nouvelle propriété.

Dans le fichier d’en-tête de contrôle (. H), ajoutez la déclaration suivante d’une variable membre protégée :

protected:
   CFontHolder m_fontHeading;

Dans le fichier d’implémentation de contrôle (. CPP), procédez comme suit :

  • Initialisez m_fontHeading dans le constructeur de contrôle.

    CMyAxFontCtrl::CMyAxFontCtrl()
       : m_fontHeading(&m_xFontNotification)
    {
       InitializeIIDs(&IID_DNVC_MFC_AxFont, &IID_DNVC_MFC_AxFontEvents);
    }
    
  • Déclarez une structure FONTDESC statique contenant les attributs par défaut de la police.

    static const FONTDESC _fontdescHeading =
    { sizeof(FONTDESC), OLESTR("MS Sans Serif"), FONTSIZE(12), FW_BOLD,
      ANSI_CHARSET, FALSE, FALSE, FALSE };
    
  • Dans la fonction membre du contrôle DoPropExchange , ajoutez un appel à la PX_Font fonction. Cela fournit l’initialisation et la persistance de votre propriété Police personnalisée.

    void CMyAxFontCtrl::DoPropExchange(CPropExchange* pPX)
    {
       ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
       COleControl::DoPropExchange(pPX);
    
       // [...other PX_ function calls...]
       PX_Font(pPX, _T("HeadingFont"), m_fontHeading, &_fontdescHeading);
    }
    
  • Terminez l’implémentation de la fonction membre de contrôle GetHeadingFont .

    IDispatch* CMyAxFontCtrl::GetHeadingFont(void)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       return m_fontHeading.GetFontDispatch();
    }
    
  • Terminez l’implémentation de la fonction membre de contrôle SetHeadingFont .

    void CMyAxFontCtrl::SetHeadingFont(IDispatch* pVal)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       m_fontHeading.InitializeFont(&_fontdescHeading, pVal);
       OnFontChanged();    //notify any changes
       SetModifiedFlag();
    }
    
  • Modifiez la fonction membre de contrôle OnDraw pour définir une variable pour contenir la police précédemment sélectionnée.

    CFont* pOldHeadingFont;
    
  • Modifiez la fonction membre de contrôle OnDraw pour sélectionner la police personnalisée dans le contexte de l’appareil en ajoutant la ligne suivante où la police doit être utilisée.

    pOldHeadingFont = SelectFontObject(pdc, m_fontHeading);
    
  • Modifiez la fonction membre de contrôle OnDraw pour sélectionner la police précédente dans le contexte de l’appareil en ajoutant la ligne suivante une fois la police utilisée.

    pdc->SelectObject(pOldHeadingFont);
    

Une fois la propriété Police personnalisée implémentée, la page de propriétés de police standard doit être implémentée, ce qui permet aux utilisateurs de contrôle de modifier la police actuelle du contrôle. Pour ajouter l’ID de page de propriétés de la page De police standard, insérez la ligne suivante après la macro BEGIN_PROPPAGEIDS :

PROPPAGEID(CLSID_CFontPropPage)

Vous devez également incrémenter le paramètre count de votre macro BEGIN_PROPPAGEIDS par un. La ligne suivante le montre :

BEGIN_PROPPAGEIDS(CMyAxFontCtrl, 2)

Une fois ces modifications effectuées, régénérez l’ensemble du projet pour incorporer les fonctionnalités supplémentaires.

Traitement des notifications de police

Dans la plupart des cas, le contrôle doit savoir quand les caractéristiques de l’objet de police ont été modifiées. Chaque objet de police est capable de fournir des notifications lorsqu’il change en appelant une fonction membre de l’interface IFontNotification , implémentée par COleControl.

Si le contrôle utilise la propriété Font stock, ses notifications sont gérées par la OnFontChanged fonction membre de COleControl. Lorsque vous ajoutez des propriétés de police personnalisées, vous pouvez les faire utiliser la même implémentation. Dans l’exemple de la section précédente, cette opération a été effectuée en passant &m_xFontNotification lors de l’initialisation de la variable membre m_fontHeading .

Implementing multiple font object interfaces.
Implémentation de plusieurs interfaces d’objet police

Les lignes solides de la figure ci-dessus montrent que les deux objets de police utilisent la même implémentation .IFontNotification Cela peut entraîner des problèmes si vous vouliez distinguer la police modifiée.

Une façon de distinguer les notifications d’objet de police du contrôle consiste à créer une implémentation distincte de l’interface IFontNotification pour chaque objet de police dans le contrôle. Cette technique vous permet d’optimiser votre code de dessin en mettant à jour uniquement la chaîne ou les chaînes qui utilisent la police récemment modifiée. Les sections suivantes illustrent les étapes nécessaires pour implémenter des interfaces de notification distinctes pour une deuxième propriété Font. La deuxième propriété de police est supposée être la HeadingFont propriété qui a été ajoutée dans la section précédente.

Implémentation d’une nouvelle interface de notification de police

Pour distinguer les notifications de deux polices ou plus, une nouvelle interface de notification doit être implémentée pour chaque police utilisée dans le contrôle. Les sections suivantes décrivent comment implémenter une nouvelle interface de notification de police en modifiant l’en-tête de contrôle et les fichiers d’implémentation.

Ajouts au fichier d’en-tête

Dans le fichier d’en-tête de contrôle (. H), ajoutez les lignes suivantes à la déclaration de classe :

protected:
   BEGIN_INTERFACE_PART(HeadingFontNotify, IPropertyNotifySink)
      INIT_INTERFACE_PART(CMyAxFontCtrl, HeadingFontNotify)
      STDMETHOD(OnRequestEdit)(DISPID);
   STDMETHOD(OnChanged)(DISPID);
   END_INTERFACE_PART(HeadingFontNotify)

Cela crée une implémentation de l’interface IPropertyNotifySink appelée HeadingFontNotify. Cette nouvelle interface contient une méthode appelée OnChanged.

Ajouts au fichier d’implémentation

Dans le code qui initialise la police de titre (dans le constructeur de contrôle), remplacez &m_xFontNotification par &m_xHeadingFontNotify. Ensuite, ajoutez le code suivant :

STDMETHODIMP_(ULONG) CMyAxFontCtrl::XHeadingFontNotify::AddRef()
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      return 1;
}
STDMETHODIMP_(ULONG) CMyAxFontCtrl::XHeadingFontNotify::Release()
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      return 0;
}

STDMETHODIMP CMyAxFontCtrl::XHeadingFontNotify::QueryInterface(REFIID iid, LPVOID FAR* ppvObj)
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IPropertyNotifySink))
      {
         *ppvObj = this;
         AddRef();
         return NOERROR;
      }
   return ResultFromScode(E_NOINTERFACE);
}

STDMETHODIMP CMyAxFontCtrl::XHeadingFontNotify::OnChanged(DISPID)
{
   METHOD_MANAGE_STATE(CMyAxFontCtrl, HeadingFontNotify)
      pThis->InvalidateControl();
   return NOERROR;
}

STDMETHODIMP CMyAxFontCtrl::XHeadingFontNotify::OnRequestEdit(DISPID)
{
   return NOERROR;
}

Les AddRef méthodes et Release les méthodes de l’interface IPropertyNotifySink effectuent le suivi du nombre de références pour l’objet de contrôle ActiveX. Lorsque le contrôle obtient l’accès au pointeur d’interface, le contrôle appelle AddRef pour incrémenter le nombre de références. Lorsque le contrôle est terminé avec le pointeur, il appelle Release, de la même façon que celui qui GlobalFree peut être appelé pour libérer un bloc de mémoire global. Lorsque le nombre de références pour cette interface est égal à zéro, l’implémentation de l’interface peut être libérée. Dans cet exemple, la QueryInterface fonction retourne un pointeur vers une IPropertyNotifySink interface sur un objet particulier. Cette fonction permet à un contrôle ActiveX d’interroger un objet pour déterminer les interfaces qu’il prend en charge.

Une fois ces modifications apportées à votre projet, régénérez le projet et utilisez le conteneur de test pour tester l’interface. Pour plus d’informations sur la façon d’accéder au conteneur de test, consultez la page Test des propriétés et des événements avec le conteneur de test .

Voir aussi

Contrôles ActiveX MFC
Contrôles ActiveX MFC : utilisation d’images dans un contrôle ActiveX
Contrôles ActiveX MFC : utilisation des pages de propriétés stock