Partager via


Exemple : implémenter une page de propriétés

Cet exemple montre comment générer une page de propriétés qui affiche (et vous permet à la modification) des propriétés de l'interface de Classes de document .Cette interface est exposée par des documents dans Exemples du modèle objet d'environnement commun de Visual Studio (bien que la page de propriétés que vous créerez ne s'inquiétera pas d'où les objets qui manipule venu tant que ils prennent en charge l'interface appropriée).

L'exemple est basé sur Exemple ATLPages.

Pour exécuter cet exemple, vous voulez bien :

  • Ajoutez la classe de page de propriétés ATL à l'aide de la boîte de dialogue de classe d'ajout et de l'Assistant Page de propriétés ATL.

  • Modifiez la ressource de boîte de dialogue en ajoutant de nouveaux contrôles pour les propriétés intéressantes de l'interface de Document .

  • ajoutez les gestionnaires de messages pour contenir le site de page de propriétés informés des modifications effectuées par l'utilisateur.

  • Ajoutez des instructions d' #import et un typedef dans la section de gestion interne .

  • substituez IPropertyPageImpl::SetObjects pour valider des objets passés à la page de propriétés.

  • substitution IPropertyPageImpl::Activate pour initialiser l'interface de la page de propriétés.

  • substitution IPropertyPageImpl::Apply pour mettre à jour l'objet avec les dernières valeurs de propriété.

  • affichez la page de propriétés en créant un objet d'assistance simple.

  • Créez une macro qui tester la page de propriétés.

Ajouter la classe de page de propriétés ATL

D'abord, créez un projet ATL pour un serveur de DLL appelée ATLPages7.Utilisez maintenant Assistant Page de propriétés ATL pour générer une page de propriétés.Donnez à la page de propriétés Nom court de DocProperties puis de basculez vers la page de Chaînes aux éléments de propriété-page- spécifique de définir comme indiqué dans le tableau ci-dessous.

Élément

Valeur

Titre

TextDocument

Chaîne de documents

Propriétés de VCUE TextDocument

Helpfile

<blank>

Les valeurs que vous définissez dans cette page de l'assistant sont retournées au conteneur de page de propriétés lorsqu'il appelle IPropertyPage::GetPageInfo.Ce qui arrive aux chaînes ensuite qui dépend du conteneur, mais généralement ils sont utilisés pour identifier votre page à l'utilisateur.Le titre s'affiche généralement dans un onglet au-dessus de votre page et la chaîne de document peut être affichée dans une barre d'état ou une info-bulle (bien que le frame de propriété standard n'utilise pas cette chaîne du tout).

[!REMARQUE]

Les chaînes que vous définissez ici sont stockées comme des ressources de type chaîne dans votre projet par l'assistant.Vous pouvez facilement modifier ces chaînes à l'aide de l'éditeur de ressources si vous devez modifier ces informations après le code de votre page a été généré.

Cliquez sur OK pour effectuer la génération à l'assistant votre page de propriétés.

Modifier la ressource de boîte de dialogue

Maintenant que votre page de propriétés a été générée, vous devrez ajouter des contrôles à la ressource de boîte de dialogue qui représente votre page.Ajoutez une zone d'édition, un contrôle de texte statique, et une case à cocher et définissez leurs ID comme indiqué ci-dessous :

Ressource de la boîte de dialogue de modification Visual Studio

Ces contrôles sont utilisés pour afficher le nom de fichier du document et de son état en lecture seule.

[!REMARQUE]

La ressource de boîte de dialogue n'inclut pas de frame ou des boutons de commande, ni elle a l'apparence à onglets que vous pouvez s'être attendu.Ces fonctionnalités sont fournies par un frame de page de propriétés telles que celui créé en appelant OleCreatePropertyFrame.

Ajouter des gestionnaires de messages

Avec les contrôles en place, vous pouvez ajouter des gestionnaires de messages pour mettre à jour l'état modifié de la page lorsque la valeur de l'un ou l'autre des instructions break de contrôles :

