Erstellen von benutzerdefinierten Explorer Balken, Werkzeugbändern und Schreibtischbändern
Die Explorer Bar wurde mit Microsoft Internet Explorer 4.0 eingeführt, um einen Anzeigebereich neben dem Browserbereich bereitzustellen. Es ist im Grunde ein untergeordnetes Fenster innerhalb des Windows Internet Explorer Fensters, und es kann verwendet werden, um Informationen anzuzeigen und mit dem Benutzer auf die gleiche Weise zu interagieren. Explorer Balken werden am häufigsten als vertikaler Bereich auf der linken Seite des Browserbereichs angezeigt. Eine Explorer leiste kann jedoch auch horizontal unterhalb des Browserbereichs angezeigt werden.
Für die Explorer Bar gibt es zahlreiche Einsatzmöglichkeiten. Benutzer können die gewünschte Option auf verschiedene Arten auswählen, z. B. im Untermenü Explorer Bar des Menüs Ansicht oder durch Klicken auf eine Symbolleistenschaltfläche. Internet Explorer bietet mehrere Standard-Explorer Balken, einschließlich Favoriten und Suche.
Sie können internet-Explorer anpassen, indem Sie eine benutzerdefinierte Explorer-Leiste hinzufügen. Nach der Implementierung und Registrierung wird sie dem Untermenü Explorer Bar des Menüs Ansicht hinzugefügt. Wenn er vom Benutzer ausgewählt wird, kann der Anzeigebereich der Explorer Leiste dann verwendet werden, um Informationen anzuzeigen und Benutzereingaben auf die gleiche Weise wie ein normales Fenster zu übernehmen.
Zum Erstellen eines benutzerdefinierten Explorer Bar müssen Sie ein Bandobjekt implementieren und registrieren. Bandobjekte wurden mit Version 4.71 der Shell eingeführt und bieten Funktionen, die denen normaler Fenster ähneln. Da es sich jedoch um COM-Objekte (Component Object Model) handelt, die entweder im Internet Explorer oder in der Shell enthalten sind, werden sie etwas anders implementiert. Einfache Bandobjekte wurden verwendet, um das Beispiel Explorer Balken zu erstellen, die in der ersten Grafik angezeigt werden. Die Implementierung des vertikalen Explorer Bar-Beispiels wird in einem späteren Abschnitt ausführlich erläutert.
Toolbänder
Ein Toolband ist ein Bandobjekt, das mit Microsoft Internet Explorer 5 eingeführt wurde, um das Windows-Optionssymbolleistenfeature zu unterstützen. Die Symbolleiste "Internet Explorer" ist eigentlich ein Rebar-Steuerelement, das mehrere Symbolleistensteuerelemente enthält. Wenn Sie ein Toolband erstellen, können Sie diesem Rebar-Steuerelement eine Band hinzufügen. Wie Explorer Balken ist ein Werkzeugband jedoch ein universelles Fenster.
Benutzer zeigen eine Symbolleiste an, indem sie sie im Untermenü Symbolleisten des MenüsAnsicht oder im Kontextmenü auswählen, das durch Klicken mit der rechten Maustaste auf den Symbolleistenbereich angezeigt wird.
Schreibtischbänder
Bandobjekte können auch zum Erstellen von Schreibtischbändern verwendet werden. Während ihre grundlegende Implementierung Explorer Bars ähnelt, haben Schreibtischbänder nichts mit internet-Explorer zu tun. Ein Schreibtischband ist im Grunde eine Möglichkeit, ein andockbares Fenster auf dem Desktop zu erstellen. Der Benutzer wählt sie aus, indem er mit der rechten Maustaste auf die Taskleiste klickt und sie im Untermenü Symbolleisten auswählt.
Zunächst sind Schreibtischbänder an der Taskleiste angedockt.
Der Benutzer kann dann das Schreibtischband auf den Desktop ziehen, und es wird als normales Fenster angezeigt.
Implementieren von Bandobjekten
Die folgenden Themen werden erläutert.
- Grundlagen des Bandobjekts
- Bandregistrierung
- Einfaches Beispiel für eine benutzerdefinierte Explorer leiste
Grundlagen des Bandobjekts
Obwohl sie ähnlich wie normale Fenster verwendet werden können, sind Bandobjekte COM-Objekte, die in einem Container vorhanden sind. Explorer Bars sind in internet Explorer enthalten, und Schreibtischbänder sind in der Shell enthalten. Obwohl sie verschiedene Funktionen erfüllen, ist ihre grundlegende Implementierung sehr ähnlich. Der Hauptunterschied besteht darin, wie das Bandobjekt registriert wird, das wiederum den Typ des Objekts und seinen Container steuert. In diesem Abschnitt werden die Aspekte der Implementierung erläutert, die allen Bandobjekten gemeinsam sind. Weitere Implementierungsdetails finden Sie unter Ein einfaches Beispiel für eine benutzerdefinierte Explorer leiste.
Zusätzlich zu IUnknown und IClassFactory müssen alle Bandobjekte die folgenden Schnittstellen implementieren.
Neben der Registrierung ihres Klassenbezeichners (CLSID) müssen die Explorer Bar- und Desk-Band-Objekte auch für die entsprechende Komponentenkategorie registriert werden. Das Registrieren der Komponentenkategorie bestimmt den Objekttyp und dessen Container. Toolbänder verwenden ein anderes Registrierungsverfahren und verfügen nicht über einen Kategoriebezeichner (CATID). Die CATIDs für die drei Bandobjekte, die diese benötigen, sind:
Bandtyp | Komponentenkategorie |
---|---|
Vertikale Explorer-Leiste | CATID_InfoBand |
Horizontale Explorer leiste | CATID_CommBand |
Schreibtischband | CATID_DeskBand |
Weitere Informationen zum Registrieren von Bandobjekten finden Sie unter Bandregistrierung .
Wenn das Bandobjekt Benutzereingaben akzeptiert, muss es auch IInputObject implementieren. Zum Hinzufügen von Elementen zum Kontextmenü für Explorer Bar- oder Schreibtischbänder muss das Bandobjekt IContextMenu exportieren. Symbolleisten unterstützen keine Kontextmenüs.
Da Bandobjekte ein untergeordnetes Fenster implementieren, müssen sie auch eine Fensterprozedur implementieren, um Windows-Messaging zu verarbeiten.
Bandobjekte können Befehle über die IOleCommandTarget-Schnittstelle des Containers an ihren Container senden. Um den Schnittstellenzeiger abzurufen, rufen Sie die IInputObjectSite::QueryInterface-Methode des Containers auf, und fragen Sie nach IID_IOleCommandTarget. Anschließend senden Sie Befehle mit IOleCommandTarget::Exec an den Container. Die Befehlsgruppe ist CGID_DeskBand. Wenn die IDeskBand::GetBandInfo-Methode eines Bandobjekts aufgerufen wird, verwendet der Container den dwBandID-Parameter , um dem Bandobjekt einen Bezeichner zuzuweisen, der für drei der Befehle verwendet wird. Vier IOleCommandTarget:: Exec-Befehls-IDs werden unterstützt.
DBID_BANDINFOCHANGED
Die Bandinformationen wurden geändert. Legen Sie den parameter pvaIn auf den Bandbezeichner fest, der beim letzten Aufruf von IDeskBand::GetBandInfo empfangen wurde. Der Container ruft die IDeskBand::GetBandInfo-Methode des Bandobjekts auf, um die aktualisierten Informationen anzufordern.
DBID_MAXIMIZEBAND
Maximieren Sie das Band. Legen Sie den parameter pvaIn auf den Bandbezeichner fest, der beim letzten Aufruf von IDeskBand::GetBandInfo empfangen wurde.
DBID_SHOWONLY
Aktivieren oder deaktivieren Sie andere Bänder im Container. Legen Sie den pvaIn-Parameter auf den VT_UNKNOWN-Typ mit einem der folgenden Werte fest:
Wert BESCHREIBUNG Punk Ein Zeiger auf die IUnknown-Schnittstelle des Bandobjekts. Alle anderen Schreibtischbänder werden ausgeblendet. 0 Ausblenden aller Schreibtischbänder. 1 Alle Schreibtischbänder anzeigen. DBID_PUSHCHEVRON
Version 5. Anzeigen eines Chevronmenüs Der Container sendet eine RB_PUSHCHEVRON Nachricht, und das Bandobjekt empfängt eine RBN_CHEVRONPUSHED Benachrichtigung, die zum Anzeigen des Menüs "Chevron" auffordert. Legen Sie den nCmdExecOpt-Parameter der IOleCommandTarget::Exec-Methode auf den Bandbezeichner fest, der im letzten Aufruf von IDeskBand::GetBandInfo empfangen wurde. Legen Sie den pvaIn-Parameter der IOleCommandTarget::Exec-Methode auf den typ VT_I4 mit einem anwendungsdefiniertem Wert fest. Es wird an das Bandobjekt als lAppValue-Wert der RBN_CHEVRONPUSHED-Benachrichtigung zurückgegeben.
Bandregistrierung
Ein Bandobjekt muss als OLE-In-Process-Server registriert werden, der Apartmentthreading unterstützt. Der Standardwert für den Server ist eine Menütextzeichenfolge. Für Explorer Bars wird sie im Untermenü Explorer Bar des Menüs Internet Explorer Ansicht angezeigt. Für Toolbänder wird sie im Untermenü Symbolleisten des Menüs Internet Explorer Ansicht angezeigt. Für Schreibtischbänder wird sie im Untermenü Symbolleisten des Kontextmenüs der Taskleiste angezeigt. Wie bei Menüressourcen führt das Platzieren eines ampersand (&) vor einem Buchstaben dazu, dass dieser unterstrichen wird und Tastenkombinationen aktiviert werden. Beispielsweise lautet die Menüzeichenfolge für die vertikale Explorer Leiste, die in der ersten Grafik gezeigt wird, "Sample &Vertical Explorer Bar".
Zunächst ruft Internet Explorer mithilfe der Komponentenkategorien eine Enumeration der registrierten Explorer Bar-Objekte aus der Registrierung ab. Um die Leistung zu erhöhen, wird diese Enumeration zwischengespeichert, sodass anschließend Explorer Bars übersehen werden. Um zu erzwingen, dass Windows Internet Explorer den Cache neu erstellt und eine neue Explorer Bar erkennt, löschen Sie während der Registrierung der neuen Explorer Leiste die folgenden Registrierungsschlüssel:
HKEY_CURRENT_USER\Software\Microsoft\Fenster\Currentversion\\ Explorer Discardable\PostSetup\Component Categories\{00021493-0000-0000-C000-000000000046}\Enum
HKEY_CURRENT_USER\Software\Microsoft\Fenster\Currentversion\\ Explorer Discardable\PostSetup\Component Categories\{00021494-0000-0000-C000-0000000000046}\Enum
Hinweis
Da für jeden Benutzer ein Explorer Bar-Cache erstellt wird, muss Ihre Setupanwendung möglicherweise alle Benutzerregistrierungsstrukturen auflisten oder einen Stub pro Benutzer hinzufügen, der ausgeführt werden soll, wenn sich der Benutzer zum ersten Mal anmeldet.
Im Allgemeinen wird der grundlegende Registrierungseintrag für ein Bandobjekt wie folgt angezeigt.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
(Default) = Menu Text String
InProcServer32
(Default) = DLL Path Name
ThreadingModel = Apartment
Bei Toolbändern muss auch die CLSID ihres Objekts bei internet-Explorer registriert sein. Weisen Sie hierzu einen Wert unter HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Toolbar mit der CLSID-GUID des Toolbandobjekts zu, wie hier gezeigt. Sein Datenwert wird ignoriert, sodass der Werttyp nicht wichtig ist.
HKEY_LOCAL_MACHINE
Software
Microsoft
Internet Explorer
Toolbar
{Your Band Object's CLSID GUID}
Es gibt mehrere optionale Werte, die auch der Registrierung hinzugefügt werden können. Für instance ist der folgende Wert erforderlich, wenn Sie den Explorer Bar verwenden möchten, um HTML anzuzeigen. Der angezeigte Wert ist kein Beispiel, sondern der tatsächliche Wert, der verwendet werden sollte.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
Instance
CLSID
(Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}
In Verbindung mit dem oben gezeigten Wert ist der folgende optionale Wert auch erforderlich, wenn Sie die Explorer Leiste zum Anzeigen von HTML verwenden möchten. Dieser Wert sollte auf den Speicherort der Datei festgelegt werden, die den HTML-Inhalt für die Explorer Leiste enthält.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
Instance
InitPropertyBag
Url
Ein weiterer optionaler Wert definiert die Standardbreite oder -höhe des Explorer Balkens, je nachdem, ob er vertikal oder horizontal ist.
HKEY_CURRENT_USER
Software
Microsoft
Internet Explorer
Explorer Bars
{Your Band Object's CLSID GUID}
BarSize
Der BarSize-Wert sollte auf die Breite oder Höhe des Balkens festgelegt werden. Der Wert benötigt acht Bytes und wird in der Registrierung als binärer Wert platziert. Die ersten vier Bytes geben die Größe in Pixeln im Hexadezimalformat an, beginnend mit dem byte links. Die letzten vier Bytes sind reserviert und sollten auf 0 (null) festgelegt werden.
Hier werden beispielsweise die vollständigen Registrierungseinträge für einen HTML-fähigen Explorer Bar mit einer Standardbreite von 291 (0x123) Pixeln angezeigt.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
(Default) = Menu Text String
InProcServer32
(Default) = DLL Path Name
ThreadingModel = Apartment
Instance
CLSID
(Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}
InitPropertyBag
Url = Your HTML File
HKEY_CURRENT_USER
Software
Microsoft
Internet Explorer
Explorer Bars
{Your Band Object's CLSID GUID}
BarSize = 23 01 00 00 00 00 00 00
Sie können die Registrierung der CATID eines Bandobjekts programmgesteuert verarbeiten. Erstellen Sie ein Komponentenkategorien-Manager-Objekt (CLSID_StdComponentCategoriesMgr), und fordern Sie einen Zeiger auf die zugehörige ICatRegister-Schnittstelle an. Übergeben Sie die CLSID und CATID des Bandobjekts an ICatRegister::RegisterClassImplCategories.
Ein einfaches Beispiel für eine benutzerdefinierte Explorer leiste
In diesem Beispiel wird die Implementierung des vertikalen Beispiels Explorer Balken in der Einführung beschrieben.
Das grundlegende Verfahren zum Erstellen einer benutzerdefinierten Explorer Bar lautet wie folgt.
- Implementieren Sie die funktionen, die von der DLL benötigt werden.
- Implementieren Sie die erforderlichen COM-Schnittstellen.
- Implementieren Sie alle gewünschten optionalen COM-Schnittstellen.
- Registrieren Sie die CLSID des Objekts und, falls erforderlich, die Komponentenkategorie.
- Erstellen Sie ein untergeordnetes Fenster von Internet Explorer, das an den Anzeigebereich der Explorer Leiste angepasst ist.
- Verwenden Sie das untergeordnete Fenster, um Informationen anzuzeigen und mit dem Benutzer zu interagieren.
Die sehr einfache Implementierung, die im Beispiel Explorer Bar verwendet wird, könnte tatsächlich für einen Explorer Bar-Typ oder ein Schreibtischband verwendet werden, indem sie einfach für die entsprechende Komponentenkategorie registriert wird. Komplexere Implementierungen müssen für den Anzeigebereich und container jedes Objekttyps angepasst werden. Ein Großteil dieser Anpassung kann jedoch erreicht werden, indem Der Beispielcode verwendet und erweitert wird, indem vertraute Windows-Programmiertechniken auf das untergeordnete Fenster angewendet werden. Sie können beispielsweise Steuerelemente für Benutzerinteraktionen oder Grafiken für eine umfangreichere Anzeige hinzufügen.
DLL-Funktionen
Alle drei Objekte werden in einer einzelnen DLL gepackt, die die folgenden Funktionen verfügbar macht.
Die ersten drei Funktionen sind Standardimplementierungen und werden hier nicht behandelt. Die Class Factory-Implementierung ist ebenfalls Standard.
Erforderliche Schnittstellenimplementierungen
Das Beispiel für vertikale Explorer Bar implementiert die vier erforderlichen Schnittstellen: IUnknown, IObjectWithSite, IPersistStream und IDeskBand als Teil der CExplorerBar-Klasse. Die Implementierungen Konstruktor, Destruktor und IUnknown sind einfach und werden hier nicht erläutert. Sehen Sie sich den Beispielcode an, um ausführliche Informationen zu erhalten.
Die folgenden Schnittstellen werden ausführlich erläutert.
Iobjectwithsite
Wenn der Benutzer eine Explorer Bar auswählt, ruft der Container die IObjectWithSite::SetSite-Methode des entsprechenden Bandobjekts auf. Der PunkSite-Parameter wird auf den IUnknown-Zeiger der Website festgelegt.
Im Allgemeinen sollte eine SetSite-Implementierung die folgenden Schritte ausführen:
- Geben Sie alle Websitezeiger frei, die derzeit gespeichert werden.
- Wenn der an SetSite übergebene Zeiger auf NULL festgelegt ist, wird das Band entfernt. SetSite kann S_OK zurückgeben.
- Wenn der an SetSite übergebene Zeiger nicht NULL ist, wird eine neue Website festgelegt.
SetSite sollte die folgenden Aktionen ausführen:
- Rufen Sie QueryInterface auf der Website für die IOleWindow-Schnittstelle auf.
- Rufen Sie IOleWindow::GetWindow auf, um das Handle des übergeordneten Fensters abzurufen. Speichern Sie das Handle zur späteren Verwendung. Geben Sie IOleWindow frei, wenn es nicht mehr benötigt wird.
- Erstellen Sie das Fenster des Bandobjekts als untergeordnetes Element des Im vorherigen Schritt abgerufenen Fensters. Erstellen Sie es nicht als sichtbares Fenster.
- Wenn das Bandobjekt IInputObject implementiert, rufen Sie QueryInterface auf der Website für die IInputObjectSite-Schnittstelle auf. Speichern Sie den Zeiger auf diese Schnittstelle zur späteren Verwendung.
- Wenn alle Schritte erfolgreich sind, geben Sie S_OK zurück. Wenn dies nicht der Fehler ist, geben Sie den OLE-definierten Fehlercode zurück, der angibt, welcher Fehler aufgetreten ist.
Im Beispiel Explorer Bar wird SetSite wie folgt implementiert. Im folgenden Code ist m_pSite eine private Membervariable, die den IInputObjectSite-Zeiger und m_hwndParent das Handle des übergeordneten Fensters enthält. In diesem Beispiel wird auch die Fenstererstellung behandelt. Wenn das Fenster nicht vorhanden ist, erstellt diese Methode das Fenster Explorer Bar als ein entsprechend großes untergeordnetes Element des übergeordneten Fensters, das von SetSite abgerufen wurde. Das Handle des untergeordneten Fensters wird in m_hwnd gespeichert.
STDMETHODIMP CDeskBand::SetSite(IUnknown *pUnkSite)
{
HRESULT hr = S_OK;
m_hwndParent = NULL;
if (m_pSite)
{
m_pSite->Release();
}
if (pUnkSite)
{
IOleWindow *pow;
hr = pUnkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&pow));
if (SUCCEEDED(hr))
{
hr = pow->GetWindow(&m_hwndParent);
if (SUCCEEDED(hr))
{
WNDCLASSW wc = { 0 };
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hInstance = g_hInst;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = g_szDeskBandSampleClass;
wc.hbrBackground = CreateSolidBrush(RGB(255, 255, 0));
RegisterClassW(&wc);
CreateWindowExW(0,
g_szDeskBandSampleClass,
NULL,
WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0,
0,
0,
0,
m_hwndParent,
NULL,
g_hInst,
this);
if (!m_hwnd)
{
hr = E_FAIL;
}
}
pow->Release();
}
hr = pUnkSite->QueryInterface(IID_IInputObjectSite, reinterpret_cast<void **>(&m_pSite));
}
return hr;
}
Die GetSite-Implementierung des Beispiels umschließt einfach einen Aufruf der QueryInterface-Methode der Website mithilfe des von SetSite gespeicherten Websitezeigers.
STDMETHODIMP CDeskBand::GetSite(REFIID riid, void **ppv)
{
HRESULT hr = E_FAIL;
if (m_pSite)
{
hr = m_pSite->QueryInterface(riid, ppv);
}
else
{
*ppv = NULL;
}
return hr;
}
Ipersiststream
Internet Explorer ruft die IPersistStream-Schnittstelle der Explorer Bar auf, damit die Explorer Bar persistente Daten laden oder speichern kann. Wenn keine persistenten Daten vorhanden sind, müssen die Methoden trotzdem einen Erfolgscode zurückgeben. Die IPersistStream-Schnittstelle erbt von IPersist, sodass fünf Methoden implementiert werden müssen.
- IPersist::GetClassID
- IPersistStream::IsDirty
- IPersistStream::Load
- IPersistStream::Save
- IPersistStream::GetSizeMax
Das Beispiel Explorer Bar verwendet keine persistenten Daten und verfügt nur über eine minimale Implementierung von IPersistStream. IPersist::GetClassID gibt die CLSID (CLSID_SampleExplorerBar) des Objekts zurück, und der Rest gibt entweder S_OK, S_FALSE oder E_NOTIMPL zurück.
IDeskBand
Die IDeskBand-Schnittstelle ist spezifisch für Bandobjekte. Zusätzlich zu seiner einen Methode erbt es von IDockingWindow, das wiederum von IOleWindow erbt.
Es gibt zwei IOleWindow-Methoden : GetWindow und IOleWindow::ContextSensitiveHelp. Die Implementierung von GetWindow im Explorer Bar-Beispiel gibt das Ziehpunkt für untergeordnete Fenster des Explorer Bar m_hwnd zurück. Die kontextbezogene Hilfe ist nicht implementiert, sodass ContextSensitiveHelpE_NOTIMPL zurückgibt.
Die IDockingWindow-Schnittstelle verfügt über drei Methoden.
Die ResizeBorderDW-Methode wird nicht mit einem Bandobjekt verwendet und sollte immer E_NOTIMPL zurückgeben. Die ShowDW-Methode blendet das Fenster des Explorer Bar abhängig vom Wert des zugehörigen Parameters ein oder aus.
STDMETHODIMP CDeskBand::ShowDW(BOOL fShow)
{
if (m_hwnd)
{
ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
}
return S_OK;
}
Die CloseDW-Methode zerstört das Fenster der Explorer Leiste.
STDMETHODIMP CDeskBand::CloseDW(DWORD)
{
if (m_hwnd)
{
ShowWindow(m_hwnd, SW_HIDE);
DestroyWindow(m_hwnd);
m_hwnd = NULL;
}
return S_OK;
}
Die verbleibende Methode GetBandInfo ist spezifisch für IDeskBand. Internet Explorer verwendet es, um den Bezeichner und den Anzeigemodus der Explorer Leiste anzugeben. Internet Explorer können auch eine oder mehrere Informationen von der Explorer Bar anfordern, indem sie den dwMask-Member der DESKBANDINFO-Struktur füllen, der als dritter Parameter übergeben wird. GetBandInfo sollte den Bezeichner und den Anzeigemodus speichern und die DESKBANDINFO-Struktur mit den angeforderten Daten füllen. Das beispiel Explorer Bar implementiert GetBandInfo, wie im folgenden Codebeispiel gezeigt.
STDMETHODIMP CDeskBand::GetBandInfo(DWORD dwBandID, DWORD, DESKBANDINFO *pdbi)
{
HRESULT hr = E_INVALIDARG;
if (pdbi)
{
m_dwBandID = dwBandID;
if (pdbi->dwMask & DBIM_MINSIZE)
{
pdbi->ptMinSize.x = 200;
pdbi->ptMinSize.y = 30;
}
if (pdbi->dwMask & DBIM_MAXSIZE)
{
pdbi->ptMaxSize.y = -1;
}
if (pdbi->dwMask & DBIM_INTEGRAL)
{
pdbi->ptIntegral.y = 1;
}
if (pdbi->dwMask & DBIM_ACTUAL)
{
pdbi->ptActual.x = 200;
pdbi->ptActual.y = 30;
}
if (pdbi->dwMask & DBIM_TITLE)
{
// Don't show title by removing this flag.
pdbi->dwMask &= ~DBIM_TITLE;
}
if (pdbi->dwMask & DBIM_MODEFLAGS)
{
pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
}
if (pdbi->dwMask & DBIM_BKCOLOR)
{
// Use the default background color by removing this flag.
pdbi->dwMask &= ~DBIM_BKCOLOR;
}
hr = S_OK;
}
return hr;
}
Optionale Schnittstellenimplementierungen
Es gibt zwei Schnittstellen, die nicht erforderlich sind, aber für die Implementierung kann nützlich sein: IInputObject und IContextMenu. Das beispiel Explorer Bar implementiert IInputObject. Informationen zum Implementieren von IContextMenu finden Sie in der Dokumentation.
IInputObject
Die IInputObject-Schnittstelle muss implementiert werden, wenn ein Bandobjekt Benutzereingaben akzeptiert. Internet Explorer implementiert IInputObjectSite und verwendet IInputObject, um den richtigen Benutzereingabefokus beizubehalten, wenn mehr als ein enthaltenes Fenster vorhanden ist. Es gibt drei Methoden, die von einem Explorer-Balken implementiert werden müssen.
Internet Explorer ruft UIActivateIO auf, um die Explorer Leiste darüber zu informieren, dass sie aktiviert oder deaktiviert wird. Bei Aktivierung ruft das Beispiel Explorer Bar SetFocus auf, um den Fokus auf das zugehörige Fenster festzulegen.
Internet Explorer ruft HasFocusIO auf, wenn versucht wird, zu bestimmen, welches Fenster den Fokus hat. Wenn das Fenster der Explorer Leiste oder eines seiner Nachfolger den Fokus hat, sollte HasFocusIO S_OK zurückgeben. Andernfalls sollte S_FALSE zurückgegeben werden.
TranslateAcceleratorIO ermöglicht dem -Objekt die Verarbeitung von Tastenkombinationen. Das Explorer Bar-Beispiel implementiert diese Methode nicht, sodass S_FALSE zurückgegeben wird.
Die Implementierung von IInputObjectSite in der Beispielleiste lautet wie folgt.
STDMETHODIMP CDeskBand::UIActivateIO(BOOL fActivate, MSG *)
{
if (fActivate)
{
SetFocus(m_hwnd);
}
return S_OK;
}
STDMETHODIMP CDeskBand::HasFocusIO()
{
return m_fHasFocus ? S_OK : S_FALSE;
}
STDMETHODIMP CDeskBand::TranslateAcceleratorIO(MSG *)
{
return S_FALSE;
};
CLSID-Registrierung
Wie bei allen COM-Objekten muss die CLSID des Explorer Bar registriert werden. Damit das Objekt ordnungsgemäß mit internet Explorer funktioniert, muss es auch für die entsprechende Komponentenkategorie (CATID_InfoBand) registriert werden. Der relevante Codeabschnitt für die Explorer Bar wird im folgenden Codebeispiel gezeigt.
HRESULT RegisterServer()
{
WCHAR szCLSID[MAX_PATH];
StringFromGUID2(CLSID_DeskBandSample, szCLSID, ARRAYSIZE(szCLSID));
WCHAR szSubkey[MAX_PATH];
HKEY hKey;
HRESULT hr = StringCchPrintfW(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s", szCLSID);
if (SUCCEEDED(hr))
{
hr = E_FAIL;
if (ERROR_SUCCESS == RegCreateKeyExW(HKEY_CLASSES_ROOT,
szSubkey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
NULL))
{
WCHAR const szName[] = L"DeskBand Sample";
if (ERROR_SUCCESS == RegSetValueExW(hKey,
NULL,
0,
REG_SZ,
(LPBYTE) szName,
sizeof(szName)))
{
hr = S_OK;
}
RegCloseKey(hKey);
}
}
if (SUCCEEDED(hr))
{
hr = StringCchPrintfW(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s\\InprocServer32", szCLSID);
if (SUCCEEDED(hr))
{
hr = HRESULT_FROM_WIN32(RegCreateKeyExW(HKEY_CLASSES_ROOT, szSubkey,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL));
if (SUCCEEDED(hr))
{
WCHAR szModule[MAX_PATH];
if (GetModuleFileNameW(g_hInst, szModule, ARRAYSIZE(szModule)))
{
DWORD cch = lstrlen(szModule);
hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE) szModule, cch * sizeof(szModule[0])));
}
if (SUCCEEDED(hr))
{
WCHAR const szModel[] = L"Apartment";
hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, L"ThreadingModel", 0, REG_SZ, (LPBYTE) szModel, sizeof(szModel)));
}
RegCloseKey(hKey);
}
}
}
return hr;
}
Die Registrierung von Bandobjekten im Beispiel verwendet normale COM-Verfahren.
Zusätzlich zur CLSID muss der Bandobjektserver auch für eine oder mehrere Komponentenkategorien registriert werden. Dies ist tatsächlich der Standard Unterschied bei der Implementierung zwischen den vertikalen und horizontalen Explorer Bar-Beispielen. Dieser Prozess wird verarbeitet, indem ein Komponentenkategorien-Manager-Objekt (CLSID_StdComponentCategoriesMgr) erstellt und die ICatRegister::RegisterClassImplCategories-Methode zum Registrieren des Bandobjektservers verwendet wird. In diesem Beispiel wird die Komponentenkategorieregistrierung verarbeitet, indem die CLSID und CATID des Explorer Bar-Beispiels an eine private Funktion – RegisterComCat – übergeben wird, wie im folgenden Codebeispiel gezeigt.
HRESULT RegisterComCat()
{
ICatRegister *pcr;
HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pcr));
if (SUCCEEDED(hr))
{
CATID catid = CATID_DeskBand;
hr = pcr->RegisterClassImplCategories(CLSID_DeskBandSample, 1, &catid);
pcr->Release();
}
return hr;
}
Die Fensterprozedur
Da ein Bandobjekt ein untergeordnetes Fenster für seine Anzeige verwendet, muss es eine Fensterprozedur implementieren, um Windows-Messaging zu verarbeiten. Das Bandbeispiel verfügt über minimale Funktionalität, sodass seine Fensterprozedur nur fünf Nachrichten verarbeitet:
Das Verfahren kann problemlos erweitert werden, um zusätzliche Nachrichten aufzunehmen, um weitere Features zu unterstützen.
LRESULT CALLBACK CDeskBand::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = 0;
CDeskBand *pDeskBand = reinterpret_cast<CDeskBand *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
switch (uMsg)
{
case WM_CREATE:
pDeskBand = reinterpret_cast<CDeskBand *>(reinterpret_cast<CREATESTRUCT *>(lParam)->lpCreateParams);
pDeskBand->m_hwnd = hwnd;
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pDeskBand));
break;
case WM_SETFOCUS:
pDeskBand->OnFocus(TRUE);
break;
case WM_KILLFOCUS:
pDeskBand->OnFocus(FALSE);
break;
case WM_PAINT:
pDeskBand->OnPaint(NULL);
break;
case WM_PRINTCLIENT:
pDeskBand->OnPaint(reinterpret_cast<HDC>(wParam));
break;
case WM_ERASEBKGND:
if (pDeskBand->m_fCompositionEnabled)
{
lResult = 1;
}
break;
}
if (uMsg != WM_ERASEBKGND)
{
lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return lResult;
}
Der WM_COMMAND-Handler gibt einfach null zurück. Der WM_PAINT-Handler erstellt die einfache Textanzeige, die im Beispiel Explorer Bar in der Einführung gezeigt wird.
void CDeskBand::OnPaint(const HDC hdcIn)
{
HDC hdc = hdcIn;
PAINTSTRUCT ps;
static WCHAR szContent[] = L"DeskBand Sample";
static WCHAR szContentGlass[] = L"DeskBand Sample (Glass)";
if (!hdc)
{
hdc = BeginPaint(m_hwnd, &ps);
}
if (hdc)
{
RECT rc;
GetClientRect(m_hwnd, &rc);
SIZE size;
if (m_fCompositionEnabled)
{
HTHEME hTheme = OpenThemeData(NULL, L"BUTTON");
if (hTheme)
{
HDC hdcPaint = NULL;
HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rc, BPBF_TOPDOWNDIB, NULL, &hdcPaint);
DrawThemeParentBackground(m_hwnd, hdcPaint, &rc);
GetTextExtentPointW(hdc, szContentGlass, ARRAYSIZE(szContentGlass), &size);
RECT rcText;
rcText.left = (RECTWIDTH(rc) - size.cx) / 2;
rcText.top = (RECTHEIGHT(rc) - size.cy) / 2;
rcText.right = rcText.left + size.cx;
rcText.bottom = rcText.top + size.cy;
DTTOPTS dttOpts = {sizeof(dttOpts)};
dttOpts.dwFlags = DTT_COMPOSITED | DTT_TEXTCOLOR | DTT_GLOWSIZE;
dttOpts.crText = RGB(255, 255, 0);
dttOpts.iGlowSize = 10;
DrawThemeTextEx(hTheme, hdcPaint, 0, 0, szContentGlass, -1, 0, &rcText, &dttOpts);
EndBufferedPaint(hBufferedPaint, TRUE);
CloseThemeData(hTheme);
}
}
else
{
SetBkColor(hdc, RGB(255, 255, 0));
GetTextExtentPointW(hdc, szContent, ARRAYSIZE(szContent), &size);
TextOutW(hdc,
(RECTWIDTH(rc) - size.cx) / 2,
(RECTHEIGHT(rc) - size.cy) / 2,
szContent,
ARRAYSIZE(szContent));
}
}
if (!hdcIn)
{
EndPaint(m_hwnd, &ps);
}
}
Die WM_SETFOCUS- und WM_KILLFOCUS-Handler informieren die Website über eine Fokusänderung, indem sie die IInputObjectSite::OnFocusChangeIS-Methode der Website aufrufen.
void CDeskBand::OnFocus(const BOOL fFocus)
{
m_fHasFocus = fFocus;
if (m_pSite)
{
m_pSite->OnFocusChangeIS(static_cast<IOleWindow*>(this), m_fHasFocus);
}
}
Bandobjekte bieten eine flexible und leistungsstarke Möglichkeit, die Funktionen von Internet Explorer zu erweitern, indem benutzerdefinierte Explorer Bars erstellt werden. Durch die Implementierung eines Schreibtischbands können Sie die Funktionen normaler Fenster erweitern. Obwohl eine gewisse COM-Programmierung erforderlich ist, dient sie letztendlich dazu, ein untergeordnetes Fenster für Ihre Benutzeroberfläche bereitzustellen. Von dort aus kann der Großteil der Implementierung vertraute Windows-Programmiertechniken verwenden. Obwohl das hier erläuterte Beispiel nur eingeschränkte Funktionalität aufweist, werden alle erforderlichen Features eines Bandobjekts veranschaulicht, und es kann leicht erweitert werden, um eine einzigartige und leistungsstarke Benutzeroberfläche zu erstellen.