Pages et feuilles de propriétés

Les propriétés d’un objet sont exposées aux clients de la même façon que les méthodes via les interfaces COM ou l’implémentation IDispatch de l’objet, ce qui permet aux programmes qui appellent ces méthodes de modifier les propriétés. la technologie OLE des pages de propriétés fournit les moyens de créer une interface utilisateur pour les propriétés d’un objet en fonction de Windows normes de l’interface utilisateur. Ainsi, les propriétés sont exposées aux utilisateurs finaux. La feuille de propriétés d’un objet est une boîte de dialogue à onglets dans laquelle chaque onglet correspond à une page de propriétés spécifique. Le modèle OLE pour l’utilisation des pages de propriétés est constitué des fonctionnalités suivantes :

  • Chaque page de propriétés est gérée par un objet in-process qui implémente IPropertyPage ou IPropertyPage2. Chaque page est identifiée avec son propre CLSID unique.
  • Un objet spécifie sa prise en charge pour les pages de propriétés en implémentant ISpecifyPropertyPages. Via cette interface, l’appelant peut obtenir une liste de CLSID identifiant les pages de propriétés spécifiques que l’objet prend en charge. Si l’objet spécifie un CLSID de page de propriétés, l’objet doit être en mesure de recevoir des modifications de propriété à partir de la page de propriétés.
  • Tout morceau de code (client ou objet) qui souhaite afficher la feuille de propriétés d’un objet passe le pointeur IUnknown de l’objet (ou un tableau si plusieurs objets doivent être affectés), ainsi qu’un tableau de CLSID de page à OleCreatePropertyFrame ou OleCreatePropertyFrameIndirect, ce qui crée la boîte de dialogue à onglets.
  • La boîte de dialogue frame de propriété instancie une seule instance de chaque page de propriétés, à l’aide de CoCreateInstance sur chaque CLSID. Le frame de propriété obtient au moins un pointeur IPropertyPage pour chaque page. En outre, le frame crée un objet de site de page de propriétés en lui-même pour chaque page. Chaque site implémente IPropertyPageSite et ce pointeur est transmis à chaque page. La page communique ensuite avec le site via ce pointeur d’interface.
  • Chaque page est également consciente de l’objet ou des objets pour lesquels elle a été appelée ; autrement dit, le frame de propriété passe les pointeurs IUnknowndes objets à chaque page. Lorsque vous êtes invité à appliquer les modifications aux objets, chaque page interroge le pointeur d’interface approprié et passe les nouvelles valeurs de propriété aux objets de la manière souhaitée. Il n’existe aucune stipulation sur la façon dont cette communication doit se produire.
  • Un objet peut également prendre en charge la navigation par propriété via l’interface IPerPropertyBrowsing , ce qui permet à l’objet de spécifier quelle propriété doit recevoir le focus initial lorsque la page de propriétés est affichée et spécifier des chaînes et des valeurs qui peuvent être affichées par le client dans sa propre interface utilisateur.

Ces fonctionnalités sont illustrées dans le diagramme suivant :

Diagramme qui montre les fonctionnalités des feuilles de propriétés et des pages de propriétés.

Ces interfaces sont définies comme suit :

interface ISpecifyPropertyPages : IUnknown 
  { 
    HRESULT GetPages([out] CAUUID *pPages); 
  }; 
 
 
interface IPropertyPage : IUnknown 
  { 
    HRESULT SetPageSite([in] IPropertyPageSite *pPageSite); 
    HRESULT Activate([in] HWND hWndParent, [in] LPCRECT prc 
        , [in] BOOL bModal); 
    HRESULT Deactivate(void); 
    HRESULT GetPageInfo([out] PROPPAGEINFO *pPageInfo); 
    HRESULT SetObjects([in] ULONG cObjects 
        , [in, max_is(cObjects)] IUnknown **ppunk); 
    HRESULT Show([in] UINT nCmdShow); 
    HRESULT Move([in] LPCRECT prc); 
    HRESULT IsPageDirty(void); 
    HRESULT Apply(void); 
    HRESULT Help([in] LPCOLESTR pszHelpDir); 
    HRESULT TranslateAccelerator([in] LPMSG pMsg); 
  } 
 
interface IPropertyPageSite : IUnknown 
  { 
    HRESULT OnStatusChange([in] DWORD dwFlags); 
    HRESULT GetLocaleID([out] LCID *pLocaleID); 
    HRESULT GetPageContainer([out] IUnknown **ppUnk); 
    HRESULT TranslateAccelerator([in] LPMSG pMsg); 
  } 
 

