Arbeiten mit Katalogen
Das Windows-Menübandframework bietet Entwicklern ein stabiles und konsistentes Modell für die Verwaltung dynamischer Inhalte über eine Vielzahl sammlungsbasierter Steuerelemente hinweg. Durch Anpassen und Neukonfigurieren der Menüband-Benutzeroberfläche ermöglichen diese dynamischen Steuerelemente dem Framework, sowohl in der Hostanwendung als auch im Menüband selbst auf Benutzerinteraktion zu reagieren und die Flexibilität zur Handhabung verschiedener Laufzeitumgebungen zu bieten.
Einführung
Diese Fähigkeit des Menübandframework, sich dynamisch an Laufzeitbedingungen, Anwendungsanforderungen und Endbenutzereingaben anzupassen, hebt die umfassenden Benutzeroberflächenfunktionen des Frameworks hervor und bietet Entwicklern die Flexibilität, eine Vielzahl von Kundenanforderungen zu erfüllen.
Der Schwerpunkt dieses Leitfadens liegt darauf, die dynamischen Katalogsteuerelemente zu beschreiben, die vom Framework unterstützt werden, ihre Unterschiede zu erläutern, zu besprechen, wann und wo sie am besten verwendet werden können, und zu veranschaulichen, wie sie in eine Menübandanwendung integriert werden können.
Kataloge
Kataloge sind funktionstüchtige und grafisch umfangreiche Listenfeld-Steuerelemente. Die Elementsammlung eines Katalogs kann nach Kategorien organisiert, in flexiblen spalten- und zeilenbasierten Layouts angezeigt, mit Bildern und Text dargestellt werden und je nach Art des Katalogs die Livevorschau unterstützen.
Kataloge unterscheiden sich aus den folgenden Gründen funktionell von anderen dynamischen Menüband-Steuerelementen:
- Kataloge implementieren die IUICollection-Schnittstelle, die die verschiedenen Methoden zum Bearbeiten von Katalogelementsammlungen definiert.
- Kataloge können zur Laufzeit aktualisiert werden, basierend auf Aktivitäten, die direkt im Menüband auftreten, z. B. wenn ein Benutzer der Symbolleiste für den Schnellzugriff (QAT) einen Befehl hinzufügt.
- Kataloge können zur Laufzeit aktualisiert werden, basierend auf Aktivitäten, die indirekt aus der Laufzeitumgebung auftreten, z. B. wenn ein Druckertreiber nur Layouts für Hochformatseiten unterstützt.
- Kataloge können zur Laufzeit aktualisiert werden, basierend auf Aktivitäten, die indirekt in der Hostanwendung auftreten, z. B. wenn ein Benutzer ein Element in einem Dokument auswählt.
Das Menübandframework macht zwei Arten von Katalogen verfügbar: Elementgalerien und Befehlsgalerien.
Elementgalerien
Elementgalerien enthalten eine indexbasierte Auflistung verwandter Elemente, bei der jedes Element durch ein Bild, eine Zeichenfolge oder beides dargestellt wird. Das Steuerelement ist an einen einzelnen Befehlshandler gebunden, der auf dem Indexwert basiert, der von der _ PKEY _ SelectedItem-Eigenschaft der Benutzeroberfläche identifiziert wird.
Elementgalerien unterstützen die Livevorschau. Dies bedeutet, dass ein Befehlsergebnis basierend auf Mauszeiger oder Fokus angezeigt wird, ohne den Befehl zu committen oder tatsächlich auf den Befehl zu übertragen.
Wichtig
Das Framework unterstützt das Hosten von Elementgalerien im Anwendungsmenü nicht.
Befehlsgalerien
Befehlsgalerien enthalten eine Auflistung unterschiedlicher, nicht indizierter Elemente. Jedes Element wird durch ein einzelnes Steuerelement dargestellt, das über eine Befehls-ID an einen Befehlshandler gebunden ist. Wie eigenständige Steuerelemente leitet jedes Element in einem Befehlskatalog Eingabeereignisse an einen zugeordneten Befehlshandler weiter– der Befehlskatalog selbst laussiert nicht auf Ereignisse.
Befehlsgalerien unterstützen keine Livevorschau.
Katalogsteuerelemente
Es gibt vier Katalogsteuerelemente im Menübandframework: DropDownGallery, SplitButtonGallery, InRibbonGalleryund ComboBox. Alle außer ComboBox können entweder als Elementkatalog oder als Befehlskatalog implementiert werden.
DropDownGallery
Eine DropDownGallery ist eine Schaltfläche, die eine Dropdownliste anzeigt, die eine Sammlung von sich gegenseitig ausschließenden Elementen oder Befehlen enthält.
Der folgende Screenshot veranschaulicht das Menüband-Dropdownkatalog-Steuerelement in Microsoft Paint für Windows 7.

