Compartilhar via


Trabalhando com galerias

A estrutura da Faixa de Opções do Windows fornece aos desenvolvedores um modelo robusto e consistente para gerenciar conteúdo dinâmico em uma variedade de controles baseados em coleção. Ao adaptar e reconfigurar a interface do usuário da Faixa de Opções, esses controles dinâmicos permitem que a estrutura responda à interação do usuário no aplicativo host e na própria Faixa de Opções e forneça a flexibilidade para lidar com vários ambientes de tempo de execução.

Introdução

Essa capacidade da estrutura da Faixa de Opções de se adaptar dinamicamente a condições de tempo de execução, requisitos de aplicativo e entrada do usuário final realça os recursos avançados de interface do usuário da estrutura e fornece aos desenvolvedores a flexibilidade para atender a uma ampla gama de necessidades do cliente.

O foco deste guia é descrever os controles dinâmicos da galeria compatíveis com a estrutura, explicar suas diferenças, discutir quando e onde eles podem ser melhor usados e demonstrar como eles podem ser incorporados em um aplicativo da Faixa de Opções.

Galerias

As galerias são controles de caixa de listagem funcional e graficamente avançados. A coleção de itens de uma galeria pode ser organizada por categorias, exibidas em layouts flexíveis baseados em colunas e linhas, representadas com imagens e texto e, dependendo do tipo de galeria, dão suporte à visualização ao vivo.

As galerias são funcionalmente distintas de outros controles dinâmicos da Faixa de Opções pelos seguintes motivos:

  • As galerias implementam a interface IUICollection que define os vários métodos para manipular coleções de itens da galeria.
  • As galerias podem ser atualizadas em tempo de execução, com base na atividade que ocorre diretamente na Faixa de Opções, como quando um usuário adiciona um Comando à QAT (Barra de Ferramentas de Acesso Rápido).
  • As galerias podem ser atualizadas em tempo de execução, com base na atividade que ocorre indiretamente do ambiente de tempo de execução, como quando um driver de impressora dá suporte apenas a layouts de página retrato.
  • As galerias podem ser atualizadas em tempo de execução, com base na atividade que ocorre indiretamente no aplicativo host, como quando um usuário seleciona um item em um documento.

A estrutura da Faixa de Opções expõe dois tipos de galerias: galerias de itens e galerias de comandos.

Galerias de Itens

As galerias de itens contêm uma coleção baseada em índice de itens relacionados em que cada item é representado por uma imagem, uma cadeia de caracteres ou ambos. O controle está associado a um único manipulador command que depende do valor de índice identificado pela propriedade UI_PKEY_SelectedItem .

As galerias de itens dão suporte à visualização ao vivo, o que significa exibir um resultado de Comando, com base em mouseover ou foco, sem se comprometer ou realmente invocar o Comando.

Importante

A estrutura não dá suporte à hospedagem de galerias de itens no Menu do Aplicativo.

 

Galerias de comandos

As galerias de comandos contêm uma coleção de itens distintos e não indexados. Cada item é representado por um único controle associado a um manipulador de comando por meio de uma ID de comando. Assim como os controles autônomos, cada item em uma galeria de comandos roteia eventos de entrada para um manipulador de comando associado— a própria galeria de comandos não escuta eventos.

As galerias de comandos não dão suporte à visualização ao vivo.

Há quatro controles de galeria na estrutura da Faixa de Opções: DropDownGallery, SplitButtonGallery, InRibbonGallery e ComboBox. Todos, exceto o ComboBox , podem ser implementados como uma galeria de itens ou uma galeria de comandos.

Um DropDownGallery é um botão que exibe uma lista suspensa que contém uma coleção de itens mutuamente exclusivos ou Comandos.

A captura de tela a seguir ilustra o controle Galeria Suspensa da Faixa de Opções no Microsoft Paint para Windows 7.

captura de tela de um controle de galeria suspensa no Microsoft Paint para Windows 7.

SplitButtonGallery