La méthode ISpecifyPropertyPages :: GetPages retourne un tableau compté de valeurs UUID (Guid) qui décrivent chacune le CLSID d’une page de propriétés que l’objet souhaite afficher. Quiconque appelle la feuille de propriétés avec OleCreatePropertyFrame ou OleCreatePropertyFrameIndirect passe ce tableau à la fonction. Notez que si l’appelant souhaite afficher des pages de propriétés pour plusieurs objets, il doit uniquement transmettre l’intersection des listes CLSID de tous les objets à ces fonctions. En d’autres termes, l’appelant doit uniquement appeler les pages de propriétés qui sont communes à tous les objets.

En outre, l’appelant transmet également les pointeurs IUnknown aux objets affectés aux fonctions d’API. Les deux fonctions API créent une boîte de dialogue de frame de propriété et instancient un site de page avec IPropertyPageSite pour chaque page qu’il chargera. Grâce à cette interface, une page de propriétés peut :

  • Récupérez la langue actuelle utilisée dans la feuille de propriétés par le biais de GetLocaleID.
  • Demandez au frame de traiter les séquences de touches via TranslateAccelerator.
  • Notifiez le frame des modifications de la page via OnStatusChange.
  • Obtenez un pointeur d’interface pour le frame lui-même via GetPageContainer, bien qu’il n’y ait pas d’interfaces définies pour le frame à ce stade pour cette fonction, retourne toujours E _ NOTIMPL.

Le frame de propriété instancie chaque objet de page de propriétés et obtient l’interface IPropertyPage de chaque page. Via cette interface, le frame informe la page de son site de page (SetPageSite), récupère les dimensions et les chaînes de page (GetPageInfo), passe les pointeurs d’interface aux objets affectés (SetObjects), indique à la page quand créer et détruire ses contrôles (activation et désactivation). indique à la page d’afficher ou de se repositionner (Afficher et déplacer), demande à la page d’appliquer ses valeurs actuelles aux objets affectés (appliquer), vérifie l’état d’intégrité de la page (IsPageDirty), appelle l’aide (aide) et passe des séquences de touches à la page (TranslateAccelerator).

Un objet peut également prendre en charge la navigation par propriété, qui fournit :

  1. Une méthode (via IPerPropertyBrowsing et IPropertyPage2) pour spécifier la propriété sur laquelle la page de propriétés doit recevoir le focus initial lorsqu’une feuille de propriétés est affichée pour la première fois
  2. Méthode (via IPerPropertyBrowsing) pour l’objet qui spécifie des valeurs prédéfinies et des chaînes descriptives correspondantes qui peuvent être affichées dans l’interface utilisateur propre à un client pour les propriétés.

Un objet peut choisir de prendre en charge (2) sans prendre en charge (1), comme lorsque l’objet n’a aucune feuille de propriétés.

Les interfaces IPropertyPage2 et IPerPropertyBrowsing sont définies comme suit :

interface IPerPropertyBrowsing : IUnknown 
  { 
    HRESULT GetDisplayString([in] DISPID dispID, [out] BSTR *pbstr); 
    HRESULT MapPropertyToPage([in] DISPID dispID, [out] CLSID *pclsid); 
    HRESULT GetPredefinedStrings([in] DISPID dispID, [out] CALPOLESTR *pcaStringsOut, [out] CADWORD *pcaCookiesOut); 
    HRESULT GetPredefinedValue([in] DISPID dispID, [in] DWORD dwCookie, [out] VARIANT *pvarOut); 
  } 
 
interface IPropertyPage2 : IPropertyPage 
  { 
    HRESULT EditProperty([in] DISPID dispID); 
  } 
 

Pour spécifier sa prise en charge de telles fonctionnalités, l’objet implémente IPerPropertyBrowsing. Grâce à cette interface, l’appelant peut demander les informations nécessaires pour accomplir l’exploration, telles que les chaînes prédéfinies (GetPredefinedStrings) et les valeurs (GetPredefinedValue), ainsi qu’une chaîne d’affichage pour une propriété donnée (GetDisplayString).

En outre, le client peut obtenir le CLSID de la page de propriétés qui permet à l’utilisateur de modifier une propriété donnée identifiée par un DISPID (MapPropertyToPage). Le client demande ensuite au frame de propriété d’activer cette page initialement en passant le CLSID et le DISPID à OleCreatePropertyFrameIndirect. Le frame active d’abord cette page et passe le DISPID à la page via IPropertyPage2 :: EditProperty. La page définit ensuite le focus sur le champ d’édition de cette propriété. De cette façon, un client peut passer d’un nom de propriété dans sa propre interface utilisateur à la page de propriétés qui peut manipuler cette propriété.

Pages de propriétés et feuilles de propriétés