BEGIN_MSG_MAP(CDocProperties)
   COMMAND_HANDLER(IDC_NAME, EN_CHANGE, OnUIChange)
   COMMAND_HANDLER(IDC_READONLY, BN_CLICKED, OnUIChange)
   CHAIN_MSG_MAP(IPropertyPageImpl<CDocProperties>)
END_MSG_MAP()

   // Respond to changes in the UI to update the dirty status of the page
   LRESULT OnUIChange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
   {
      wNotifyCode; wID; hWndCtl; bHandled;
      SetDirty(true);
      return 0;
   }

Ce code répond aux modifications apportées au contrôle d'édition ou la case à cocher en appelant IPropertyPageImpl::SetDirty, qui signale au site de page que la page a changé.En général le site de page répondra en activant ou désactivant un bouton de Appliquer sur le frame de page de propriétés.

[!REMARQUE]

Dans vos propres pages de propriétés, vous devrez peut-être effectuer précisément que les propriétés ont été modifié par l'utilisateur afin que vous puissiez éviter de mettre à jour les propriétés qui n'ont pas été modifiées.Outils de cet exemple que le code en maintenant les valeurs de propriété d'origine et en les comparant avec les valeurs actuelles de l'interface utilisateur lorsqu'il est temps d'appliquer les modifications.

Gestion interne

Ajoutez maintenant des instructions d' #import à DocProperties.h afin que le compilateur sache l'interface de Document :

// MSO.dll
#import <libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52> version("2.2") \
   rename("RGB", "Rgb")   \
   rename("DocumentProperties", "documentproperties")   \
   rename("ReplaceText", "replaceText")   \
   rename("FindText", "findText")   \
   rename("GetObject", "getObject")   \
   raw_interfaces_only

// dte.olb
#import <libid:80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2> \
   inject_statement("using namespace Office;")   \
   rename("ReplaceText", "replaceText")   \
   rename("FindText", "findText")   \
   rename("GetObject", "getObject")   \
   rename("SearchPath", "searchPath")   \
   raw_interfaces_only

Vous devez également faire référence à la classe de base d' IPropertyPageImpl ; ajoutez typedef suivant à la classe de CDocProperties :

typedef IPropertyPageImpl<CDocProperties> PPGBaseClass;

Substituer IPropertyPageImpl::SetObjects

La première méthode d' IPropertyPageImpl que vous devez substituer est SetObjects.Voici que vous ajouterez du code pour vérifier qu'un objet unique a été passé et qu'il prend en charge l'interface de Document que vous attendez :

STDMETHOD(SetObjects)(ULONG nObjects, IUnknown** ppUnk)
{
   HRESULT hr = E_INVALIDARG;
   if (nObjects == 1)
   {
      CComQIPtr<EnvDTE::Document> pDoc(ppUnk[0]);
      if (pDoc)
         hr = PPGBaseClass::SetObjects(nObjects, ppUnk);
   }
   return hr;
}

[!REMARQUE]

Il est logique de prendre en charge un objet unique pour cette page car vous permettrez à l'utilisateur de définir le nom de fichier de l'objet — un seul fichier peut exister à tout un emplacement.

Substituer IPropertyPageImpl::Activate

L'étape suivante consiste à initialiser la page de propriétés avec les valeurs de propriété de l'objet sous-jacent lorsque la page est d'abord créée.

Dans ce cas vous devez ajouter les membres suivants à la classe comme vous utiliserez également les valeurs de propriété initiales pour la comparaison lorsque les utilisateurs de la page appliquent leurs modifications :

CComBSTR m_bstrFullName;  // The original name
VARIANT_BOOL m_bReadOnly; // The original read-only state

L'implémentation de la classe de base de la méthode d' Exécutez est chargé de créer la boîte de dialogue et ses contrôles, vous pouvez substituer cette méthode et ajoutez votre propre initialisation après avoir appelé la classe de base :