Um SplitButtonGallery é um controle composto que expõe um único item padrão ou Command de sua coleção em um botão primário e exibe outros itens ou comandos em uma lista suspensa mutuamente exclusiva que é exibida quando um botão secundário é clicado.

A captura de tela a seguir ilustra o controle Galeria de Botões de Divisão da Faixa de Opções no Microsoft Paint para Windows 7.

captura de tela de um controle de galeria de botões divididos no Microsoft Paint para Windows 7.

InRibbonGallery

Uma InRibbonGallery é uma galeria que exibe uma coleção de itens relacionados ou Comandos na Faixa de Opções. Se houver muitos itens na galeria, uma seta de expansão será fornecida para exibir o restante da coleção em um painel expandido.

A captura de tela a seguir ilustra o controle Da Galeria na Faixa de Opções da Faixa de Opções no Microsoft Paint para Windows 7.

captura de tela de um controle de galeria na faixa de opções na faixa de opções do Microsoft Paint.

ComboBox

Um ComboBox é uma caixa de listagem de coluna única que contém uma coleção de itens com um controle estático ou controle de edição e seta suspensa. A parte da caixa de listagem do controle é exibida quando o usuário clica na seta suspensa.

A captura de tela a seguir ilustra um controle Caixa de Combinação da Faixa de Opções de Windows Live Movie Maker.

captura de tela de um controle de caixa de combinação na faixa de opções do Microsoft Paint.

Como o ComboBox é exclusivamente uma galeria de itens, ele não dá suporte a itens de Comando. Ele também é o único controle da galeria que não dá suporte a um Espaço de Comando. (Um Espaço de Comando é uma coleção de Comandos declarados na marcação e listados na parte inferior de uma galeria de itens ou galeria de comandos.)

O exemplo de código a seguir mostra a marcação necessária para declarar um Espaço de Comando de três botões em uma DropDownGallery.

<DropDownGallery 
  CommandName="cmdSizeAndColor" 
  TextPosition="Hide" 
  Type="Commands"
  ItemHeight="32"
  ItemWidth="32">
  <DropDownGallery.MenuLayout>
    <FlowMenuLayout Rows="2" Columns="3" Gripper="None"/>
  </DropDownGallery.MenuLayout>
  <Button CommandName="cmdCommandSpace1"/>
  <Button CommandName="cmdCommandSpace2"/>
  <Button CommandName="cmdCommandSpace3"/>
</DropDownGallery>

A captura de tela a seguir ilustra o Espaço de Comando de três botões do exemplo de código anterior.

captura de tela de um espaço de comando de três botões em uma lista suspensa.

Esta seção discute os detalhes de implementação das galerias da Faixa de Opções e explica como incorporá-las em um aplicativo da Faixa de Opções.

Os componentes básicos

Esta seção descreve o conjunto de propriedades e métodos que formam o backbone do conteúdo dinâmico na estrutura da Faixa de Opções e dão suporte à adição, exclusão, atualização e manipulação do conteúdo e layout visual das galerias da Faixa de Opções em tempo de execução.

IUICollection

As galerias exigem um conjunto básico de métodos para acessar e manipular os itens individuais em suas coleções.

A interface IEnumUnknown define esses métodos e a estrutura complementa sua funcionalidade com métodos adicionais definidos na interface IUICollection . IUICollection é implementado pela estrutura para cada declaração de galeria na marcação da Faixa de Opções.

Se forem necessárias funcionalidades adicionais que não são fornecidas pela interface IUICollection , um objeto de coleção personalizado implementado pelo aplicativo host e derivado de IEnumUnknown poderá ser substituído pela coleção de estruturas.

IUICollectionChangedEvent

Para que um aplicativo responda a alterações em uma coleção da galeria, ele deve implementar a interface IUICollectionChangedEvent . Os aplicativos podem assinar notificações de um objeto IUICollection por meio do ouvinte de eventos IUICollectionChangedEvent::OnChanged .

