Utilisation des galeries

L’infrastructure du ruban Windows fournit aux développeurs un modèle robuste et cohérent pour la gestion du contenu dynamique sur une variété de contrôles basés sur la collection. En adaptant et reconfigurant l’interface utilisateur du ruban, ces contrôles dynamiques permettent à l’infrastructure de répondre à l’interaction de l’utilisateur dans l’application hôte et dans le ruban lui-même, et offrent la flexibilité nécessaire pour gérer différents environnements d’exécution.

Introduction

Cette capacité de l’infrastructure ruban à s’adapter dynamiquement aux conditions d’exécution, aux exigences de l’application et aux entrées de l’utilisateur final met en évidence les fonctionnalités d’interface utilisateur enrichies de l’infrastructure et offre aux développeurs la flexibilité nécessaire pour répondre à un large éventail de besoins des clients.

L’objectif de ce guide est de décrire les contrôles de galerie dynamiques pris en charge par l’infrastructure, d’expliquer leurs différences, de discuter du moment et de l’endroit où ils peuvent être utilisés, et de montrer comment ils peuvent être incorporés dans une application ruban.

Galeries

Les galeries sont des contrôles de zone de liste riches fonctionnellement et graphiquement. La collection d’éléments d’une galerie peut être organisée par catégories, affichées dans des dispositions flexibles basées sur des colonnes et des lignes, représentées avec des images et du texte, et selon le type de galerie, prennent en charge l’aperçu en direct.

Les galeries sont fonctionnellement distinctes des autres contrôles de ruban dynamiques pour les raisons suivantes :

  • Les galeries implémentent l’interface IUICollection qui définit les différentes méthodes de manipulation des collections d’éléments de galerie.
  • Les galeries peuvent être mises à jour au moment de l’exécution, en fonction de l’activité qui se produit directement dans le ruban, par exemple lorsqu’un utilisateur ajoute une commande à la barre d’outils Accès rapide (QAT).
  • Les galeries peuvent être mises à jour au moment de l’exécution, en fonction de l’activité qui se produit indirectement à partir de l’environnement d’exécution, par exemple lorsqu’un pilote d’imprimante prend uniquement en charge les mises en page portrait.
  • Les galeries peuvent être mises à jour au moment de l’exécution, en fonction de l’activité qui se produit indirectement dans l’application hôte, par exemple lorsqu’un utilisateur sélectionne un élément dans un document.

L’infrastructure Ribbon expose deux types de galeries : les galeries d’éléments et les galeries de commande.

Galeries d’éléments

Les galeries d’éléments contiennent une collection basée sur un index d’éléments connexes où chaque élément est représenté par une image, une chaîne ou les deux. Le contrôle est lié à un seul gestionnaire de commandes qui s’appuie sur la valeur d’index identifiée par la propriété UI_PKEY_SelectedItem .

Les galeries d’éléments prennent en charge la préversion en direct, ce qui signifie l’affichage d’un résultat de commande, en fonction de la souris ou du focus, sans validation ou appel de la commande.

Important

L’infrastructure ne prend pas en charge l’hébergement des galeries d’éléments dans le menu Application.

 

Galeries de commandes

Les galeries de commandes contiennent une collection d’éléments distincts non indexés. Chaque élément est représenté par un seul contrôle lié à un gestionnaire de commandes via un ID de commande. Comme les contrôles autonomes, chaque élément d’une galerie de commandes achemine les événements d’entrée vers un gestionnaire de commandes associé , la galerie de commandes elle-même n’écoute pas les événements.

Les galeries de commandes ne prennent pas en charge la préversion en direct.

Il existe quatre contrôles de galerie dans l’infrastructure ribbon : DropDownGallery, SplitButtonGallery, InRibbonGallery et ComboBox. Tous les éléments, à l’exception de ComboBox , peuvent être implémentés sous la forme d’une galerie d’éléments ou d’une galerie de commandes.

Un dropDownGallery est un bouton qui affiche une liste déroulante contenant une collection d’éléments ou de commandes mutuellement exclusifs.