STDMETHOD(Activate)(HWND hWndParent, LPCRECT prc, BOOL bModal)
{
   // If we don't have any objects, this method should not be called
   // Note that OleCreatePropertyFrame will call Activate even if
   // a call to SetObjects fails, so this check is required
   if (!m_ppUnk)
      return E_UNEXPECTED;

   // Use Activate to update the property page's UI with information
   // obtained from the objects in the m_ppUnk array

   // We update the page to display the Name and ReadOnly properties
   // of the document

   // Call the base class
   HRESULT hr = PPGBaseClass::Activate(hWndParent, prc, bModal);
   if (FAILED(hr))
      return hr;

   // Get the EnvDTE::Document pointer
   CComQIPtr<EnvDTE::Document> pDoc(m_ppUnk[0]);
   if (!pDoc)
      return E_UNEXPECTED;

   // Get the FullName property
   hr = pDoc->get_FullName(&m_bstrFullName);
   if (FAILED(hr))
      return hr;

   // Set the text box so that the user can see the document name
   USES_CONVERSION;
   SetDlgItemText(IDC_NAME, CW2CT(m_bstrFullName));

   // Get the ReadOnly property
   m_bReadOnly = VARIANT_FALSE;
   hr = pDoc->get_ReadOnly(&m_bReadOnly);
   if (FAILED(hr))
      return hr;

   // Set the check box so that the user can see the document's read-only status
   CheckDlgButton(IDC_READONLY, m_bReadOnly ? BST_CHECKED : BST_UNCHECKED);

   return hr;
}

Ce code utilise les méthodes COM d'interface de Document pour obtenir des propriétés qui vous intéresse.Il utilise ensuite les wrappers de l'API Win32 fournis par CDialogImpl et ses classes de base pour afficher les valeurs de propriété à l'utilisateur.

Substituer IPropertyPageImpl::Apply

Lorsque les utilisateurs souhaitent appliquer leurs modifications apportées aux objets, le site de page de propriétés appelle la méthode d' appliquez .Il s'agit de l'emplacement pour effectuer l'inverse du code dans Activate — alors qu' Activate a pris des valeurs de l'objet et les a envoyées dans les contrôles de la page de propriétés, Appliquer prend les valeurs des contrôles de la page de propriétés et les pousse dans l'objet.

STDMETHOD(Apply)(void)
{
   // If we don't have any objects, this method should not be called
   if (!m_ppUnk)
      return E_UNEXPECTED;

   // Use Apply to validate the user's settings and update the objects'
   // properties

   // Check whether we need to update the object
   // Quite important since standard property frame calls Apply
   // when it doesn't need to
   if (!m_bDirty)
      return S_OK;

   HRESULT hr = E_UNEXPECTED;

   // Get a pointer to the document
   CComQIPtr<EnvDTE::Document> pDoc(m_ppUnk[0]);
   if (!pDoc)
      return hr;

   // Get the read-only setting
   VARIANT_BOOL bReadOnly = IsDlgButtonChecked(IDC_READONLY) ? VARIANT_TRUE : VARIANT_FALSE;

   // Get the file name
   CComBSTR bstrName;
   if (!GetDlgItemText(IDC_NAME, bstrName.m_str))
      return E_FAIL;

   // Set the read-only property
   if (bReadOnly != m_bReadOnly)
   {
      hr = pDoc->put_ReadOnly(bReadOnly);
      if (FAILED(hr))
         return hr;
   }

   // Save the document
   if (bstrName != m_bstrFullName)
   {
      EnvDTE::vsSaveStatus status;
      hr = pDoc->Save(bstrName, &status);
      if (FAILED(hr))
         return hr;
   }

   // Clear the dirty status of the property page
   SetDirty(false);

   return S_OK;
}

[!REMARQUE]

Le contrôle sur m_bDirty au début de cette implémentation est un premier contrôle pour éviter les mises à jour inutiles les objets si Appliquer est appelé plusieurs fois.Il existe également des contrôles sur chacune des valeurs de propriété de vérifier que les modifications entraînent un appel de méthode à Document.

[!REMARQUE]

