Compartir a través de


Example: Implementing a Property Page

Este ejemplo muestra cómo compilar una página de propiedades que muestre (y permite cambiar) las propiedades de la interfaz de Clases de documento . Esta interfaz es expuesta por los documentos en Ejemplos del modelo de objetos de entorno común de Visual Studio (aunque la página de propiedades que creará no cuidará de donde los objetos que manipulan alcanzado mientras admiten la interfaz correcta).

el ejemplo se basa en Ejemplo ATLPages.

Para completar este ejemplo, debe:

  • Agregue la clase de la página de propiedades ATL mediante el cuadro de diálogo agregar clase y el Asistente para páginas de propiedades ATL.

  • Edite el recurso de cuadro de diálogo agregando nuevos controles para las propiedades interesantes de la interfaz de Documento .

  • Agregue controladores de mensajes para mantener el sitio de la página de propiedades a los cambios realizados por el usuario.

  • Agregue algunas instrucciones de #import y una definición en la sección de mantenimiento .

  • Reemplazo IPropertyPageImpl:: SetObjects para validar los objetos que se pasan a la página de propiedades.

  • Reemplazo IPropertyPageImpl:: Activar para inicializar la interfaz de la página de propiedades.

  • Reemplazo IPropertyPageImpl:: Aplicar para actualizar el objeto con los últimos valores de propiedad.

  • Abra la página de propiedades creando un objeto simple auxiliares.

  • cree una macro que va a la página de propiedades.

Agregar una clase de la página de propiedades ATL

Primero, cree un nuevo proyecto ATL para un servidor de una DLL denominada ATLPages7. ahora utilice Asistente para páginas de propiedades ATL para generar una página de propiedades. Dé a la página de propiedades nombre corto de DocProperties después a Cadenas la página para establecer elementos propiedad-página-específicos tal y como se muestra en la siguiente tabla.

Elemento

Valor

Título

TextDocument

Cadena de Documento

propiedades de VCUE TextDocument

Helpfile

<espacio en blanco>

Los valores que establece en esta página del asistente devolverán al contenedor de la página de propiedades cuando llama a IPropertyPage:: GetPageInfo. Lo que sucede con las cadenas después que depende del contenedor, pero se utilizan normalmente para identificar la página al usuario. El título aparecerá normalmente en una ficha a la página y la cadena de Documento se puede mostrar en una barra de estado o una información sobre herramientas (aunque el cuadro estándar de la propiedad no utiliza esta cadena en absoluto).

Nota

Las cadenas que el asistente establece aquí almacena como recursos de cadena en el proyecto.Es fácil modificar estas cadenas utilizando el editor de recursos si necesita cambiar esta información después del código de la página se ha generado.

Haga clic Aceptar para que el asistente genere la página de propiedades.

Ahora que se ha generado la página de propiedades, necesitará agregar controles al recurso de cuadro de diálogo que representa la página. Agregue un cuadro de edición, un control de texto estático, y una casilla y establezca su id. como se muestra a continuación:

Edición de un recurso de cuadro de diálogo

Estos controles se utilicen para mostrar el nombre de archivo de documento y su estado de sólo lectura.

Nota

El recurso de cuadro de diálogo no incluye un marco o los botones de comando, ni tampoco tabular tengan que puede haber esperado.Estas características son proporcionadas por un marco de página de propiedades como el que se creó llamando a OleCreatePropertyFrame.

Controladores de mensajes de suma

Con el nombre de los controles, puede agregar controladores de mensajes para actualizar el estado modificado de la página cuando el valor de cualquiera de los cambios de controles:

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;
   }

Este código responde a los cambios realizados en el control de edición o la casilla llamando a IPropertyPageImpl:: SetDirty, que informa al sitio de la página que la página ha cambiado. El sitio de la página responderá normalmente habilitar o deshabilitar un botón de Aplicar en el cuadro de la página de propiedades.

Nota

En poseer las páginas de propiedades, puede ser necesario realizar un seguimiento de exacto que las propiedades han sido modificadas por el usuario para poder impedir actualizar las propiedades que no se han cambiado.Este ejemplo aplica ese código un seguimiento de los valores de propiedad originales y comparándolos con los valores actuales de la interfaz de usuario cuando llega el momento de aplicar los cambios.

mantenimiento

Ahora agregue un par de instrucciones de #import a DocProperties.h de modo que el compilador sepa sobre la interfaz de Documento :

