Compartir a través de


Hojas de propiedades y páginas de propiedades

Las propiedades de un objeto se exponen a los clientes iguales que los métodos a través de interfaces COM o la implementación de IDispatch del objeto, lo que permite cambiar las propiedades mediante programas que llaman a estos métodos. La tecnología OLE de las páginas de propiedades proporciona los medios para crear una interfaz de usuario para las propiedades de un objeto según los estándares de la interfaz de usuario de Windows. Por lo tanto, las propiedades se exponen a los usuarios finales. La hoja de propiedades de un objeto es un cuadro de diálogo con pestañas donde cada pestaña corresponde a una página de propiedades específica. El modelo OLE para trabajar con páginas de propiedades consta de estas características:

  • Cada página de propiedades se administra mediante un objeto en proceso que implementa IPropertyPage o IPropertyPage2. Cada página se identifica con su propio CLSID único.
  • Un objeto especifica su compatibilidad con las páginas de propiedades mediante la implementación de ISpecifyPropertyPages. A través de esta interfaz, el autor de la llamada puede obtener una lista de CLSID que identifican las páginas de propiedades específicas que admite el objeto. Si el objeto especifica un CLSID de página de propiedades, el objeto debe poder recibir los cambios de propiedad de la página de propiedades.
  • Cualquier fragmento de código (cliente o objeto) que quiera mostrar la hoja de propiedades de un objeto pasa el puntero IUnknown del objeto (o una matriz si se van a ver afectados varios objetos) junto con una matriz de CLSID de páginas a OleCreatePropertyFrame o OleCreatePropertyFrameIndirect, que crea el cuadro de diálogo con pestañas.
  • El cuadro de diálogo de marco de propiedad crea una instancia única de cada página de propiedades, usando CoCreateInstance en cada CLSID. El marco de propiedad obtiene al menos un puntero IPropertyPage para cada página. Además, el marco crea un objeto de sitio de página de propiedades en sí mismo para cada página. Cada sitio implementa IPropertyPageSite y este puntero se pasa a cada página. A continuación, la página se comunica con el sitio a través de este puntero de interfaz.
  • Cada página también se hace consciente del objeto u objetos para los que se ha invocado; es decir, el marco de propiedad pasa los punteros IUnknownde los objetos a cada página. Cuando se le indica que aplique cambios a los objetos, cada página consulta el puntero de interfaz adecuado y pasa nuevos valores de propiedad a los objetos de la manera que desee. No hay ninguna información sobre cómo se debe producir dicha comunicación.
  • Un objeto también puede admitir la exploración por propiedad a través de la interfaz IPerPropertyBrowsing , lo que permite al objeto especificar qué propiedad debe recibir el foco inicial cuando se muestra la página de propiedades y especificar cadenas y valores que el cliente puede mostrar en su propia interfaz de usuario.

Estas características se muestran en el diagrama siguiente:

Diagrama que muestra las hojas de propiedades y las características de las páginas de propiedades.

Estas interfaces se definen de la siguiente manera:

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

El método ISpecifyPropertyPages::GetPages devuelve una matriz contada de valores UUID (GUID) cada uno de los cuales describe el CLSID de una página de propiedades que el objeto desea mostrar. Quien invoque la hoja de propiedades con OleCreatePropertyFrame o OleCreatePropertyFrameIndirect pasa esta matriz a la función . Tenga en cuenta que si el autor de la llamada desea mostrar páginas de propiedades para varios objetos, solo debe pasar la intersección de las listas CLSID de todos los objetos a estas funciones. En otras palabras, el autor de la llamada solo debe invocar páginas de propiedades que son comunes a todos los objetos.

Además, el autor de la llamada pasa también los punteros IUnknown a los objetos afectados a las funciones de api. Ambas funciones de API crean un cuadro de diálogo de marco de propiedad y crean una instancia de un sitio de página con IPropertyPageSite para cada página que se cargará. A través de esta interfaz, una página de propiedades puede:

  • Recupere el idioma actual usado en la hoja de propiedades a través de GetLocaleID.
  • Pida al fotograma que procese las pulsaciones de teclas a través de TranslateAccelerator.
  • Notifique el marco de los cambios en la página a través de OnStatusChange.
  • Obtenga un puntero de interfaz para el marco en sí a través de GetPageContainer, aunque no hay interfaces definidas para el fotograma en este momento para esta función siempre devuelve E_NOTIMPL.

El marco de propiedad crea una instancia de cada objeto de página de propiedades y obtiene la interfaz IPropertyPage de cada página. A través de esta interfaz, el marco informa a la página de su sitio de página (SetPageSite), recupera las dimensiones de página y las cadenas (GetPageInfo), pasa los punteros de interfaz a los objetos afectados (SetObjects), indica a la página cuándo crear y destruir sus controles (Activar y desactivar), indica a la página que muestre o cambie su posición (Mostrar y mover), indique a la página que aplique sus valores actuales a los objetos afectados (Aplicar). ), comprueba el estado desfasado de la página (IsPageDirty), invoca la ayuda (Ayuda) y pasa pulsaciones de teclas a la página (TranslateAccelerator).

Un objeto también puede admitir la exploración por propiedad, que proporciona:

  1. Una manera (a través de IPerPropertyBrowsing e IPropertyPage2) para especificar qué propiedad en qué página de propiedades se debe proporcionar el foco inicial cuando se muestra una hoja de propiedades por primera vez
  2. Una manera (a través de IPerPropertyBrowsing) para que el objeto especifique valores predefinidos y las cadenas descriptivas correspondientes que se podrían mostrar en la propia interfaz de usuario de un cliente para las propiedades.

Un objeto puede optar por admitir (2) sin admitir (1), como cuando el objeto no tiene ninguna hoja de propiedades.

Las interfaces IPropertyPage2 e IPerPropertyBrowsing se definen de la siguiente manera:

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

Para especificar su compatibilidad con estas funcionalidades, el objeto implementa IPerPropertyBrowsing. A través de esta interfaz, el autor de la llamada puede solicitar la información necesaria para lograr la exploración, como cadenas predefinidas (GetPredefinedStrings) y valores (GetPredefinedValue), así como una cadena de presentación para una propiedad determinada (GetDisplayString).

Además, el cliente puede obtener el CLSID de la página de propiedades que permite al usuario editar una propiedad determinada identificada con un DISPID (MapPropertyToPage). A continuación, el cliente indica al marco de propiedad que active esa página inicialmente pasando el CLSID y el DISPID a OleCreatePropertyFrameIndirect. El marco activa esa página primero y pasa el DISPID a la página a través de IPropertyPage2::EditProperty. A continuación, la página establece el foco en el campo de edición de esa propiedad. De este modo, un cliente puede pasar de un nombre de propiedad en su propia interfaz de usuario a la página de propiedades que puede manipular esa propiedad.

Páginas de propiedades y hojas de propiedades