SplitButtonGallery
SplitButtonGallery ist ein zusammengesetztes Steuerelement, das ein einzelnes Standardelement oder einen Befehl aus seiner Sammlung auf einer primären Schaltfläche verfügbar macht und andere Elemente oder Befehle in einer sich gegenseitig ausschließenden Dropdownliste anzeigt, die angezeigt wird, wenn auf eine sekundäre Schaltfläche geklickt wird.
Der folgende Screenshot veranschaulicht das Steuerelement Ribbon Split Button Gallery in Microsoft Paint für Windows 7.

InRibbonGallery
Eine InRibbonGallery ist ein Katalog, der eine Sammlung verwandter Elemente oder Befehle im Menüband anzeigt. Wenn zu viele Elemente im Katalog vorhanden sind, wird ein Erweiterungspfeil bereitgestellt, um den Rest der Sammlung in einem erweiterten Bereich anzuzeigen.
Der folgende Screenshot veranschaulicht das Menüband-In-Ribbon Gallery-Steuerelement in Microsoft Paint für Windows 7.

Kombinationsfeld
Ein ComboBox-Steuerelement ist ein Einspalten-Listenfeld, das eine Sammlung von Elementen mit einem statischen Steuerelement oder einem Bearbeitungssteuerfeld und einem Dropdownpfeil enthält. Der Listenfeldteil des Steuerelements wird angezeigt, wenn der Benutzer auf den Dropdownpfeil klickt.
Der folgende Screenshot veranschaulicht ein Menüband-Kombinationsfeld-Steuerelement aus Windows Live Movie Maker.

Da comboBox ausschließlich ein Elementkatalog ist, werden keine Befehlselemente unterstützt. Es ist auch das einzige Katalogsteuer steuerelement, das keinen Befehlsraum unterstützt. (Ein Befehlsraum ist eine Sammlung von Befehlen, die im Markup deklariert und am unteren Rand eines Elementkatalogs oder Befehlskatalogs aufgeführt werden.)
Das folgende Codebeispiel zeigt das Markup, das zum Deklarieren eines Befehlsraums mit drei Schaltflächen in einer DropDownGallery erforderlich ist.
<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>
Der folgende Screenshot veranschaulicht den Befehlsraum mit drei Schaltflächen des vorangehenden Codebeispiels.