La capture d’écran suivante illustre le contrôle Galerie déroulante du ruban dans Microsoft Paint pour Windows 7.

capture d’écran d’un contrôle de galerie de liste déroulante dans microsoft paint pour windows 7.

SplitButtonGallery

Un SplitButtonGallery est un contrôle composite qui expose un seul élément par défaut ou une commande de sa collection sur un bouton principal, et affiche d’autres éléments ou commandes dans une liste déroulante mutuellement exclusive qui s’affiche lorsque vous cliquez sur un bouton secondaire.

La capture d’écran suivante illustre le contrôle Galerie de boutons fractionnés du ruban dans Microsoft Paint pour Windows 7.

capture d’écran d’un contrôle de galerie de boutons partagés dans microsoft paint pour windows 7.

InRibbonGallery

InRibbonGallery est une galerie qui affiche une collection d’éléments ou de commandes associés dans le ruban. S’il y a trop d’éléments dans la galerie, une flèche de développement est fournie pour afficher le reste de la collection dans un volet développé.

La capture d’écran suivante illustre le contrôle Ribbon In-Ribbon Gallery dans Microsoft Paint pour Windows 7.

capture d’écran d’un contrôle de galerie dans le ruban Microsoft Paint.

ComboBox

Une zone de liste ComboBox est une zone de liste à colonne unique qui contient une collection d’éléments avec un contrôle statique ou un contrôle de modification et une flèche déroulante. La partie zone de liste du contrôle s’affiche lorsque l’utilisateur clique sur la flèche déroulante.

La capture d’écran suivante illustre un contrôle de zone de liste déroulante du ruban à partir de Windows Live Movie Maker.

capture d’écran d’un contrôle de zone de liste modifiable dans le ruban Microsoft Paint.

Étant donné que comboBox est exclusivement une galerie d’éléments, il ne prend pas en charge les éléments command. Il s’agit également du seul contrôle de galerie qui ne prend pas en charge un espace de commande. (Un espace de commande est une collection de commandes déclarées dans le balisage et répertoriées en bas d’une galerie d’éléments ou d’une galerie de commandes.)

L’exemple de code suivant montre le balisage requis pour déclarer un espace de commande à trois boutons dans un 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>

La capture d’écran suivante illustre l’espace de commande à trois boutons de l’exemple de code précédent.

capture d’écran d’un espace de commande à trois boutons dans une liste déroulantegallery.

Cette section décrit les détails d’implémentation des galeries de ruban et explique comment les incorporer dans une application ruban.

Composants de base

Cette section décrit l’ensemble de propriétés et de méthodes qui constituent l’épine dorsale du contenu dynamique dans l’infrastructure du ruban et prennent en charge l’ajout, la suppression, la mise à jour et la manipulation du contenu et de la disposition visuelle des galeries de ruban au moment de l’exécution.

IUICollection

Les galeries nécessitent un ensemble de méthodes de base pour accéder aux éléments individuels de leurs collections et les manipuler.

L’interface IEnumUnknown définit ces méthodes et l’infrastructure complète leurs fonctionnalités par des méthodes supplémentaires définies dans l’interface IUICollection . IUICollection est implémenté par l’infrastructure pour chaque déclaration de galerie dans le balisage du ruban.

Si des fonctionnalités supplémentaires ne sont pas fournies par l’interface IUICollection , un objet de collection personnalisé implémenté par l’application hôte et dérivé d’IEnumUnknown peut être remplacé par la collection d’infrastructure.

IUICollectionChangedEvent

Pour qu’une application réponde aux modifications d’une collection de galerie, elle doit implémenter l’interface IUICollectionChangedEvent . Les applications peuvent s’abonner aux notifications d’un objet IUICollection via l’écouteur d’événements IUICollectionChangedEvent::OnChanged .

