Share via


Uso delle gallerie

Il framework della barra multifunzione di Windows offre agli sviluppatori un modello affidabile e coerente per la gestione del contenuto dinamico in un'ampia gamma di controlli basati sulla raccolta. Adattando e riconfigurando l'interfaccia utente della barra multifunzione, questi controlli dinamici consentono al framework di rispondere all'interazione utente sia nell'applicazione host che nella barra multifunzione stessa e offrono la flessibilità per gestire vari ambienti di runtime.

Introduzione

Questa capacità del framework della barra multifunzione di adattarsi dinamicamente a condizioni di runtime, requisiti dell'applicazione e input utente finale evidenzia le funzionalità avanzate dell'interfaccia utente del framework e offre agli sviluppatori la flessibilità di soddisfare un'ampia gamma di esigenze dei clienti.

L'obiettivo di questa guida è descrivere i controlli della raccolta dinamica supportati dal framework, spiegare le differenze, discutere quando e dove possono essere usati al meglio e dimostrare come possono essere incorporati in un'applicazione della barra multifunzione.

Raccolte

Le raccolte sono controlli casella di riepilogo funzionalmente e graficamente avanzati. L'insieme di elementi di una raccolta può essere organizzato per categorie, visualizzate in layout flessibili basati su colonne e righe, rappresentate con immagini e testo e a seconda del tipo di raccolta, supportano l'anteprima in tempo reale.

Le raccolte sono distinte funzionalmente da altri controlli della barra multifunzione dinamici per i motivi seguenti:

  • Le raccolte implementano l'interfaccia IUICollection che definisce i vari metodi per modificare le raccolte di elementi della raccolta.
  • Le raccolte possono essere aggiornate in fase di esecuzione, in base all'attività che si verifica direttamente nella barra multifunzione, ad esempio quando un utente aggiunge un comando alla barra degli strumenti di accesso rapido (QAT).
  • Le raccolte possono essere aggiornate in fase di esecuzione, in base all'attività che si verifica indirettamente dall'ambiente di runtime, ad esempio quando un driver della stampante supporta solo layout di pagina verticale.
  • Le raccolte possono essere aggiornate in fase di esecuzione, in base all'attività che si verifica indirettamente nell'applicazione host, ad esempio quando un utente seleziona un elemento in un documento.

Il framework della barra multifunzione espone due tipi di raccolte: raccolte di elementi e raccolte comandi.

Raccolte di elementi

Le raccolte di elementi contengono una raccolta basata su indice di elementi correlati in cui ogni elemento è rappresentato da un'immagine, una stringa o entrambe. Il controllo è associato a un singolo gestore comandi che si basa sul valore di indice identificato dalla proprietà UI_PKEY_SelectedItem .

Le raccolte di elementi supportano l'anteprima live, che significa visualizzare un risultato del comando, in base al mouseover o allo stato attivo, senza eseguire il commit o richiamando effettivamente il comando.

Importante

Il framework non supporta l'hosting delle raccolte di elementi nel menu applicazione.

 

Raccolte comandi

Le raccolte di comandi contengono una raccolta di elementi distinti e non indicizzati. Ogni elemento è rappresentato da un singolo controllo associato a un gestore comandi tramite un ID comando. Come i controlli autonomi, ogni elemento di una raccolta comandi indirizza gli eventi di input a un gestore comandi associato, la raccolta comandi stessa non è in ascolto degli eventi.

Le raccolte di comandi non supportano l'anteprima live.

Nel framework della barra multifunzione sono disponibili quattro controlli della raccolta: DropDownGallery, SplitButtonGallery, InRibbonGallery e ComboBox. Tutte le eccezioni di ComboBox possono essere implementate come raccolta di elementi o una raccolta comandi.

Un elenco a discesa DropDownGallery è un pulsante che visualizza un elenco a discesa contenente una raccolta di elementi o comandi reciprocamente esclusivi.

