Compartilhar via


Folhas de propriedades e páginas de propriedades

As propriedades de um objeto são expostas aos clientes da mesma forma que os métodos por meio de interfaces COM ou da implementação IDispatch do objeto, permitindo que as propriedades sejam alteradas por programas que chamam esses métodos. A tecnologia OLE de páginas de propriedades fornece os meios para criar uma interface do usuário para as propriedades de um objeto de acordo com os padrões de interface do usuário do Windows. Assim, as propriedades são expostas aos usuários finais. A folha de propriedades de um objeto é uma caixa de diálogo com guias em que cada guia corresponde a uma página de propriedades específica. O modelo OLE para trabalhar com páginas de propriedades consiste nestes recursos:

  • Cada página de propriedades é gerenciada por um objeto em processo que implementa IPropertyPage ou IPropertyPage2. Cada página é identificada com seu próprio CLSID exclusivo.
  • Um objeto especifica seu suporte para páginas de propriedades implementando ISpecifyPropertyPages. Por meio dessa interface, o chamador pode obter uma lista de CLSIDs identificando as páginas de propriedades específicas que o objeto suporta. Se o objeto especificar uma página de propriedades CLSID, o objeto deverá ser capaz de receber alterações de propriedade da página de propriedades.
  • Qualquer parte do código (cliente ou objeto) que deseja exibir a folha de propriedades de um objeto passa o ponteiro IUnknown do objeto (ou uma matriz se vários objetos forem afetados) junto com uma matriz de CLSIDs de página para OleCreatePropertyFrame ou OleCreatePropertyFrameIndirect, que cria a caixa de diálogo com guias.
  • A caixa de diálogo do quadro de propriedade instancia uma única instância de cada página de propriedades, usando CoCreateInstance em cada CLSID. O quadro de propriedade obtém pelo menos um ponteiro IPropertyPage para cada página. Além disso, o quadro cria um objeto de site de página de propriedades em si mesmo para cada página. Cada site implementa IPropertyPageSite e esse ponteiro é passado para cada página. Em seguida, a página se comunica com o site por meio desse ponteiro de interface.
  • Cada página também é informada do objeto ou objetos para os quais foi invocada; ou seja, o quadro de propriedade passa os ponteiros IUnknowndos objetos para cada página. Quando instruída a aplicar alterações aos objetos, cada página consulta o ponteiro de interface apropriado e passa novos valores de propriedade para os objetos da maneira desejada. Não há estipulações sobre como essa comunicação deve acontecer.
  • Um objeto também pode oferecer suporte à navegação por propriedade pela interface IPerPropertyBrowsing permitindo que o objeto especifique qual propriedade deve receber o foco inicial quando a página de propriedades for exibida e especifique cadeias de caracteres e valores que podem ser exibidos pelo cliente em sua própria interface do usuário.

Esses recursos são ilustrados no diagrama a seguir:

Diagram that shows the property sheets and property pages features.

Essas interfaces são definidas da seguinte forma:

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

O método ISpecifyPropertyPages::GetPages retorna uma matriz contada de valores UUID (GUID), cada um dos quais descreve o CLSID de uma página de propriedades que o objeto gostaria de exibir. Quem invoca a folha de propriedades com OleCreatePropertyFrame ou OleCreatePropertyFrameIndirect passa essa matriz para a função. Observe que, se o chamador desejar exibir páginas de propriedades para vários objetos, ele deverá apenas passar a interseção das listas CLSID de todos os objetos para essas funções. Em outras palavras, o chamador só deve invocar páginas de propriedades que são comuns a todos os objetos.

Além disso, o chamador passa os ponteiros IUnknown para os objetos afetados para as funções da API também. Ambas as funções da API criam uma caixa de diálogo de quadro de propriedade e instanciam um site de página com IPropertyPageSite para cada página que será carregada. Através desta interface uma página de propriedades pode:

  • Recupere o idioma atual usado na folha de propriedades por meio de GetLocaleID.
  • Peça ao quadro para processar pressionamentos de tecla por meio do TranslateAccelerator.
  • Notifique o quadro de alterações na página por meio de OnStatusChange.
  • Obtenha um ponteiro de interface para o próprio quadro por meio de GetPageContainer, embora não haja interfaces definidas para o quadro no momento, pois essa função sempre retorna E_NOTIMPL.

O quadro de propriedade instancia cada objeto de página de propriedade e obtém a interface IPropertyPage de cada página. Através dessa interface o quadro informa a página de seu site de página (SetPageSite), recupera as dimensões e cadeias de caracteres da página (GetPageInfo), passa os ponteiros da interface para os objetos afetados (SetObjects), informa à página quando criar e destruir seus controles (Ativar e Desativar), instrui a página a mostrar ou se reposicionar (Mostrar e Mover), instrui a página a aplicar seus valores atuais aos objetos afetados (Apply), verifica o status sujo da página (IsPageDirty), invoca a ajuda (Help) e passa pressionamentos de tecla para a página (TranslateAccelerator).

Um objeto também pode oferecer suporte à navegação por propriedade, que fornece:

  1. Uma maneira (por meio de IPerPropertyBrowsing e IPropertyPage2) de especificar qual propriedade em qual página de propriedades deve receber o foco inicial quando uma folha de propriedades é exibida pela primeira vez
  2. Uma maneira (por meio de IPerPropertyBrowsing) para o objeto especificar valores predefinidos e cadeias de caracteres descritivas correspondentes que podem ser exibidas na própria interface do usuário de um cliente para propriedades.

Um objeto pode optar por oferecer suporte a (2) sem suporte a (1), como quando o objeto não tem folha de propriedades.

As interfaces IPropertyPage2 e IPerPropertyBrowsing são definidas da seguinte maneira:

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 seu suporte para tais recursos, o objeto implementa IPerPropertyBrowsing. Por meio dessa interface, o chamador pode solicitar as informações necessárias para obter a navegação, como cadeias de caracteres predefinidas (GetPredefinedStrings) e valores (GetPredefinedValue), bem como uma cadeia de caracteres de exibição para uma determinada propriedade (GetDisplayString).

Além disso, o cliente pode obter o CLSID da página de propriedades que permite ao usuário editar uma determinada propriedade identificada com um DISPID (MapPropertyToPage). Em seguida, o cliente instrui o quadro de propriedade a ativar essa página inicialmente passando o CLSID e o DISPID para OleCreatePropertyFrameIndirect. O quadro ativa essa página primeiro e passa o DISPID para a página através de IPropertyPage2::EditProperty. Em seguida, a página define o foco para o campo de edição dessa propriedade. Dessa forma, um cliente pode saltar de um nome de propriedade em sua própria interface do usuário para a página de propriedades que pode manipular essa propriedade.

Páginas de propriedades e folhas de propriedades