Expose NomComplet deDocument en tant que propriété en lecture seule.Pour mettre à jour le nom de fichier du document en fonction de les modifications apportées à la page de propriétés, vous devez utiliser la méthode Enregistrer pour enregistrer le fichier sous un nom différent.Ainsi, le code d'une page de propriétés ne doit pas se limiter à obtenir ou de définir des propriétés.

Affichage de la page de propriétés

Pour afficher cette page, vous devez créer un objet d'assistance simple.L'objet d'assistance fournit une méthode qui simplifie l'API d' OleCreatePropertyFrame pour afficher un connecté d'une page à un objet unique.Ce programme d'assistance est conçu afin qu'il puisse être utilisé de Visual Basic.

Utilisez ajoutez la boîte de dialogue de classe et Assistant Objet simple ATL pour générer une nouvelle classe et utiliser Helper comme son nom court.Une fois créé, ajoutez une méthode comme indiqué dans le tableau ci-dessous.

Élément

Valeur

Nom de la méthode

ShowPage

Paramètres

[in] BSTR bstrCaption, [in] BSTR bstrID, [in] IUnknown* pUnk

Le paramètre d' bstrCaption est la légende à afficher comme titre de la boîte de dialogue.Le paramètre d' bstrID est une chaîne qui représente le CLSID ou un progid de la page de propriétés pour afficher.Le paramètre d' pUnk sera le pointeur d' IUnknown de l'objet dont les propriétés sont configurées par la page de propriétés.

Implémentez la méthode comme indiqué ci-dessous :

STDMETHODIMP CHelper::ShowPage(BSTR bstrCaption, BSTR bstrID, IUnknown* pUnk)
{
   if (!pUnk)
      return E_INVALIDARG;

   // First, assume bstrID is a string representing the CLSID 
   CLSID theCLSID = {0};
   HRESULT hr = CLSIDFromString(bstrID, &theCLSID);
   if (FAILED(hr))
   {
      // Now assume bstrID is a ProgID
      hr = CLSIDFromProgID(bstrID, &theCLSID);
      if (FAILED(hr))
         return hr;
   }

   // Use the system-supplied property frame
   return OleCreatePropertyFrame(
      GetActiveWindow(),   // Parent window of the property frame
      0,           // Horizontal position of the property frame
      0,           // Vertical position of the property frame
      bstrCaption, // Property frame caption
      1,           // Number of objects
      &pUnk,       // Array of IUnknown pointers for objects
      1,           // Number of property pages
      &theCLSID,   // Array of CLSIDs for property pages
      NULL,        // Locale identifier
      0,           // Reserved - 0
      NULL         // Reserved - 0
      );
}

Créer une macro

Une fois que vous avez généré le projet, vous pouvez tester la page de propriétés et l'objet d'assistance à l'aide d'une macro simple que vous pouvez créer et exécuter dans l'environnement de développement Visual Studio.Cette macro crée un objet d'assistance, puis appelle sa méthode de ShowPage à l'aide de l'identificateur programmatique de la page de propriétés de DocProperties et du pointeur d' IUnknown du document active dans l'éditeur Visual Studio.Le code que vous avez besoin pour cette macro est indiqué ci-dessous :

Imports EnvDTE
Imports System.Diagnostics

Public Module AtlPages

    Public Sub Test()
        Dim Helper
        Helper = CreateObject("ATLPages7.Helper.1")

        On Error Resume Next
        Helper.ShowPage( _
            ActiveDocument.Name, _
            "ATLPages7Lib.DocumentProperties.1", _
            DTE.ActiveDocument _
            )
    End Sub

End Module

Lorsque vous exécutez cette macro, la page de propriétés s'affiche et le nom de fichier et l'état en lecture seule actuel - texte du document actif.L'état de lecture seule du document indique uniquement la possibilité d'écrire au document dans l'environnement de développement ; il n'affecte pas l'attribut de lecture seule du fichier sur le disque.

Voir aussi

Concepts

Pages de propriétés ATL COM

Exemple ATLPages