La schermata seguente illustra il controllo Raccolta a discesa della barra multifunzione in Microsoft Paint per Windows 7.

schermata di un controllo della raccolta a discesa in microsoft paint per Windows 7.

SplitButtonGallery

Un controllo SplitButtonGallery è un controllo composito che espone un singolo elemento predefinito o comando dalla raccolta in un pulsante primario e visualizza altri elementi o comandi in un elenco a discesa a discesa reciprocamente esclusivo visualizzato quando viene fatto clic su un pulsante secondario.

La schermata seguente illustra il controllo Split Button Gallery della barra multifunzione in Microsoft Paint per Windows 7.

schermata di un controllo della raccolta di pulsanti di divisione in microsoft paint per windows 7.

InRibbonGallery

InRibbonGallery è una raccolta che visualizza una raccolta di elementi o comandi correlati nella barra multifunzione. Se nella raccolta sono presenti troppi elementi, viene fornita una freccia di espansione per visualizzare il resto della raccolta in un riquadro espanso.

La schermata seguente illustra il controllo Raccolta barra multifunzione in Microsoft Paint per Windows 7.

schermata di un controllo della raccolta della barra multifunzione nella barra multifunzione microsoft.

ComboBox

Un controllo ComboBox è una casella di riepilogo a colonna singola che contiene una raccolta di elementi con un controllo statico o una freccia a discesa. La parte della casella di riepilogo del controllo viene visualizzata quando l'utente fa clic sulla freccia a discesa.

La schermata seguente illustra un controllo Casella combinata della barra multifunzione da Windows Live Movie Maker.

schermata di un controllo combobox nella barra multifunzione microsoft paint.

Poiché ComboBox è esclusivamente una raccolta di elementi, non supporta gli elementi di comando. È anche l'unico controllo della raccolta che non supporta uno spazio dei comandi. Uno spazio dei comandi è una raccolta di comandi dichiarati nel markup e elencati nella parte inferiore di una raccolta di elementi o della raccolta comandi.

Nell'esempio di codice seguente viene illustrato il markup necessario per dichiarare uno spazio di comando a tre pulsanti in un'istanza di 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 schermata seguente illustra lo spazio dei comandi a tre pulsanti dell'esempio di codice precedente.

screenshot di uno spazio di comando a tre pulsanti in un'elenco a discesa.

Questa sezione illustra i dettagli dell'implementazione delle raccolte della barra multifunzione e illustra come incorporarli in un'applicazione della barra multifunzione.

Componenti di base

Questa sezione descrive il set di proprietà e metodi che costituiscono il backbone del contenuto dinamico nel framework della barra multifunzione e supportano l'aggiunta, l'eliminazione, l'aggiornamento e la modifica del contenuto e del layout visivo delle raccolte della barra multifunzione in fase di esecuzione.

IUICollection

Le raccolte richiedono un set di metodi di base per accedere e modificare i singoli elementi nelle raccolte.

L'interfaccia IEnumUnknown definisce questi metodi e il framework integra le funzionalità con metodi aggiuntivi definiti nell'interfaccia IUICollection . IUICollection viene implementato dal framework per ogni dichiarazione della raccolta nel markup della barra multifunzione.

Se è necessaria una funzionalità aggiuntiva non fornita dall'interfaccia IUICollection , è possibile sostituire un oggetto raccolta personalizzato implementato dall'applicazione host e derivato da IEnumUnknown .

IUICollectionChangedEvent

Per rispondere alle modifiche in una raccolta di raccolte, un'applicazione deve implementare l'interfaccia IUICollectionChangedEvent . Le applicazioni possono sottoscrivere notifiche da un oggetto IUICollection tramite il listener di eventi IUICollectionChangedEvent::OnChanged .

Quando l'applicazione sostituisce la raccolta raccolta fornita dal framework con una raccolta personalizzata, l'applicazione deve implementare l'interfaccia IConnectionPointContainer . Se IConnectionPointContainer non viene implementato, l'applicazione non è in grado di notificare il framework delle modifiche apportate alla raccolta personalizzata che richiedono aggiornamenti dinamici al controllo della raccolta.