Lorsque l’application remplace la collection de galerie fournie par l’infrastructure par une collection personnalisée, l’application doit implémenter l’interface IConnectionPointContainer . Si IConnectionPointContainer n’est pas implémenté, l’application ne peut pas informer l’infrastructure des modifications apportées à la collection personnalisée qui nécessitent des mises à jour dynamiques du contrôle galerie.

Dans les cas où IConnectionPointContainer n’est pas implémenté, le contrôle de galerie peut être mis à jour uniquement par invalidation via IUIFramework::InvalidateUICommand et IUICommandHandler::UpdateProperty, ou en appelant IUIFramework::SetUICommandProperty.

IUISimplePropertySet

Les applications doivent implémenter IUISimplePropertySet pour chaque élément ou commande d’une collection de galerie. Toutefois, les propriétés qui peuvent être demandées avec IUISimplePropertySet::GetValue varient.

Les éléments sont définis et liés à une galerie via la clé de propriété UI_PKEY_ItemsSource et exposent les propriétés avec un objet IUICollection .

Les propriétés valides des éléments dans les galeries d’éléments (UI_COMMANDTYPE_COLLECTION) sont décrites dans le tableau suivant.

Notes

Certaines propriétés d’élément, telles que UI_PKEY_Label, peuvent être définies dans le balisage. Pour plus d’informations, consultez la documentation de référence sur les clés de propriété .

 

Control

Propriétés

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 est une propriété de la galerie d’éléments.

 

Les propriétés d’élément valides pour les galeries de commandes (UI_COMMANDTYPE_COMMANDCOLLECTION) sont décrites dans le tableau suivant.

Control Propriétés
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

 

Les catégories sont utilisées pour organiser les éléments et les commandes dans les galeries. Les catégories sont définies et liées à une galerie via la clé de propriété UI_PKEY_Categories et exposent des propriétés avec un objet IUICollection spécifique à la catégorie.

Les catégories n’ont pas de CommandType et ne prennent pas en charge l’interaction utilisateur. Par exemple, les catégories ne peuvent pas devenir l’objet SelectedItem dans une galerie d’éléments, et elles ne sont pas liées à une commande dans une galerie de commandes. Comme d’autres propriétés d’élément de galerie, les propriétés de catégorie telles que UI_PKEY_Label et UI_PKEY_CategoryId peuvent être récupérées en appelant IUISimplePropertySet::GetValue.

Important

IUISimplePropertySet::GetValue doit retourner UI_COLLECTION_INVALIDINDEX lorsque UI_PKEY_CategoryId est demandé pour un élément qui n’a pas de catégorie associée.

 

Déclarer les contrôles dans le balisage

Les galeries, comme tous les contrôles du ruban, doivent être déclarées dans le balisage. Une galerie est identifiée dans le balisage en tant que galerie d’éléments ou galerie de commandes, et divers détails de présentation sont déclarés. Contrairement à d’autres contrôles, les galeries nécessitent que le contrôle de base uniquement, ou le conteneur de collection, soit déclaré dans le balisage. Les collections réelles sont remplies au moment de l’exécution. Lorsqu’une galerie est déclarée dans le balisage, l’attribut Type est utilisé pour spécifier si la galerie est une galerie d’éléments d’une galerie de commandes.

Un certain nombre d’attributs de disposition facultatifs sont disponibles pour chacun des contrôles décrits ici. Ces attributs fournissent des préférences de développement pour l’infrastructure à suivre qui affectent directement la façon dont un contrôle est rempli et affiché dans un ruban. Les préférences applicables dans le balisage sont liées aux modèles et comportements d’affichage et de disposition décrits dans Personnalisation d’un ruban via des définitions de taille et des stratégies de mise à l’échelle.

Si un contrôle particulier n’autorise pas les préférences de disposition directement dans le balisage, ou si les préférences de disposition ne sont pas spécifiées, l’infrastructure définit des conventions d’affichage spécifiques au contrôle en fonction de la quantité d’espace d’écran disponible.

Les exemples suivants montrent comment incorporer un ensemble de galeries dans un ruban.

Déclarations de commande

