Lavorare con le 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 su raccolte. Adattando e riconfigurando l'interfaccia utente della barra multifunzione, questi controlli dinamici consentono al framework di rispondere all'interazione dell'utente sia nell'applicazione host che nella barra multifunzione stessa e offrono la flessibilità necessaria per gestire vari ambienti di runtime.
Introduzione
Questa capacità del framework della barra multifunzione di adattarsi dinamicamente alle condizioni di runtime, ai requisiti dell'applicazione e all'input dell'utente finale evidenzia le funzionalità avanzate dell'interfaccia utente del framework e offre agli sviluppatori la flessibilità necessaria per soddisfare un'ampia gamma di esigenze dei clienti.
L'obiettivo di questa guida è descrivere i controlli dinamici della galleria supportati dal framework, spiegare le loro differenze, discutere quando e dove possono essere utilizzati al meglio e dimostrare come possano essere incorporati in un'applicazione Ribbon.
Gallerie
Le gallerie sono controlli della casella di elenco avanzati funzionalmente e graficamente. La raccolta di elementi di una raccolta può essere organizzata 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 funzionalmente distinte dagli altri controlli della barra multifunzione dinamica per i motivi seguenti:
- Le gallerie implementano l'interfaccia IUICollection, che definisce i vari metodi per la modifica delle raccolte di elementi della galleria.
- 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 di accesso rapido (QAT).
- Le gallerie possono essere aggiornate in tempo di esecuzione, basandosi su attività che si verificano indirettamente dall'ambiente di runtime, come quando un driver della stampante supporta solo i layout di pagina in 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 Ribbon espone due tipi di gallerie: gallerie di elementi e gallerie di comandi.
Raccolte di articoli
Le raccolte di elementi contengono una raccolta basata su indice di elementi correlati in cui ogni elemento è rappresentato da un'immagine, da una stringa o da entrambi. Il controllo è associato a un singolo gestore Command che si basa sul valore di indice identificato dalla proprietà UI_PKEY_SelectedItem.
Le raccolte di elementi supportano l'anteprima in tempo reale, ovvero la visualizzazione di un risultato del comando, in base al mouse o allo stato attivo, senza eseguire il commit o richiamare effettivamente il comando.
Importante
Il framework non supporta l'hosting di raccolte di elementi nel menu dell'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 di comandi tramite un ID comando. Analogamente ai controlli autonomi, ogni elemento di una raccolta comandi instrada gli eventi di input a un gestore dei comandi associato, ovvero la raccolta comandi stessa non è in ascolto degli eventi.
Le raccolte di comandi non supportano l'anteprima in tempo reale.
Controlli della galleria
Nel framework della barra multifunzione sono disponibili quattro controlli della galleria: DropDownGallery, SplitButtonGallery, InRibbonGallerye ComboBox. Tutti tranne i ComboBox possono essere implementati come una raccolta di elementi o una raccolta comandi.
DropDownGallery
Un DropDownGallery è un pulsante che visualizza un elenco a discesa contenente una raccolta di elementi o Comandi che si escludono a vicenda.
La schermata seguente illustra il controllo della barra multifunzione Drop-Down Gallery in Microsoft Paint per Windows 7.
SplitButtonGallery
Un 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 con opzioni mutuamente esclusive quando si fa clic su un pulsante secondario.
La schermata seguente illustra il controllo Pulsante diviso nella Raccolta della barra multifunzione in Microsoft Paint per Windows 7.
InRibbonGallery
Un InRibbonGallery è una galleria che visualizza una raccolta di elementi correlati o Comandi 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 Gallery In-Ribbon nella barra multifunzione di Microsoft Paint per Windows 7.
ComboBox
Un ComboBox è una casella di riepilogo a colonna singola che contiene una raccolta di elementi con un controllo statico o un controllo di modifica e una freccia a discesa. La sezione della casella di riepilogo del controllo viene visualizzata quando l'utente fa clic sulla freccia a discesa.
La schermata seguente illustra un controllo di tipo Casella combinata nella Barra multifunzione da Windows Live Movie Maker.
Poiché il ComboBox è esclusivamente una raccolta di elementi, non supporta gli elementi di comando. È anche l'unico controllo della galleria che non supporta uno spazio comandi. Uno spazio comandi è una raccolta di comandi dichiarati nel markup e elencati nella parte inferiore di una raccolta di elementi o di una raccolta di comandi.
Nell'esempio di codice seguente viene illustrato il markup necessario per dichiarare uno spazio comandi a tre pulsanti in 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 schermata seguente illustra lo spazio comandi a tre pulsanti dell'esempio di codice precedente.
Come implementare una galleria
Questa sezione descrive i dettagli di implementazione delle gallerie della barra multifunzione e spiega come integrarle in un'applicazione con la 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 del Ribbon.
Se sono necessarie funzionalità aggiuntive non fornite dall'interfaccia IUICollection , è possibile sostituire il framework di raccolta con un oggetto raccolta personalizzato che è implementato dall'applicazione host e derivato da IEnumUnknown.
IUICollectionChangedEvent
Affinché un'applicazione risponda alle modifiche apportate a una raccolta, deve implementare l'interfacciaIUICollectionChangedEvent. Le applicazioni possono sottoscrivere notifiche da un oggetto IUICollection tramite il listener di eventi IUICollection ChangedEvent::OnChanged.
Quando l'applicazione sostituisce la raccolta fornita dal framework con una raccolta personalizzata, essa deve implementare l'interfaccia IConnectionPointContainer. Se IConnectionPointContainer non viene implementato, l'applicazione non è in grado di notificare al framework le modifiche nella raccolta personalizzata che richiedono aggiornamenti dinamici al controllo galleria.
Nei casi in cui IConnectionPointContainer non viene implementato, il controllo raccolta può essere aggiornato solo tramite l'invalidazione con IUIFramework::InvalidateUICommand e IUICommandHandler::UpdatePropertyo 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 galleria 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à degli elementi, ad esempio UI_PKEY_Label, possono essere definite nel markup. Per altri dettagli, vedere la documentazione di riferimento sulle chiavi delle proprietà .
Controllo
Proprietà
UI_PKEY_Label, UI_PKEY_CategoryId
UI_PKEY_Label, UI_PKEY_ItemImage , UI_PKEY_CategoryId
UI_PKEY_Label, UI_PKEY_ItemImage , UI_PKEY_CategoryId
UI_PKEY_Label, UI_PKEY_ItemImage, UI_PKEY_CategoryId
UI_PKEY_SelectedItem è una proprietà della galleria di elementi.
Le proprietà dell'elemento valide per le raccolte di comandi (UI_COMMANDTYPE_COMMANDCOLLECTION) sono descritte nella tabella seguente.
Le categorie vengono usate per organizzare elementi e comandi nelle gallerie. Le categorie vengono definite e associate a una galleria tramite la chiave della proprietà UI_PKEY_Categories e mettono a disposizione proprietà con un oggetto IUICollection specifico di categoria .
Le categorie non hanno 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. Analogamente ad altre proprietà degli elementi della raccolta, è possibile recuperare proprietà di categoria come UI_PKEY_Label e UI_PKEY_CategoryId chiamando IUISimplePropertySet::GetValue.
Importante
IUISimplePropertySet::GetValue deve restituire UI_COLLECTION_INVALIDINDEX quando UI_PKEY_CategoryId viene richiesto per un elemento che non dispone di una categoria associata.
Dichiarare i controlli nel markup
Le raccolte, come tutti i controlli della barra multifunzione, devono essere dichiarate nel markup. Una raccolta viene identificata nel markup come raccolta di elementi o raccolta di comandi e vengono dichiarati vari dettagli di presentazione. A differenza di altri controlli, le gallerie richiedono che venga dichiarato nel markup solo il controllo di base o il contenitore di raccolta. Le raccolte effettive vengono popolate in fase di esecuzione. Quando una galleria viene dichiarata nel markup, l'attributo Type viene usato per specificare se la galleria è una galleria di elementi o una galleria di comandi.
Sono disponibili diversi attributi di layout facoltativi per ognuno dei controlli descritti qui. Questi attributi forniscono al framework le preferenze degli sviluppatori da seguire, influenzando direttamente il 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 disponibile sullo schermo.
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 a Command.
Un commandId attributo usato per associare un oggetto Command a un gestore command quando il markup viene compilato può essere specificato qui. Se non viene specificato 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 necessario per i vari tipi di galleria. 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 il DropDownGallery, in cui viene usato l'attributo Type per specificare che si tratta di una galleria di 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 l'InRibbonGallery.
Nota
Poiché il InRibbonGallery è progettato per visualizzare un subset della relativa raccolta di elementi nella barra multifunzione senza attivare un menu a discesa, fornisce una serie di attributi facoltativi che ne regolano le dimensioni e il layout degli elementi nell'inizializzazione della barra multifunzione. Questi attributi sono univoci per il 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 di comandi corrispondente nell'applicazione host. I gestori dei comandi sono 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 di comandi svolge due scopi:
- IUICommandHandler::UpdateProperty risponde alle richieste di aggiornamento delle proprietà. I valori delle proprietà command, 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 di tutti i comandi a cui è associato il gestore.
- Lo stato di anteprima visualizza in anteprima tutti i comandi a cui è associato il gestore. In pratica, vengono eseguiti i comandi senza confermare il risultato.
- Lo stato CancelPreview annulla tutti i comandi visualizzati in anteprima. Questa operazione è necessaria per supportare l'attraversamento attraverso un menu o un elenco e visualizzare in anteprima in sequenza e annullare i risultati in base alle esigenze.
Nell'esempio seguente viene illustrato un gestore di 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 della galleria a un gestore di comando specifico. In questo caso, sia il ComboBox sia i controlli della galleria sono associati ai rispettivi gestori di 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 deriva da IUISimplePropertySet. Oltre al metodo richiesto 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
L'esempio seguente illustra 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;
}
Argomenti correlati