Quando o aplicativo substitui a coleção de galeria fornecida pela estrutura por uma coleção personalizada, o aplicativo deve implementar a interface IConnectionPointContainer . Se IConnectionPointContainer não for implementado, o aplicativo não poderá notificar a estrutura de alterações na coleção personalizada que exigem atualizações dinâmicas para o controle da galeria.

Nos casos em que IConnectionPointContainer não é implementado, o controle da galeria só pode ser atualizado pela invalidação por meio de IUIFramework::InvalidateUICommand e IUICommandHandler::UpdateProperty ou chamando IUIFramework::SetUICommandProperty.

IUISimplePropertySet

Os aplicativos devem implementar IUISimplePropertySet para cada item ou Command em uma coleção da galeria. No entanto, as propriedades que podem ser solicitadas com IUISimplePropertySet::GetValue variam.

Os itens são definidos e associados a uma galeria por meio da chave de propriedade UI_PKEY_ItemsSource e expõem propriedades com um objeto IUICollection .

As propriedades válidas para itens em galerias de itens (UI_COMMANDTYPE_COLLECTION) são descritas na tabela a seguir.

Observação

Algumas propriedades de item, como UI_PKEY_Label, podem ser definidas na marcação. Para obter mais detalhes, consulte a documentação de referência de Chaves de Propriedade .

 

Control

Propriedades

ComboBox

UI_PKEY_Label, UI_PKEY_CategoryId

DropDownGallery

UI_PKEY_Label, UI_PKEY_ItemImage , UI_PKEY_CategoryId

InRibbonGallery

UI_PKEY_Label, UI_PKEY_ItemImage , UI_PKEY_CategoryId

SplitButtonGallery

UI_PKEY_Label, UI_PKEY_ItemImage, UI_PKEY_CategoryId

UI_PKEY_SelectedItem é uma propriedade da galeria de itens.

 

As propriedades de item válidas para galerias de comandos (UI_COMMANDTYPE_COMMANDCOLLECTION) são descritas na tabela a seguir.

Control Propriedades
DropDownGallery UI_PKEY_CommandId, UI_PKEY_CommandType , UI_PKEY_CategoryId
InRibbonGallery UI_PKEY_CommandId, UI_PKEY_CommandType , UI_PKEY_CategoryId
SplitButtonGallery UI_PKEY_CommandId, UI_PKEY_CommandType, UI_PKEY_CategoryId

 

As categorias são usadas para organizar itens e comandos em galerias. As categorias são definidas e associadas a uma galeria por meio da chave de propriedade UI_PKEY_Categories e expõem propriedades com um objeto IUICollection específico da categoria.

As categorias não têm um CommandType e não dão suporte à interação do usuário. Por exemplo, as categorias não podem se tornar SelectedItem em uma galeria de itens e não estão associadas a um Command em uma galeria de comandos. Assim como outras propriedades de item da galeria, propriedades de categoria como UI_PKEY_Label e UI_PKEY_CategoryId podem ser recuperadas chamando IUISimplePropertySet::GetValue.

Importante

IUISimplePropertySet::GetValue deve retornar UI_COLLECTION_INVALIDINDEX quando UI_PKEY_CategoryId é solicitado para um item que não tem uma categoria associada.

 

Declarar os controles na marcação

Galerias, como todos os controles da Faixa de Opções, devem ser declaradas na marcação. Uma galeria é identificada na marcação como uma galeria de itens ou galeria de comandos, e vários detalhes da apresentação são declarados. Ao contrário de outros controles, as galerias exigem que apenas o controle base, ou contêiner de coleção, seja declarado na marcação. As coleções reais são preenchidas em tempo de execução. Quando uma galeria é declarada na marcação, o atributo Type é usado para especificar se a galeria é uma galeria de itens de uma galeria de comandos.

Há vários atributos de layout opcionais disponíveis para cada um dos controles discutidos aqui. Esses atributos fornecem preferências de desenvolvedor para a estrutura seguir que afetam diretamente como um controle é preenchido e exibido em uma faixa de opções. As preferências aplicáveis na marcação estão relacionadas aos modelos e comportamentos de exibição e layout discutidos em Personalizando uma faixa de opções por meio de definições de tamanho e políticas de dimensionamento.