In questi casi in cui IConnectionPointContainer non viene implementato, il controllo della raccolta può essere aggiornato solo tramite l'invalidazione tramite IUIFramework::InvalidateUICommandHandler::UpdateProperty o chiamando IUIFramework::SetUICommandProperty.

IUISimplePropertySet

Le applicazioni devono implementare IUISimplePropertySet per ogni elemento o Comando in una raccolta di raccolte. Tuttavia, le proprietà che possono essere richieste con IUISimplePropertySet::GetValue variano.

Gli elementi vengono definiti e associati a una raccolta tramite la chiave della proprietà UI_PKEY_ItemsSource ed espongono le proprietà con un oggetto IUICollection .

Le proprietà valide per gli elementi nelle raccolte di elementi (UI_COMMANDTYPE_COLLECTION) sono descritte nella tabella seguente.

Nota

Alcune proprietà dell'elemento, ad esempio UI_PKEY_Label, possono essere definite nel markup. Per altre informazioni, vedere la documentazione di riferimento sulle chiavi delle proprietà .

 

Control

Proprietà

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 è una proprietà della raccolta di elementi.

 

Le proprietà dell'elemento valide per le raccolte di comandi (UI_COMMANDTYPE_COMMANDCOLLECTION) sono descritte nella tabella seguente.

Control Proprietà
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

 

Le categorie vengono usate per organizzare elementi e comandi nelle raccolte. Le categorie vengono definite e associate a una raccolta tramite la chiave della proprietà UI_PKEY_Categories ed espongono le proprietà con un oggetto IUICollection specifico della categoria.

Le categorie non dispongono di un commandType e non supportano l'interazione dell'utente. Ad esempio, le categorie non possono diventare SelectedItem in una raccolta di elementi e non sono associate a un comando in una raccolta comandi. Come altre proprietà dell'elemento della raccolta, le proprietà della categoria, ad esempio UI_PKEY_Label e UI_PKEY_CategoryId , possono essere recuperate chiamando IUISimplePropertySet::GetValue.

Importante

IUISimplePropertySet::GetValue deve restituire UI_COLLECTION_INVALIDINDEXquando UI_PKEY_CategoryId viene richiesto per un elemento che non ha una categoria associata.

 

Dichiarare i controlli in Markup

Le raccolte, come tutti i controlli della barra multifunzione, devono essere dichiarati nel markup. Una raccolta viene identificata nel markup come raccolta di elementi o raccolta comandi e vengono dichiarati vari dettagli della presentazione. A differenza di altri controlli, le raccolte richiedono solo il controllo di base o il contenitore di raccolta, da dichiarare nel markup. Le raccolte effettive vengono popolate in fase di esecuzione. Quando una raccolta viene dichiarata nel markup, l'attributo Type viene usato per specificare se la raccolta è una raccolta di elementi di una raccolta comandi.

Sono disponibili diversi attributi di layout facoltativi per ognuno dei controlli descritti qui. Questi attributi forniscono le preferenze per gli sviluppatori per il framework da seguire che influiscono direttamente sul modo in cui un controllo viene popolato e visualizzato in una barra multifunzione. Le preferenze applicabili nel markup sono correlate ai modelli di visualizzazione e layout e ai comportamenti descritti in Personalizzazione di una barra multifunzione tramite definizioni di dimensioni e criteri di ridimensionamento.

Se un particolare controllo non consente le preferenze di layout direttamente nel markup o le preferenze di layout non vengono specificate, il framework definisce convenzioni di visualizzazione specifiche del controllo in base alla quantità di spazio dello schermo disponibile.

Gli esempi seguenti illustrano come incorporare un set di raccolte in una barra multifunzione.

Dichiarazioni di comando

I comandi devono essere dichiarati con un attributo CommandName usato per associare un controllo o un set di controlli con il comando.