// 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

También necesitará hacer referencia a la clase base de IPropertyPageImpl ; agregue typedef siguiente a la clase de CDocProperties :

typedef IPropertyPageImpl<CDocProperties> PPGBaseClass;

Reemplazar IPropertyPageImpl:: SetObjects

El primer método de IPropertyPageImpl que necesita invalidar es SetObjects. A continuación agregará código para comprobar que solo se ha pasado un objeto único y admite la interfaz de Documento que espera:

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;
}

Nota

Tiene sentido de admitir un solo objeto de esta página porque permitirá que el usuario establezca el nombre de archivo de objeto (solo un archivo puede existir en una ubicación.

Reemplazar IPropertyPageImpl:: Activar

El paso siguiente es inicializar la página de propiedades con los valores de propiedad del objeto subyacente cuando la página se crea por primera vez.

En este caso debe agregar los miembros siguientes a la clase puesto que también utilizará los valores de propiedad iniciales para la comparación cuando se aplican los usuarios de la página los cambios:

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

La implementación de la clase base del método de Activar es responsable de crear el cuadro de diálogo y sus controles, lo que puede invalidar este método y agregarlo dispone de inicialización después de llamar a la clase 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;
}

Este código utiliza los métodos COM de la interfaz de Documento para obtener las propiedades de interés. Utilice los contenedores de la API Win32 proporcionados por CDialogImpl y sus clases base para mostrar los valores de propiedad al usuario.

Reemplazar IPropertyPageImpl:: Aplicar

Cuando los usuarios desean aplicar los cambios en los objetos, el sitio de la página de propiedades llamará al método de Aplicar . Éste es el lugar para hacer el inverso del código en Activar — mientras Activar tardó valores de objeto y los insertó en los controles de la página de propiedades, Aplicar toma los valores de los controles en la página de propiedades y los inserta en el objeto.

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;
}

Nota

La comprobación en m_bDirty al principio de esta implementación es una comprobación inicial para evitar las actualizaciones innecesarias de objetos si Aplicar se llama más de una vez.Hay también comprueba en cada uno de los valores de propiedad para asegurarse de que solo los cambios da lugar a una llamada al método a Documento.

Nota

Expone Fullname deDocumento como propiedad de sólo lectura.Para actualizar el nombre de archivo de documento basado en los cambios realizados en la página de propiedades, hay que utilizar el método de Guardar para guardar el archivo con un nombre diferente.Así, el código de una página de propiedades no tiene que limitarse a obtener o establecer propiedades.

Mostrar la página de propiedades

Para mostrar esta página, debe crear un objeto simple auxiliares. El objeto auxiliar proporcionará un método que simplifica OleCreatePropertyFrame API para mostrar una única página conectada a un único objeto. Esta aplicación auxiliar se diseñó para que se pueda utilizar de Visual Basic.

Utilice agregue el cuadro de diálogo de la clase y Asistente para objetos simples ATL para generar una nueva clase y utilizar Helper como su nombre corto. Una vez creado, agregue un método como se muestra en la siguiente tabla.

Elemento

Valor

Nombre del método

ShowPage

Parámetros

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

El parámetro de bstrCaption es la leyenda que se mostrará como título del cuadro de diálogo. El parámetro de bstrID es una cadena que representa el CLSID o ProgID de la página de propiedades para mostrar. El parámetro de pUnk será el puntero de IUnknown de objeto cuyas propiedades se configurarán por la página de propiedades.

Implemente el método como se muestra a continuación:

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
      );
}

crear una macro

Una vez compilado el proyecto, puede probar la página de propiedades y el objeto auxiliar mediante una macro simple que puede crear y ejecutar en el entorno de desarrollo de Visual Studio. Esta macro creará un objeto auxiliar, después llama a su método de ShowPage mediante ProgID de la página de propiedades de DocProperties y el puntero de IUnknown de documento activo actualmente en el editor de Visual Studio. El código que necesita para esta macro se muestra a continuación:

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

Al ejecutar esta macro, la página de propiedades se mostrará que muestra el nombre de archivo y el estado de sólo lectura actualmente de documento de texto activo. El estado de sólo lectura del documento sólo refleja la capacidad para escribir el documento en el entorno de desarrollo; no afecta al atributo de sólo lectura del archivo en el disco.

Vea también

Conceptos

Páginas de propiedades COM de ATL

Ejemplo ATLPages