Se um controle específico não permitir preferências de layout diretamente na marcação ou as preferências de layout não forem especificadas, a estrutura definirá convenções de exibição específicas do controle com base na quantidade de espaço de tela disponível.

Os exemplos a seguir demonstram como incorporar um conjunto de galerias em uma Faixa de Opções.

Declarações de comando

Os comandos devem ser declarados com um atributo CommandName que é usado para associar um controle, ou conjunto de controles, ao Comando.

Um atributo CommandId usado para associar um Command a um manipulador command quando a marcação é compilada também pode ser especificado aqui. Se nenhuma ID for fornecida, uma será gerada pela estrutura.

<!-- ComboBox -->
<Command Name="cmdComboBoxGroup"
         Symbol="cmdComboBoxGroup"
         Comment="ComboBox Group"
         LabelTitle="ComboBox"/>
<Command Name="cmdComboBox"
         Symbol="cmdComboBox"
         Comment="ComboBox"
         LabelTitle="ComboBox"/>

<!-- DropDownGallery -->
<Command Name="cmdDropDownGalleryGroup"
         Symbol="cmdDropDownGalleryGroup"
         Comment="DropDownGallery Group"
         LabelTitle="DropDownGallery"/>
<Command Name="cmdDropDownGallery"
         Symbol="cmdDropDownGallery"
         Comment="DropDownGallery"
         LabelTitle="DropDownGallery"/>

<!-- InRibbonGallery -->
<Command Name="cmdInRibbonGalleryGroup"
         Symbol="cmdInRibbonGalleryGroup"
         Comment="InRibbonGallery Group"
         LabelTitle="InRibbonGallery"/>
<Command Name="cmdInRibbonGallery"
         Symbol="cmdInRibbonGallery"
         Comment="InRibbonGallery"
         LabelTitle="InRibbonGallery"

<!-- SplitButtonGallery -->
<Command Name="cmdSplitButtonGalleryGroup"
         Symbol="cmdSplitButtonGalleryGroup"
         Comment="SplitButtonGallery Group"
         LabelTitle="SplitButtonGallery"/>
<Command Name="cmdSplitButtonGallery"
         Symbol="cmdSplitButtonGallery"
         Comment="SplitButtonGallery"
         LabelTitle="SplitButtonGallery"

Declarações de controle

Esta seção contém exemplos que demonstram a marcação de controle básica necessária para os vários tipos de galeria. Eles mostram como declarar os controles da galeria e associá-los a um Command por meio do atributo CommandName .

O exemplo a seguir mostra uma declaração de controle para DropDownGallery em que o atributo Type é usado para especificar que esta é uma galeria de comandos.

<!-- DropDownGallery -->
<Group CommandName="cmdDropDownGalleryGroup">
  <DropDownGallery CommandName="cmdDropDownGallery"
                   TextPosition="Hide"
                   Type="Commands"
                   ItemHeight="32"
                   ItemWidth="32">
    <DropDownGallery.MenuLayout>
      <FlowMenuLayout Rows="2"
                      Columns="3"
                      Gripper="None"/>
    </DropDownGallery.MenuLayout>
    <DropDownGallery.MenuGroups>
      <MenuGroup>
        <Button CommandName="cmdButton1"></Button>
        <Button CommandName="cmdButton2"></Button>
       </MenuGroup>
       <MenuGroup>
        <Button CommandName="cmdButton3"></Button>
      </MenuGroup>
    </DropDownGallery.MenuGroups>
  </DropDownGallery>
</Group>

O exemplo a seguir mostra uma declaração de controle para SplitButtonGallery.

<!-- SplitButtonGallery -->
<Group CommandName="cmdSplitButtonGalleryGroup">
  <SplitButtonGallery CommandName="cmdSplitButtonGallery">
    <SplitButtonGallery.MenuLayout>
      <FlowMenuLayout Rows="2"
                      Columns="3"
                      Gripper="None"/>
    </SplitButtonGallery.MenuLayout>
    <SplitButtonGallery.MenuGroups>
      <MenuGroup>
        <Button CommandName="cmdButton1"></Button>
        <Button CommandName="cmdButton2"></Button>
      </MenuGroup>
      <MenuGroup>
        <Button CommandName="cmdButton3"></Button>
      </MenuGroup>
    </SplitButtonGallery.MenuGroups>
  </SplitButtonGallery>