Un attributo CommandId usato per associare un comando a un gestore comandi quando il markup viene compilato può essere specificato anche qui. Se non viene fornito alcun ID, ne viene generato uno dal framework.

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

Dichiarazioni di controllo

Questa sezione contiene esempi che illustrano il markup di controllo di base richiesto per i vari tipi di raccolta. Illustrano come dichiarare i controlli della raccolta e associarli a un comando tramite l'attributo CommandName .

Nell'esempio seguente viene illustrata una dichiarazione di controllo per DropDownGallery in cui viene usato l'attributo Type per specificare che si tratta di una raccolta comandi.

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

Nell'esempio seguente viene illustrata una dichiarazione di controllo per 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>

Nell'esempio seguente viene illustrata una dichiarazione di controllo per InRibbonGallery.

Nota

Poiché InRibbonGallery è progettato per visualizzare un subset della relativa raccolta di elementi nella barra multifunzione senza attivare un menu a discesa, fornisce un numero di attributi facoltativi che regolano le dimensioni e il layout dell'elemento nella inizializzazione della barra multifunzione. Questi attributi sono univoci per InRibbonGallery e non sono disponibili dagli altri controlli dinamici.

 

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

Nell'esempio seguente viene illustrata una dichiarazione di controllo per ComboBox.

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

Creare un gestore comandi

Per ogni comando, il framework della barra multifunzione richiede un gestore comandi corrispondente nell'applicazione host. I gestori comandi vengono implementati dall'applicazione host della barra multifunzione e sono derivati dall'interfaccia IUICommandHandler .

Nota

È possibile associare più comandi a un singolo gestore comandi.

 

Un gestore comandi serve due scopi:

  • IUICommandHandler::UpdateProperty risponde alle richieste di aggiornamento delle proprietà. I valori delle proprietà del comando, ad esempio UI_PKEY_Enabled o UI_PKEY_Label, vengono impostati tramite chiamate a IUIFramework::SetUICommandProperty o IUIFramework::InvalidateUICommand.
  • IUICommandHandler::Execute risponde agli eventi di esecuzione. Questo metodo supporta i tre stati di esecuzione seguenti specificati dal parametro UI_EXECUTIONVERB .
    • Lo stato Execute esegue o esegue il commit a, tutti i comandi a cui è associato il gestore.
    • Lo stato di anteprima visualizza in anteprima tutti i comandi a cui è associato il gestore. Questo esegue essenzialmente i comandi senza eseguire il commit al risultato.
    • Lo stato CancelPreview annulla qualsiasi comando in anteprima. Questa operazione è necessaria per supportare l'attraversamento attraverso un menu o un elenco e visualizzare in sequenza i risultati in anteprima e annullare i risultati in base alle esigenze.

Nell'esempio seguente viene illustrato un gestore dei comandi della raccolta.

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

Associare il gestore dei comandi

Dopo aver definito un gestore comandi, il comando deve essere associato al gestore.

Nell'esempio seguente viene illustrato come associare un comando di raccolta a un gestore di comandi specifico. In questo caso, entrambi i controlli ComboBox e raccolta sono associati ai rispettivi gestori comandi.

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

Inizializzare una raccolta

Nell'esempio seguente viene illustrata un'implementazione personalizzata di IUISimplePropertySet per le raccolte di elementi e comandi.

La classe CItemProperties in questo esempio è derivata da IUISimplePropertySet. Oltre al metodo obbligatorio IUISimplePropertySet::GetValue, la classe CItemProperties implementa un set di funzioni helper per l'inizializzazione e il rilevamento degli indici.

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

Gestire gli eventi di raccolta

Nell'esempio seguente viene illustrata un'implementazione di 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;
}

Proprietà della raccolta

Creazione di un'applicazione della barra multifunzione

Informazioni sui comandi e sui controlli

Linee guida per l'esperienza utente della barra multifunzione

Processo di progettazione della barra multifunzione

Esempio di raccolta