Les commandes doivent être déclarées avec un attribut CommandName utilisé pour associer un contrôle ou un ensemble de contrôles à la commande.

Un attribut CommandId utilisé pour lier une commande à un gestionnaire de commandes lors de la compilation du balisage peut également être spécifié ici. Si aucun ID n’est fourni, l’infrastructure en génère un.

<!-- 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"

Déclarations de contrôle

Cette section contient des exemples illustrant le balisage de contrôle de base requis pour les différents types de galerie. Ils montrent comment déclarer les contrôles de la galerie et les associer à une commande via l’attribut CommandName .

L’exemple suivant montre une déclaration de contrôle pour dropDownGallery où l’attribut Type est utilisé pour spécifier qu’il s’agit d’une galerie de commandes.

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

L’exemple suivant montre une déclaration de contrôle pour 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>

L’exemple suivant montre une déclaration de contrôle pour InRibbonGallery.

Notes

Étant donné que InRibbonGallery est conçu pour afficher un sous-ensemble de sa collection d’éléments dans le ruban sans activer de menu déroulant, il fournit un certain nombre d’attributs facultatifs qui régissent sa taille et sa disposition d’élément lors de l’initialisation du ruban. Ces attributs sont propres à InRibbonGallery et ne sont pas disponibles à partir des autres contrôles dynamiques.

 

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

L’exemple suivant montre une déclaration de contrôle pour comboBox.

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

Créer un gestionnaire de commandes

Pour chaque commande, l’infrastructure du ruban nécessite un gestionnaire de commandes correspondant dans l’application hôte. Les gestionnaires de commandes sont implémentés par l’application hôte du ruban et sont dérivés de l’interface IUICommandHandler .

Notes

Plusieurs commandes peuvent être liées à un seul gestionnaire de commandes.

 

Un gestionnaire de commandes remplit deux objectifs :

  • IUICommandHandler::UpdateProperty répond aux demandes de mise à jour de propriété. Les valeurs des propriétés command, telles que UI_PKEY_Enabled ou UI_PKEY_Label, sont définies par le biais d’appels à IUIFramework::SetUICommandProperty ou IUIFramework::InvalidateUICommand.
  • IUICommandHandler::Execute répond aux événements d’exécution. Cette méthode prend en charge les trois états d’exécution suivants qui sont spécifiés par le paramètre UI_EXECUTIONVERB .
    • L’état Exécuter exécute ou valide toutes les commandes auxquelles le gestionnaire est lié.
    • L’état d’aperçu affiche un aperçu des commandes auxquelles le gestionnaire est lié. Cela exécute essentiellement les commandes sans valider le résultat.
    • L’état CancelPreview annule toutes les commandes en préversion. Cela est nécessaire pour prendre en charge la traversée via un menu ou une liste, et pour afficher un aperçu séquentiel et annuler les résultats en fonction des besoins.

L’exemple suivant illustre un gestionnaire de commandes de galerie.

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

Lier le gestionnaire de commandes

Après avoir défini un gestionnaire de commandes, la commande doit être liée au gestionnaire.

L’exemple suivant montre comment lier une commande de galerie à un gestionnaire de commandes spécifique. Dans ce cas, les contrôles ComboBox et gallery sont liés à leurs gestionnaires de commandes respectifs.

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

Initialiser une collection

L’exemple suivant illustre une implémentation personnalisée d’IUISimplePropertySet pour les galeries d’éléments et de commandes.

La classe CItemProperties dans cet exemple est dérivée de IUISimplePropertySet. En plus de la méthode requise IUISimplePropertySet::GetValue, la classe CItemProperties implémente un ensemble de fonctions d’assistance pour l’initialisation et le suivi des index.

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

Gérer les événements de collection

L’exemple suivant illustre une implémentation 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;
}

Propriétés de la collection

Création d’une application ruban

Présentation des commandes et des contrôles

Instructions relatives à l’expérience utilisateur du ruban

Processus de conception du ruban

Exemple de galerie