</Group>

O exemplo a seguir mostra uma declaração de controle para InRibbonGallery.

Observação

Como InRibbonGallery foi projetado para exibir um subconjunto de sua coleção de itens na Faixa de Opções sem ativar um menu suspenso, ele fornece vários atributos opcionais que regem seu tamanho e layout de item na inicialização da Faixa de Opções. Esses atributos são exclusivos do InRibbonGallery e não estão disponíveis nos outros controles dinâmicos.

 

<!-- InRibbonGallery -->
<Group CommandName="cmdInRibbonGalleryGroup" SizeDefinition="OneInRibbonGallery">
  <InRibbonGallery CommandName="cmdInRibbonGallery"
                   MaxColumns="10"
                   MaxColumnsMedium="5"
                   MinColumnsLarge="5"
                   MinColumnsMedium="3"
                   Type="Items">
    <InRibbonGallery.MenuLayout>
      <VerticalMenuLayout Rows="2"
                          Gripper="Vertical"/>
    </InRibbonGallery.MenuLayout>
    <InRibbonGallery.MenuGroups>
      <MenuGroup>
        <Button CommandName="cmdButton1"></Button>
        <Button CommandName="cmdButton2"></Button>
      </MenuGroup>
      <MenuGroup>
        <Button CommandName="cmdButton3"></Button>
      </MenuGroup>
    </InRibbonGallery.MenuGroups>            
  </InRibbonGallery>
</Group>

O exemplo a seguir mostra uma declaração de controle para o ComboBox.

<!-- ComboBox -->
<Group CommandName="cmdComboBoxGroup">
  <ComboBox CommandName="cmdComboBox">              
  </ComboBox>
</Group>

Criar um manipulador de comandos

Para cada Comando, a estrutura da Faixa de Opções requer um manipulador de comando correspondente no aplicativo host. Os manipuladores de comando são implementados pelo aplicativo host da Faixa de Opções e são derivados da interface IUICommandHandler .

Observação

Vários comandos podem ser associados a um único manipulador de comando.

 

Um manipulador de comandos serve a duas finalidades:

  • IUICommandHandler::UpdateProperty responde a solicitações de atualização de propriedade. Os valores das propriedades Command, como UI_PKEY_Enabled ou UI_PKEY_Label, são definidos por meio de chamadas para IUIFramework::SetUICommandProperty ou IUIFramework::InvalidateUICommand.
  • IUICommandHandler::Execute responde a eventos de execução. Esse método dá suporte aos três estados de execução a seguir especificados pelo parâmetro UI_EXECUTIONVERB .
    • O estado Executar executa ou confirma em todos os comandos aos quais o manipulador está associado.
    • O estado Visualizar visualiza todos os comandos aos quais o manipulador está associado. Essencialmente, isso executa os comandos sem se comprometer com o resultado.
    • O estado CancelPreview cancela todos os Comandos visualizados. Isso é necessário para dar suporte à passagem por meio de um menu ou lista e visualizar sequencialmente e desfazer os resultados conforme necessário.

O exemplo a seguir demonstra um manipulador de comandos da galeria.

/*
 * GALLERY COMMAND HANDLER IMPLEMENTATION
 */