Implementieren eines Katalogs
In diesem Abschnitt werden die Implementierungsdetails von Menüband-Katalogen erläutert und erläutert, wie sie in eine Menübandanwendung integriert werden.
Die grundlegenden Komponenten
In diesem Abschnitt werden die Eigenschaften und Methoden beschrieben, die den Backbone dynamischer Inhalte im Menübandframework bilden und das Hinzufügen, Löschen, Aktualisieren und anderweitige Bearbeiten des Inhalts und visuellen Layouts von Menüband-Katalogen zur Laufzeit unterstützen.
IUICollection
Kataloge erfordern einen grundlegenden Satz von Methoden, um auf die einzelnen Elemente in ihren Sammlungen zu zugreifen und sie zu bearbeiten.
Die IEnumUnknown-Schnittstelle definiert diese Methoden, und das Framework ergänzt ihre Funktionalität durch zusätzliche Methoden, die in der IUICollection-Schnittstelle definiert sind. IUICollection wird vom Framework für jede Katalogdeklaration im Menübandmarkup implementiert.
Wenn zusätzliche Funktionen erforderlich sind, die nicht von der IUICollection-Schnittstelle bereitgestellt werden, kann ein benutzerdefiniertes Sammlungsobjekt, das von der Hostanwendung implementiert und von IEnumUnknown abgeleitet wird, durch die Frameworksammlung ersetzt werden.
IUICollectionChangedEvent
Damit eine Anwendung auf Änderungen in einer Katalogsammlung reagieren kann, muss sie die IUICollectionChangedEvent-Schnittstelle implementieren. Anwendungen können Benachrichtigungen von einem IUICollection-Objekt über den IUICollectionChangedEvent::OnChanged-Ereignislistener abonnieren.
Wenn die Anwendung die vom Framework bereitgestellte Katalogsammlung durch eine benutzerdefinierte Sammlung ersetzt, sollte die Anwendung die IConnectionPointContainer-Schnittstelle implementieren. Wenn IConnectionPointContainer nicht implementiert ist, kann die Anwendung das Framework nicht über Änderungen in der benutzerdefinierten Sammlung benachrichtigen, die dynamische Aktualisierungen des Katalogsteuerpunkts erfordern.
In Fällen, in denen IConnectionPointContainer nicht implementiert ist, kann das Katalogsteuerfeld nur durch Ungültigkeit über IUIFramework::InvalidateUICommand und IUICommandHandler::UpdatePropertyoder durch Aufrufen von IUIFramework::SetUICommandProperty aktualisiert werden.
IUISimplePropertySet
Anwendungen müssen IUISimplePropertySet für jedes Element oder jeden Befehl in einer Katalogsammlung implementieren. Die Eigenschaften, die mit IUISimplePropertySet::GetValue angefordert werden können, variieren jedoch.
Elemente werden über den _ PKEY _ ItemsSource-Eigenschaftsschlüssel der Benutzeroberfläche definiert und an einen Katalog gebunden und machen Eigenschaften mit einem IUICollection-Objekt verfügbar.
Die gültigen Eigenschaften für Elemente in Elementgalerien (UI _ COMMANDTYPE _ COLLECTION) werden in der folgenden Tabelle beschrieben.
Hinweis
Einige Elementeigenschaften, z. B. _ _ PKEY-Beschriftung der Benutzeroberfläche,können im Markup definiert werden. Weitere Informationen finden Sie in der Referenzdokumentation zu Eigenschaftsschlüsseln.
Control
Eigenschaften
Benutzeroberfläche _ PKEY _ Label, UI _ PKEY _ CategoryId
Benutzeroberfläche _ PKEY _ Label, UI _ PKEY _ ItemImage , UI _ PKEY _ CategoryId
Benutzeroberfläche _ PKEY _ Label, UI _ PKEY _ ItemImage , UI _ PKEY _ CategoryId
Benutzeroberfläche _ PKEY _ Label, UI _ PKEY _ ItemImage, UI _ PKEY _ CategoryId
Benutzeroberfläche _ PKEY _ SelectedItem ist eine Eigenschaft des Elementkatalogs.
Die gültigen Elementeigenschaften für Befehlssammlungen (UI _ COMMANDTYPE _ COMMANDCOLLECTION) werden in der folgenden Tabelle beschrieben.
Kategorien werden verwendet, um Elemente und Befehle in Katalogen zu organisieren. Kategorien werden über den Eigenschaftenschlüssel _ PKEY _ Categories der Benutzeroberfläche definiert und an einen Katalog gebunden und machen Eigenschaften mit einem kategoriespezifischen IUICollection-Objekt verfügbar.
Kategorien haben keinen CommandType und unterstützen keine Benutzerinteraktion. Beispielsweise können Kategorien nicht zum SelectedItem in einem Elementkatalog werden, und sie sind nicht an einen Befehl in einem Befehlskatalog gebunden. Wie andere Katalogelementeigenschaften können Kategorieeigenschaften wie UI _ PKEY _ Label und UI _ PKEY _ CategoryId durch Aufrufen von IUISimplePropertySet::GetValueabgerufen werden.
Wichtig
IUISimplePropertySet::GetValue sollte UI COLLECTION _ _ INVALIDINDEX zurückgeben, wenn ui _ PKEY _ CategoryId für ein Element angefordert wird, dem keine Kategorie zugeordnet ist.
Deklarieren der Steuerelemente im Markup
Kataloge müssen wie alle Menübandsteuerelemente im Markup deklariert werden. Ein Katalog wird im Markup als Elementkatalog oder Befehlskatalog identifiziert, und verschiedene Präsentationsdetails werden deklariert. Im Gegensatz zu anderen Steuerelementen müssen Kataloge nur das Basissteuerelement oder den Sammlungscontainer im Markup deklariert werden. Die tatsächlichen Auflistungen werden zur Laufzeit aufgefüllt. Wenn ein Katalog im Markup deklariert wird, wird das Type-Attribut verwendet, um anzugeben, ob der Katalog ein Elementkatalog eines Befehlskatalogs ist.
Für jedes der hier erläuterten Steuerelemente stehen eine Reihe optionaler Layoutattribute zur Verfügung. Diese Attribute bieten Entwicklereinstellungen für das Framework, die sich direkt darauf auswirken, wie ein Steuerelement aufgefüllt und in einem Menüband angezeigt wird. Die im Markup anwendbaren Einstellungen beziehen sich auf die Anzeige- und Layoutvorlagen und -verhaltensweisen, die unter Anpassen eines Menübands durch Größendefinitionen und Skalierungsrichtlinienerläutert werden.
Wenn ein bestimmtes Steuerelement layouteinstellungen nicht direkt im Markup zulässt oder die Layouteinstellungen nicht angegeben sind, definiert das Framework steuerelementspezifische Anzeigekonventionen basierend auf dem verfügbaren Bildschirmspeicherplatz.
In den folgenden Beispielen wird veranschaulicht, wie Sie eine Reihe von Katalogen in ein Menüband integrieren.
Befehlsdeklarationen
Befehle sollten mit einem CommandName-Attribut deklariert werden, das zum Zuordnen eines Steuerelements oder einer Gruppe von Steuerelementen zum Befehl verwendet wird.
Ein CommandId-Attribut, das zum Binden eines Befehls an einen Befehlshandler beim Kompilieren des Markups verwendet wird, kann hier ebenfalls angegeben werden. Wenn keine ID angegeben wird, wird eine vom Framework generiert.
<!-- 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"
Steuerelementdeklarationen
Dieser Abschnitt enthält Beispiele, die das grundlegende Steuerelementmarkup veranschaulichen, das für die verschiedenen Katalogtypen erforderlich ist. Sie zeigen, wie sie die Katalogsteuerelemente deklarieren und einem Befehl über das CommandName-Attribut zuordnen.
Das folgende Beispiel zeigt eine Steuerelementdeklaration für dropDownGallery, wobei das Type-Attribut verwendet wird, um anzugeben, dass es sich um einen Befehlskatalog handelt.
<!-- 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>
Das folgende Beispiel zeigt eine Steuerelementdeklaration für 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>
Das folgende Beispiel zeigt eine Steuerelementdeklaration für inRibbonGallery.
Hinweis
Da InRibbonGallery so konzipiert ist, dass eine Teilmenge der Elementauflistung im Menüband angezeigt wird, ohne ein Dropdownmenü zu aktivieren, stellt es eine Reihe optionaler Attribute bereit, die die Größe und das Elementlayout bei der Menübandinitialisierung steuern. Diese Attribute sind für inRibbonGallery eindeutig und nicht in den anderen dynamischen Steuerelementen verfügbar.
<!-- 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>
Das folgende Beispiel zeigt eine Steuerelementdeklaration für das ComboBox -Steuerelement.
<!-- ComboBox -->
<Group CommandName="cmdComboBoxGroup">
<ComboBox CommandName="cmdComboBox">
</ComboBox>
</Group>
Erstellen eines Befehlshandlers
Für jeden Befehl benötigt das Menübandframework einen entsprechenden Befehlshandler in der Hostanwendung. Befehlshandler werden von der Menübandhostanwendung implementiert und von der IUICommandHandler-Schnittstelle abgeleitet.
Hinweis
Mehrere Befehle können an einen einzelnen Befehlshandler gebunden werden.
Ein Befehlshandler dient zwei Zwecken:
- IUICommandHandler::UpdateProperty antwortet auf Anforderungen zum Aktualisieren von Eigenschaften. Die Werte der Befehlseigenschaften, z. B. UI _ PKEY _ Enabled oder UI _ PKEY _ Label,werden durch Aufrufe von IUIFramework::SetUICommandProperty oder IUIFramework::InvalidateUICommandfestgelegt.
- IUICommandHandler::Execute reagiert auf Ausführungsereignisse. Diese Methode unterstützt die folgenden drei Ausführungszustände, die vom _ EXECUTIONVERB-Parameter der Benutzeroberfläche angegeben werden.
- Der Ausführungsstatus führt befehle aus, an die der Handler gebunden ist, oder führt einen Commit an diese aus.
- Der Vorschauzustand zeigt eine Vorschau aller Befehle an, an die der Handler gebunden ist. Dies führt im Wesentlichen die Befehle aus, ohne ein Commit für das Ergebnis auszuführen.
- Der CancelPreview-Zustand bricht alle Befehle in der Vorschau ab. Dies ist erforderlich, um das Durchlaufen eines Menüs oder einer Liste zu unterstützen und sequenziell eine Vorschau anzuzeigen und die Ergebnisse nach Bedarf rückgängig zu machen.
Im folgenden Beispiel wird ein Katalogbefehlshandler veranschaulicht.
/*
* 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;
}
};
Binden des Befehlshandlers
Nachdem Sie einen Befehlshandler definiert haben, muss der Befehl an den Handler gebunden werden.
Im folgenden Beispiel wird veranschaulicht, wie ein Katalogbefehl an einen bestimmten Befehlshandler gebunden wird. In diesem Fall sind sowohl die ComboBox- als auch die Katalogsteuerelemente an ihre jeweiligen Befehlshandler gebunden.
// 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.
}
}
Initialisieren einer Auflistung
Im folgenden Beispiel wird eine benutzerdefinierte Implementierung von IUISimplePropertySet für element- und command-Kataloge veranschaulicht.
Die CItemProperties-Klasse in diesem Beispiel wird von IUISimplePropertySetabgeleitet. Zusätzlich zur erforderlichen IUISimplePropertySet::GetValue-Methodeimplementiert die CItemProperties-Klasse eine Reihe von Hilfsfunktionen für die Initialisierung und Indexnachverfolgung.
//
// 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;
};
Behandeln von Sammlungsereignissen
Im folgenden Beispiel wird eine IUICollectionChangedEvent-Implementierung veranschaulicht.
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;
}