class CGalleryCommandHandler
      : public CComObjectRootEx<CComMultiThreadModel>
      , public IUICommandHandler
{
public:
  BEGIN_COM_MAP(CGalleryCommandHandler)
    COM_INTERFACE_ENTRY(IUICommandHandler)
  END_COM_MAP()

  // Gallery command handler's Execute method
  STDMETHODIMP Execute(UINT nCmdID,
                       UI_EXECUTIONVERB verb, 
                       const PROPERTYKEY* key,
                       const PROPVARIANT* ppropvarValue,
                       IUISimplePropertySet* pCommandExecutionProperties)
  {
    HRESULT hr = S_OK;
        
    // Switch on manner of execution (Execute/Preview/CancelPreview)
    switch (verb)
    {
      case UI_EXECUTIONVERB_EXECUTE:
        if(nCmdID == cmdTextSizeGallery || 
           nCmdID == cmdTextSizeGallery2 || 
           nCmdID == cmdTextSizeGallery3)
        {
          if (pCommandExecutionProperties != NULL)
          {
            CItemProperties *pItem = 
              static_cast<CItemProperties *>(pCommandExecutionProperties);
            g_prevSelection = g_index = pItem->GetIndex();
            UpdateGallerySelectedItems();
            ::InvalidateRect(g_hWindowFrame, NULL, TRUE);
          }
          else
          {
            g_prevSelection = g_index = 0;
            UpdateGallerySelectedItems();
            ::InvalidateRect(g_hWindowFrame, NULL, TRUE);
          }
        }           
        break;
      case UI_EXECUTIONVERB_PREVIEW:
        CItemProperties *pItem = 
          static_cast<CItemProperties *>(pCommandExecutionProperties);
        g_index = pItem->GetIndex();
        ::InvalidateRect(g_hWindowFrame, NULL, TRUE);
        break;
      case UI_EXECUTIONVERB_CANCELPREVIEW:
        g_index = g_prevSelection;
        ::InvalidateRect(g_hWindowFrame, NULL, TRUE);
        break;
    }   
    return hr;
  }

  // Gallery command handler's UpdateProperty method
  STDMETHODIMP UpdateProperty(UINT nCmdID,
                              REFPROPERTYKEY key,
                              const PROPVARIANT* ppropvarCurrentValue,
                              PROPVARIANT* ppropvarNewValue)
  {
    UNREFERENCED_PARAMETER(ppropvarCurrentValue);

    HRESULT hr = E_NOTIMPL;         

    if (key == UI_PKEY_ItemsSource) // Gallery items requested
    {
      if (nCmdID == cmdTextSizeGallery || 
          nCmdID == cmdTextSizeGallery2 || 
          nCmdID == cmdTextSizeGallery3)
      {
        CComQIPtr<IUICollection> spCollection(ppropvarCurrentValue->punkVal);

        int count = _countof(g_labels);

        for (int i = 0; i < count; i++)
        {
          CComObject<CItemProperties> * pItem;
          CComObject<CItemProperties>::CreateInstance(&pItem);
                    
          pItem->AddRef();
          pItem->Initialize(i);

          spCollection->Add(pItem);
        }
        return S_OK;
      }
      if (nCmdID == cmdCommandGallery1)
      {
        CComQIPtr<IUICollection> spCollection(ppropvarCurrentValue->punkVal);

        int count = 12;
        int commands[] = {cmdButton1, 
                          cmdButton2, 
                          cmdBoolean1, 
                          cmdBoolean2, 
                          cmdButton1, 
                          cmdButton2, 
                          cmdBoolean1, 
                          cmdBoolean2, 
                          cmdButton1, 
                          cmdButton2, 
                          cmdBoolean1, 
                          cmdBoolean2};

        for (int i = 0; i < count; i++)
        {
          CComObject<CItemProperties> * pItem;
          CComObject<CItemProperties>::CreateInstance(&pItem);
                    
          pItem->AddRef();
          pItem->InitializeAsCommand(commands[i]);

          spCollection->Add(pItem);
        }
        return S_OK;
      }
    }        
    else if (key == UI_PKEY_SelectedItem) // Selected item requested
    {           
      hr = UIInitPropertyFromUInt32(UI_PKEY_SelectedItem, g_index, ppropvarNewValue);           
    }
    return hr;
  }
};

Associar o manipulador de comandos

Depois de definir um manipulador de comando, o Comando deve ser associado ao manipulador.

O exemplo a seguir demonstra como associar um Comando da galeria a um manipulador de comando específico. Nesse caso, os controles ComboBox e gallery estão associados aos respectivos manipuladores de comando.

// Called for each Command in markup. 
// Application will return a Command handler for each Command.
STDMETHOD(OnCreateUICommand)(UINT32 nCmdID,
                             UI_COMMANDTYPE typeID,
                             IUICommandHandler** ppCommandHandler) 
{   
  // CommandType for ComboBox and galleries
  if (typeID == UI_COMMANDTYPE_COLLECTION || typeID == UI_COMMANDTYPE_COMMANDCOLLECTION) 
  {
    switch (nCmdID)
    {
      case cmdComboBox:
        CComObject<CComboBoxCommandHandler> * pComboBoxCommandHandler;
        CComObject<CComboBoxCommandHandler>::CreateInstance(&pComboBoxCommandHandler);
        return pComboBoxCommandHandler->QueryInterface(IID_PPV_ARGS(ppCommandHandler));
      default:
        CComObject<CGalleryCommandHandler> * pGalleryCommandHandler;
        CComObject<CGalleryCommandHandler>::CreateInstance(&pGalleryCommandHandler);
        return pGalleryCommandHandler->QueryInterface(IID_PPV_ARGS(ppCommandHandler));
    }
    return E_NOTIMPL; // Command is not implemented, so do not pass a handler back.
  }
}

Inicializar uma coleção

O exemplo a seguir demonstra uma implementação personalizada de IUISimplePropertySet para galerias de itens e comandos.

A classe CItemProperties neste exemplo é derivada de IUISimplePropertySet. Além do método necessário IUISimplePropertySet::GetValue, a classe CItemProperties implementa um conjunto de funções auxiliares para inicialização e acompanhamento de índice.

//
//  PURPOSE:    Implementation of IUISimplePropertySet.
//
//  COMMENTS:
//              Three gallery-specific helper functions included. 
//

class CItemProperties
  : public CComObjectRootEx<CComMultiThreadModel>
  , public IUISimplePropertySet
{
  public:

  // COM map for QueryInterface of IUISimplePropertySet.
  BEGIN_COM_MAP(CItemProperties)
    COM_INTERFACE_ENTRY(IUISimplePropertySet)
  END_COM_MAP()

  // Required method that enables property key values to be 
  // retrieved on gallery collection items.
  STDMETHOD(GetValue)(REFPROPERTYKEY key, PROPVARIANT *ppropvar)
  {
    HRESULT hr;

    // No category is associated with this item.
    if (key == UI_PKEY_CategoryId)
    {
      return UIInitiPropertyFromUInt32(UI_PKEY_CategoryId, 
                                       UI_COLLECTION_INVALIDINDEX, 
                                       pprovar);
    }

    // A Command gallery.
    // _isCommandGallery is set on initialization.
    if (_isCommandGallery)
    {           
      if(key == UI_PKEY_CommandId && _isCommandGallery)
      {
        // Return a pointer to the CommandId of the item.
        return InitPropVariantFromUInt32(_cmdID, ppropvar);
      }         
    }
    // An item gallery.
    else
    {
      if (key == UI_PKEY_Label)
      {
        // Return a pointer to the item label string.
        return UIInitPropertyFromString(UI_PKEY_Label, ppropvar);
      }
      else if(key == UI_PKEY_ItemImage)
      {
        // Return a pointer to the item image.
        return UIInitPropertyFromImage(UI_PKEY_ItemImage, ppropvar);
      }         
    }
    return E_NOTIMPL;
  }

  // Initialize an item in an item gallery collection at the specified index.
  void Initialize(int index)
  {
    _index = index;
    _cmdID = 0;
    _isCommandGallery = false;
  }

  // Initialize a Command in a Command gallery.
  void InitializeAsCommand(__in UINT cmdID)
  {
    _index = 0;
    _cmdID = cmdID;
    _isCommandGallery = true;
  }

  // Gets the index of the selected item in an item gallery.
  int GetIndex()
  {
    return _index;
  }

private:
  int _index;
  int _cmdID;
  bool _isCommandGallery;   
};

Manipular eventos de coleção

O exemplo a seguir demonstra uma implementação IUICollectionChangedEvent.

class CQATChangedEvent
  : public CComObjectRootEx<CComSingleThreadModel>
  , public IUICollectionChangedEvent
{
  public:

  HRESULT FinalConstruct()
  {
    _pSite = NULL;
    return S_OK;
  }

  void Initialize(__in CQATSite* pSite)
  {
    if (pSite != NULL)
    {
      _pSite = pSite;
    }
  }

  void Uninitialize()
  {
    _pSite = NULL;
  }

  BEGIN_COM_MAP(CQATChangedEvent)
    COM_INTERFACE_ENTRY(IUICollectionChangedEvent)
  END_COM_MAP()

  // IUICollectionChangedEvent interface
  STDMETHOD(OnChanged)(UI_COLLECTIONCHANGE action, 
                       UINT32 oldIndex, 
                       IUnknown *pOldItem, 
                       UINT32 newIndex, 
                       IUnknown *pNewItem)
  {
    if (_pSite)
    {
      _pSite->OnCollectionChanged(action, oldIndex, pOldItem, newIndex, pNewItem);
    }
    return S_OK;
  }

  protected:
  virtual ~CQATChangedEvent(){}

  private:
  CQATSite* _pSite; // Weak ref to avoid circular refcounts
};

HRESULT CQATHandler::EnsureCollectionEventListener(__in IUICollection* pUICollection)
{
  // Check if listener already exists.
  if (_spQATChangedEvent)
  {
    return S_OK;
  }

  HRESULT hr = E_FAIL;

  // Create an IUICollectionChangedEvent listener.
  hr = CreateInstanceWithRefCountOne(&_spQATChangedEvent);
    
  if (SUCCEEDED(hr))
  {
    CComPtr<IUnknown> spUnknown;
    _spQATChangedEvent->QueryInterface(IID_PPV_ARGS(&spUnknown));

    // Create a connection between the collection connection point and the sink.
    AtlAdvise(pUICollection, spUnknown, __uuidof(IUICollectionChangedEvent), &_dwCookie);
    _spQATChangedEvent->Initialize(this);
  }
  return hr;
}

HRESULT CQATHandler::OnCollectionChanged(
             UI_COLLECTIONCHANGE action, 
          UINT32 oldIndex, 
             IUnknown *pOldItem, 
          UINT32 newIndex, 
          IUnknown *pNewItem)
{
    UNREFERENCED_PARAMETER(oldIndex);
    UNREFERENCED_PARAMETER(newIndex);

    switch (action)
    {
      case UI_COLLECTIONCHANGE_INSERT:
      {
        CComQIPtr<IUISimplePropertySet> spProperties(pNewItem);
                
        PROPVARIANT var;
        if (SUCCEEDED(spProperties->GetValue(UI_PKEY_CommandId, &var)))
        {
          UINT tcid;
          if (SUCCEEDED(UIPropertyToUInt32(UI_PKEY_CommandId, var, &tcid)))
          {
            FireETWEvent(tcid, L"Added to QAT");
            PropVariantClear(&var);
          }
        }
      }
      break;
      case UI_COLLECTIONCHANGE_REMOVE:
      {
        CComQIPtr<IUISimplePropertySet> spProperties(pOldItem);
                
        PROPVARIANT var;
        if (SUCCEEDED(spProperties->GetValue(UI_PKEY_CommandId, &var)))
        {
          UINT tcid;
          if (SUCCEEDED(UIPropertyToUInt32(UI_PKEY_CommandId, var, &tcid)))
          {
            FireETWEvent(tcid, L"Removed from QAT");
            PropVariantClear(&var);
          }
        }
      }
      break;
    default:
  }
  return S_OK;
}

Propriedades da coleção

Criando um aplicativo de faixa de opções

Noções básicas sobre comandos e controles

Diretrizes de experiência do usuário da faixa de opções

Processo de Design da Faixa de Opções

Exemplo de Galeria