Application Desktop Toolbars

Veröffentlicht: 13. Nov 2000 | Aktualisiert: 14. Jun 2004

Von Christoph Haltiner

Auf dieser Seite

 

Diesen Artikel können Sie hier lesen dank freundlicher Unterstützung der Zeitschrift:

Bild03

Wollten Sie auch schon einmal eine eigene Taskleiste programmieren oder Ihre Anwendung wie im Microsoft Office-Paket mit einer Shortcut-Leiste erweitern? All dies (und noch viel mehr) lässt sich über das Application Desktop Toolbar Interface von Windows realisieren. Wie Sie mit dieser Schnittstelle umgehen, wird hier anhand eines VB-Klassenmoduls beschrieben, mit dem Sie ein VB-Formular in eine Application Desktop Toolbar verwandeln können.

Was ist eine Application Desktop Toolbar?
Mit Application Desktop Toolbars (auch: AppBar) bezeichnet man die schmalen Fenster, die an die Bildschirmkanten angedockt sind und immer sichtbar bleiben, auch wenn andere Anwendungen maximiert werden. Die Windows Tasklist (Abbildung 1) ist wohl das bekannteste Beispiel einer AppBar.

Bild01

Abbildung 1: Die Windows Tasklist

Anwendungsbeispiele von AppBars
Was alles mit AppBars realisiert werden kann, hängt eigentlich nur von den Wünschen (und vielleicht vom Können) des Entwicklers ab. AppBars können nicht nur als Programmerweiterung, sondern auch als eigenständige Applikationen laufen. Die folgenden Beispiele vermitteln einen Eindruck von den vielfältigen Einsatzmöglichkeiten dieser kleinen Helfer:

  • Systemmonitor, der laufend die Prozessorauslastung, den Speicherverbrauch etc. anzeigt.

  • Newsticker, der auf aktuelle Meldungen hinweist (verbunden mit einem Online-Nachrichtendienst).

  • ShortcutBar, die die am häufigsten benutzten Programme enthält (Abbildung 2).

  • Anzeige für Zeit und Ort des nächsten Termins (als Ergänzung zu einer Agenda-Applikation).

Bild02

Abbildung 2: ShortcutBar des Microsoft Office 97 Pakets

Die Kommunikation zwischen AppBar und Betriebssystem
Eine AppBar muss - z.B. bei der Registrierung oder bei ihrer Entfernung - Meldungen an das Betriebssystem senden, so genannte AppBar Messages (Tabelle 1). Das Win32 API stellt dafür die Funktion SHAppBarMessage zu Verfügung.

Public Declare Function SHAppBarMessage Lib "shell32.dll" Alias 
"SHAppBarMessage" (ByVal dwMessage As Long, pData As APPBARDATA) As Long

Der erste Parameter, der angegeben werden muss, ist eine AppBar Message (s. Tabelle 1), der zweite ist eine Variable vom Typ AppBarData. Die verschiedenen Eigenschaften dieses Variablentyps ersehen Sie aus Tabelle 2. Die beiden Eigenschaften cbSize und hWnd müssen bei allen AppBar Messages angegeben werden, die übrigen werden nur von bestimmten AppBar Messages berücksichtigt (siehe Tabelle 1).

Konstante

Wert

Beschreibung

Berücksichtigte Parameter

ABM_NEW

&H0

Registriert eine neue AppBar.

cbSize, hWnd, uCallbackMessage

ABM_REMOVE

&H1

Löscht eine AppBar aus der Betriebssystem-internen Tabelle.

cbSize, hWnd

ABM_QUERYPOS

&H2

Korrigiert das übergebene Positionsrechteck für eine AppBar.

cbSize, hWnd, uEdge, rc

ABM_SETPOS

&H3

Schreibt Größe und Position der AppBar in die Windows-interne Tabelle.

cbSize, hWnd, uEdge, rc

ABM_GETSTATE

&H4

Gibt die AlwaysOnTop- und die Autohide-Eigenschaft der Tasklist zurück.

cbSize, hWnd

ABM_GETTASKBARPOS

&H5

Gibt die Position der Windows Tasklist zurück.

cbSize, hWnd, rc

ABM_ACTIVATE

&H6

Aktiviert das AppBar-Fenster.

cbSize, hWnd

ABM_GETAUTOHIDEBAR

&H7

Fragt, ob an der angegebenen Bildschirmkante bereits eine Autohide-AppBar vorhanden ist.

cbSize, hWnd, uEdge

ABM_SETAUTOHIDEBAR

&H8

Setzt die Autohide-Eigenschaft der AppBar.

cbSize, hWnd, uEdge, lParam

ABM_WINDOWPOSCHANGED

&H9

Informiert das System über einen Positionswechsel einer AppBar.

cbSize, hWnd

Tabelle 1: AppBar Messages. Die Win32 API-Funktion SHAppBarMessage erwartet eine AppBar Message als ersten Parameter.

Ereignisverarbeitung mit einer Callback-Funktion
Da die AppBar auf bestimmte Ereignisse reagieren muss - z.B. wenn eine FullScreenApplication (siehe Kasten 1) gestartet oder beendet wird - sollte sie auch Meldungen vom Betriebssystem empfangen können. Das geschieht über eine Callback-Funktion, eine Prozedur, die von einer anderen Komponente aus aufgerufen werden kann (z.B. von einer DLL oder vom Betriebssystem).

FullScreenApplications
Mit FullScreenApplication wird ein Programm bezeichnet, das den ganzen Bildschirm ausfüllt. Im Gegensatz zu maximierten Fenstern sind bei FullScreenApplications eventuell vorhandene Application Desktop Toolbars (also auch die Tasklist) nicht mehr sichtbar.

Beispiele für FullScreenApplications sind etwa der Microsoft Internet Explorer 4 im Vollbildmodus oder auch viele Installationsprogramme.

Allgemein wird eine FullScreenApplication empfohlen, wenn der Benutzer nicht gleichzeitig mehrere Anwendungen zu bedienen braucht. Man kann zwar auch mit FullScreenApplications noch mehrere Programme parallel bedienen, Programmwechsel sind dann aber nur noch über die Tastenkombination ALT+TAB möglich.

Kasten 1

Die Klasse clsAppBar
Die Klasse clsAppBar ist eine leicht abgeänderte Version der VB-Klasse TAppBar von Paolo Giacomuzzi [1]. Diese Klasse wiederum ist eine Übersetzung der MFC-Klasse CAppBar von J. Richter [2]. In diesem Artikel werden immer wieder Teile der Klasse clsAppBar als Beispielcode auftauchen. Da das Klassenmodul durch die vielen Prozeduraufrufe zum Teil etwas unübersichtlich ist, habe ich den Beispielcode an manchen Stellen vereinfacht.

Die Klasse clsAppBar verwenden
Die Verwendung dieser Klasse ist denkbar einfach. Sie müssen lediglich das Modul und das Klassenmodul des Beispielprojekts von der Heft-CD zu Ihrem Projekt hinzufügen. Um ein Formular in eine AppBar zu verwandeln, erzeugen Sie ein clsAppBar-Objekt und rufen die Methode Extends auf. Da die Klasse clsAppBar auch Ereignisse besitzt, sollte die Variable mit dem Schlüsselwort WithEvents deklariert werden.
Dim WithEvents

AppBar As clsAppBar 
Private Sub Form_Load() 
Set AppBar = New clsAppBar 
AppBar.Extends frmAppBar

Wenn Sie die AppBar nicht mehr benötigen, können Sie die Methode Detach aufrufen, und die AppBar wird entfernt.

Private Sub Form_Unload(Cancel As Integer) 
AppBar.Detach

Auf alle Eigenschaften der AppBar (z.B. an welcher Bildschirmkante sie andocken soll) können Sie bequem über die Eigenschaften der Objektvariablen zugreifen. Die wichtigsten Eigenschaften und der Code, der dahinter steht, werden in diesem Artikel erklärt.

Die Funktion SHAppBarMessage im Beispielklassenmodul
Neben der AppBarMessage verlangt die Funktion SHAppBarMessage als zweiten Parameter eine Variable von Typ AppBarData. Damit nicht immer eine AppBarData-Variable erstellt werden muss, wenn diese Funktion aufgerufen wird, ist sie im Klassenmodul in kleinere Funktionen aufgeteilt.

Anstatt also eine Variable zu erstellen und die Eigenschaften zuzuweisen, rufen Sie nur eine der vier Funktionen AppBarMessage1 bis AppBarMessage4 auf. Über Parameter können Sie die Eigenschaften der AppBarData-Variablen angeben, die diese AppBar Message verlangt. Diese vier Funktionen rufen die AppBarMessage-Prozedur auf, die sich auch im Klassenmodul befindet. In dieser Funktion wird eine AppBarData-Variable aus den Funktionsparametern gefüllt und als zweiter Parameter an die API-Funktion SHAppBarMessage übergeben.

Im Beispielcode in der basicpro werden alle Aufrufe dieser Funktionen durch äquivalente Aufrufe der Funktion SHAppBarMessage ersetzt, damit Sie einen besseren Überblick behalten.

Eine AppBar beim System an- und abmelden
Alle Application Desktop Toolbars werden vom Betriebssystem in einer internen Tabelle verwaltet. Das ist nötig, damit die Workarea (siehe Kasten 2) immer korrekt berechnet wird und sich die verschiedenen AppBars nicht in die Quere kommen. Damit diese interne Liste immer vollständig ist, müssen AppBars beim Betriebssystem an- und wieder abgemeldet werden.

Workarea
Mit Workarea wird der Bereich des Bildschirms bezeichnet, der nicht durch AppBars belegt ist. Wenn ein Fenster maximiert wird, füllt es immer nur die Workarea aus. Die Bildschirmfläche, die außerhalb dieser Workarea liegt, bleibt also auch bei maximierten Anwendungen sichtbar. Eine Ausnahme bilden FullScreenApplications (Kasten 1), die den gesamten Bildschirm ohne Rücksicht auf die Workarea ausfüllen.

Wenn die Workarea durch Hinzufügen, Entfernen oder Verschieben einer AppBar verändert wird, werden automatisch alle maximierten Fenster neu positioniert.

Kasten 2

Hinzufügen einer AppBar zum Desktop
Wollen Sie eine Application Desktop Toolbar über das Beispiel-Klassenmodul registrieren, brauchen Sie nur die Methode Extends aufzurufen. Als Parameter geben Sie das Formular an, das Sie als AppBar registrieren möchten.

Public Function Extends(ByVal Value As Form) 
Set Self = Value 
LinkCallback Value, Me 
OnCreate 
End Function

Zuerst wird das übergebene Formular in einer Objektvariablen vom Typ Form gespeichert. Als nächstes wird die Funktion LinkCallback ausgeführt, die sich im Modul AppBarModul befindet. Diese Funktion richtet die Callback-Prozedur Ihrer AppBar ein. Mit dem Aufruf der Methode OnCreate wird dann noch ein Timer installiert. Dieser Timer dient dazu, die AppBar auszublenden, falls die Autohide-Eigenschaft auf True eingestellt ist und die Maus den Bereich des Formulars verlassen hat. Um eine AppBar in die interne Liste des Betriebssystems einzutragen, müssen Sie die API-Funktion SHAppBarMessage mit den Parametern ABM_NEW aufrufen (das geschieht in OnCreate):

Dim AppBar As AppBarData 
AppBar.cbSize = Len(AppBar) 'Größe der AppBar-Variable 
AppBar.hWnd = frmAppBar.hWnd 'Handle des AppBar-Fensters 
AppBar.uCallbackMessage = WM_APPBARNOTIFY 'Selbstdefinierter Message Identifier 
SHAppBarMessage(ABM_NEW, AppBar)

ABM_NEW ist eine AppBarMessage-Konstante, AppBar eine Variable vom Typ AppBarData. Beim Senden der AppBar MessageABM_NEW werden von den Eigenschaften der AppBarData-Variablen (Tabelle 2) nur cbSize, hWnd und uCallbackMessage berücksichtigt. Nach diesem Schritt ist Ihre AppBar in der internen Liste von Windows eingetragen. Im Klassenmodul wird diese Aufgabe durch die Codezeile AppBarMessage1abmNew übernommen.

Es genügt aber nicht, die AppBar zu registrieren, damit sie angezeigt wird. Durch den Aufruf der Funktion UpdateBar wird die Eigenschaft Edge neu zugewiesen (ebenfalls in OnCreate). Das hat zur Folge, dass die AppBar neu angezeigt wird, weil sie bei jeder Änderung der Bildschirmkante an die neue Position verschoben werden muss. Wenn Sie die Anmeldung der AppBar selbst vornehmen, müssen Sie auch ihre Position und Größe selbst registrieren (s.u., Abschnitt Größe und Position).

Schließlich löscht die Methode OnCreate das Systemmenü des AppBar-Formulars. Da die Eigenschaft ControlBox während der Laufzeit schreibgeschützt ist, wird die API-Funktion DeleteMenu zu Hilfe genommen.

Eigenschaft

Bedeutung

cbSize

Größe der AppBarData-Variablen

hWnd

Window Handle des AppBar-Formulars

uCallbackMessage

Window Message Identifier für AppBar Notification Messages

uEdge

Bildschirmkante, an der die AppBar andocken soll. (ABE_TOP, ABE_LEFT, ABE_RIGHT oder ABE_BOTTOM)

rc

Rechteck, das das AppBar-Formular ausfüllen soll.

lParam

Zusätzlicher Parameter

Tabelle 2: Eigenschaften einer AppBarData-Variablen

Entfernen einer AppBar
Bevor Sie ein AppBar-Fenster mit Unload entfernen, müssen Sie die AppBar Message ABM_REMOVE senden. Bei dieser Meldung werden nur die beiden Parameter cbSize und hWnd berücksichtigt. Falls Sie vergessen, sie zu schicken, ist die AppBar-Tabelle des Betriebssystems nicht mehr aktuell. Das führt dazu, dass die Workarea nicht korrekt berechnet wird, so dass der Benutzer nur noch einen Teil der Desktopfläche verwenden kann.

Dim AppBar As AppBarData 
AppBar.cbSize = Len(AppBar) 
AppBar.hWnd = frmAppBar.hWnd 
SHAppBarMessage ABM_REMOVE, AppBar 
Unload frmAppBar

Um eine AppBar zu entfernen, die auf dem Klassenmodul basiert, rufen Sie die Methode Detach auf. Sie ruft die Methode OnDestroy auf, die zuerst den in OnCreate erstellten Timer löscht. Dann wird der Eigenschaft Edge des Klassenmoduls der Wert abeUnknown zugewiesen. Das ruft in der Property Let Edge-Prozedur die SHAppBarMessage-Funktion mit dem Parameter ABM_REMOVE auf. Nachdem die AppBar aus der Betriebssystemtabelle entfernt wurde, ruft die Methode Detach die Funktion DetachCallback des Moduls auf. Sie löscht die Callback-Prozedur, die von der Funktion LinkCallback eingerichtet wurde.

Dim AppBar as AppBarData 
KillTimer frmAppBar.hwnd, AUTO_HIDE_TIMER_ID 
AppBar.cdSize = Len(AppBar) 
AppBar.hWnd = frmAppBar.hWnd 
SHAppBarMessage ABM_REMOVE, AppBar 
Unload frmAppBar 
DetachCallback

Steuerelemente auf einer AppBar
Nachdem Sie eine AppBar erzeugt haben, übernimmt die Klasse clsAppBar fast alle Aufgaben für die Verwaltung des Formulars. Sie müssen es jetzt nur noch mit Leben füllen. Da eine AppBar ein VB-Formular ist, können Sie auf ihr alle Steuerelemente benutzen, wie Sie es gewohnt sind. Beachten Sie jedoch, dass eine AppBar keine Titel- und Menüleiste hat. Am besten stellen Sie die Funktionalität Ihrer Anwendung über Buttons (ähnlich wie auf einem Coolbar-Control) oder ein Kontextmenü (PopupMenu) zur Verfügung.

Daneben können Sie auch Textfelder und andere Steuerelemente auf einer AppBar einsetzen. Allerdings passen sich nicht alle gleich gut der geringen Breite einer AppBar an, die am linken bzw. rechten Bildschirmrand andockt. Benutzen Sie deshalb die ChangeEdge-Ereignisbehandlungsmethode Ihres clsAppBar-Objekts, um die Steuerelemente auf Ihrer AppBar deren Dimensionsänderungen anzupassen.

Die Callback-Funktion
Die Callback-Funktion hat den Zweck, Meldungen (sog. AppBar Notification Messages) vom Betriebssystem zu empfangen. AppBar Notification Messages benachrichtigen die AppBar über Ereignisse, die einen Einfluss auf ihre Position oder ihr Verhalten haben können. Die verschiedenen AppBar Notification Messages sehen Sie in Tabelle 3. Wie Sie auf die einzelnen Meldungen reagieren müssen, steht unten im Abschnitt AppBar Notification Messages.

Konstante

Wert

Bedeutung

ABN_STATECHANGE

&H0

Die Autohide- oder die AlwaysOnTop-Eigenschaft der Windows Tasklist wurde verändert.

ABN_POSCHANGED

&H1

Ein Ereignis ist aufgetreten, das die Größe oder die Position der AppBar beeinflussen könnte.

ABN_FULLSCREENAPP

&H2

Eine FullScreenApplication (siehe Kasten 1) wurde gestartet oder beendet.

ABN_WINDOWARRANGE

&H3

Im Kontextmenü der Tasklist wurde einer der Menüpunkte "Überlappen", "Untereinander" oder "Nebeneinander" gewählt.

Tabelle 3: AppBar Notification Messages. Sie werden von der AppBar-Callback-Funktion empfangen.

Realisierung der Callback-Funktion
Wie Ihnen sicher bekannt ist, arbeitet das Windows Betriebssystem mit Nachrichten. So gibt es z.B. Fenster-Nachrichten (Window Messages), mit denen das Betriebssystem Nachrichten an eine bestimmte Fensterhandle senden kann. Diese Nachrichten werden von einer Window Procedure (oder auch WindowProc) verarbeitet.

In Visual Basic hat man in der Regel nichts mit diesen Prozeduren zu tun. Man kann aber über das Windows-API erreichen, dass die Standard-WindowProc, die vom Compiler generiert wird, durch eine eigene ersetzt wird. Diese Möglichkeit machen wir uns bei der AppBarProgrammierung zunutze.

Bei der Registrierung der AppBar mit SHAppBarMessage(ABM_NEW, abd) wird in der Eigenschaft uCallbackMessage der AppBarData-Variablen ein selbstdefinierter Window Message Identifier angegeben - d.h. eine neue, eigene Windows-Meldung nur für unsere Anwendung. Im Beispielprogramm ist das die Konstante WM_APPBARNOTIFY. Sobald das Betriebssystem der AppBar etwas mitteilen möchte, sendet es eine WM_APPBARNOTIFY-Meldung an die WindowProc unseres VB-AppBar-Formulars. Zusätzlich können noch zwei weitere Parameter übergeben werden - dazu später mehr. Jetzt müssen Sie nur noch eine Prozedur programmieren und diese als aktuelle WindowProc für Ihre AppBar einstellen. Dieses Neueinstellen der WindowProc übernimmt im Beispielmodul die Prozedur LinkCallback (siehe Listing 1).

Einrichten und Entfernen der Callback-Funktion
In der LinkCallback-Funktion wird die Windowhandle des übergebenen Formulars in einer Variablen gespeichert und der Objektvariablen AppBar das übergebene clsAppBar-Objekt zugewiesen.

Public Function LinkCallback(ByVal frmInstance As Form, ByVal clsInstance As clsAppBar) 
ghWnd = frmInstance.hwnd 
Set gAppBar = clsInstance 
gpcbOldWindowProc = SetWindowLong(ghWnd, GWL_WNDPROC, AddressOf lfnAppBarCallback) 
End Function

Mit dem Aufruf von SetWindowLong(ghWnd, GWL_WNDPROC, AddressOf lfnAppBarCallback) wird die Adresse der WindowProc des AppBar-Formulars geändert auf die Adresse der Funktion lfnAppBarCallback, die sich auch im Modul befindet. Der Rückgabewert ist die Adresse der alten WindowProc. Auch diese wird in einer Variablen gespeichert, da sie später noch gebraucht wird, um die alte WindowProc aufzurufen. LinkCallback führt also ein Sub-classing des AppBar-Formulars durch; eine Technik, die zu den Grundlagen der Win32 API-Programmierung mit VB gehört.

In der Prozedur DetachCallback wird genau dieselbe API-Funktion aufgerufen, allerdings mit den Werten, die zuvor in den Variablen gespeichert wurden. Damit ist die alte WindowProc wiederhergestellt.

Public Function DetachCallback() 
SetWindowLong ghWnd, GWL_WNDPROC, gpcbOldWindowProc 
End Function

Die AppBar WindowProc
Das Wichtigste ist aber die Prozedur lfnAppBarCallback (siehe Listing 1). Diese Funktion dient als neue WindowProc und somit als Callback-Funktion. Die vier Parameter, die übergeben werden, haben folgende Bedeutung:

  • hWnd ist die Handle des Fensters, auf das sich die WindowProc bezieht. Diese Angabe ist nötig, weil man die gleiche Prozedur bei mehreren Fenstern als WindowProc angeben kann.

  • uMsg ist die Window Message, die in der Prozedur mit einer Select Case-Konstruktion ausgewertet wird.

  • wParam und lParam sind zusätzliche Parameter, die je nach Window Message anders verwendet werden. Wenn uMsg = WM_APPBARNOTIFY ist, handelt es sich beim Parameter wParam um die AppBar Notification Message (siehe Abschnitt AppBar Notification Messages).

In den einzelnen Fällen der Select Case-Konstruktion werden die entsprechenden Methoden des clsAppBar-Objekts aufgerufen. Wenn die aufgerufene Methode das Ereignis nicht behandelt, d.h. wenn der Standardrückgabewert der Methode nicht verändert worden ist, wird die alte WindowProc mit den Parametern aufgerufen, die an die Callback-Funktion übergeben worden sind.

In bestimmten Fällen muss die alte WindowProc ohnehin ausgeführt werden, deshalb befindet sich unterhalb der If-Konstruktion nochmals eine Select Case-Konstruktion.

Hier werden nicht alle On...-Ereignisbehandlungsroutinen des Klassenmoduls besprochen, Sie finden aber die Wichtigsten in Tabelle 4.

Window Message

Aufgerufene On... Methode

Beschreibung der On... Methode

WM_WINDOWPOSCHANGED

OnWindowPosChanged

Sendet die AppBar-Message ABM_WINDOWPOSCHANGED an das System.

WM_ACTIVATE

OnActivate wParam

Wenn das Fenster aktiviert wurde, wird die AppBar-Message ABM_ACTIVATE gesendet.
Wenn das Fenster deaktiviert wurde, wird es ausgeblendet, falls es sich um eine Autohide-AppBar handelt.

WM_NCMOUSEMOVE

OnNcMouseMove

Wenn es sich um eine Autohide-AppBar handelt, wird sie eingeblendet.

WM_TIMER

OnAppBarTimer

Wenn es sich um eine Autohide-AppBar handelt, diese nicht den Fokus besitzt und sich die Maus nicht über dem Fenster befindet, wird die AppBar ausgeblendet.

WM_APPBARNOTIFY oder anderer selbstdefinierter Message Identifier

OnAppBarCallbackMsg (wParam, lParam)

Ruft die Callback-Funktion der AppBar auf.

Tabelle 4: Die wichtigsten Window Messages, die die Callback-Funktion behandeln muss

Private Function lfnAppBarCallback(ByVal hwnd As Long, ByVal uMsg As Long, 
ByVal wParam As Long, ByVal lParam As Long) As Long 
Dim Result As Long 
Result = INHERIT_DEFAULT_CALLBACK 
Select Case uMsg 
Case WM_APPBARNOTIFY 
Result = gAppBar.OnAppBarCallbackMsg(wParam, lParam) 
Case WM_ENTERSIZEMOVE 
Result = gAppBar.OnEnterSizeMove 
Case WM_EXITSIZEMOVE 
Result = gAppBar.OnExitSizeMove 
Case WM_GETMINMAXINFO 
Result = gAppBar.OnGetMinMaxInfo(lParam) 
Case WM_MOVING 
Result = gAppBar.OnMoving(lParam) 
Case WM_NCMOUSEMOVE 
gAppBar.OnNcMouseMove 
Case WM_SIZING 
Result = gAppBar.OnSizing(wParam, lParam) 
Case WM_TIMER 
gAppBar.OnAppBarTimer 
End Select 
If Result = INHERIT_DEFAULT_CALLBACK Then 
Result = CallWindowProc(gpcbOldWindowProc, hwnd, uMsg, wParam, lParam) 
End If 
Select Case uMsg 
Case WM_ACTIVATE 
gAppBar.OnActivate wParam 
Case WM_NCHITTEST    
gAppBar.OnNcHitTest lParam, Result 
Case WM_WINDOWPOSCHANGED 
gAppBar.OnWindowPosChanged 
End Select 
lfnAppBarCallback = Result 
End Function 
'Aus dem Klassenmodul 
Friend Function OnAppBarCallbackMsg(ByVal wParam, ByVal lParam) As Long 
Select Case wParam 
Case ABN_FULLSCREENAPP 
OnABNFullScreenApp CBool(lParam) 
Case ABN_POSCHANGED 
OnABNPosChanged 
Case ABN_WINDOWARRANGE 
OnABNWindowArrange CBool(lParam) 
Case ABN_STATECHANGE 
OnABNStateChange 
End Select 
OnAppBarCallbackMsg = 0 
End Function 

Listing 1: Die Funktion lfnAppBarCallback ersetzt die WindowProc des AppBar-Formulars und verarbeitet alle Windows-Nachrichten, die an die AppBar geschickt werden - viele leitet sie jedoch weiter an die Original-WindowProc.
OnAppBarCallbackMsg behandelt die speziellen AppBar Notification Messages, die als Parameter der von uns definierten Nachricht WM_APPBARNOTIFY an die Callback-Funktion geschickt werden.

Größe und Position
Größe und Position der AppBar werden mithilfe einer Variablen vom Typ Rect angegeben. Rect-Variablen haben die Eigenschaften Top, Left, Right und Bottom, die jeweils den Abstand der betreffenden Kante vom Nullpunkt aus (linke obere Bildschirmecke) angeben. Auch die rechte und die untere Kante sind also vom Nullpunkt abhängig, und nicht, wie Sie es von den VB-Formularen gewöhnt sind, von der linken bzw. oberen Kante.

Größe und Position prüfen und setzen
Um die Position der AppBar zu ändern, müssen Sie zuerst beim System anfragen, ob die AppBar mit der gewünschten Größe an der betreffenden Ecke platziert werden darf. Sie erstellen also eine AppBarData-Variable, bei der Sie die Eigenschaften cbSize, hWnd, uEdge und rc angeben müssen. Danach rufen Sie die API-Funktion SHAppBarMessage mit der AppBar Message ABM_QUERYPOS auf.

Dim AppBar As APPBARDATA 
AppBar.cbSize = Len(AppBar) 'Grösse der Variablen 
AppBar.hwnd = frmAppBar.hwnd 'Handle des AppBar-Formulars 
AppBar.uEdge = BildschirmkanteAnDerDieAppBarAndockenSoll 'ABE_TOP, ABE_LEFT, ABE_RIGHT oder ABE_BOTTOM 
With AppBar.rc 'Rechteck zuweisen, das den gesamten Bildschirm ausfüllt 
.Left = 0 
.Top = 0 
.Right = GetSystemMetrics(SM_CXSCREEN) 
.Bottom = GetSystemMetrics(SM_CYSCREEN) 
End With 
SHAppBarMessage ABM_QUERYPOS, AppBar

Das System überprüft das vorgeschlagene Rechteck und korrigiert es, falls das nötig ist. Da Ihre AppBar aber natürlich nicht den gesamten Bildschirm ausfüllen darf, müssen Sie im nächsten Schritt mit dem korrigierten Rechteck die endgültige Größe der AppBar berechnen. Je nachdem, an welcher Bildschirmkante die AppBar andocken soll, müssen Sie die Left-, Top-, Right- oder Bottom-Eigenschaft ermitteln.

Select Case AppBar.uEdge 
Case ABE_TOP 
AppBar.rc.Bottom = AppBar.rc.Top + HöheDerAngedocktenAppBar 
Case ABE_LEFT 
AppBar.rc.Right = AppBar.rc.Left + BreiteDerAngedocktenAppBar 
Case ABE_RIGHT 
 AppBar.rc.Left = AppBar.rc.Right - BreiteDerAngedocktenAppBar 
Case ABE_BOTTOM 
AppBar.rc.Top = AppBar.rc.Bottom - HöheDerAngedocktenAppBar 
End Select

Danach kann die AppBar Message ABM_SETPOS gesendet werden, die die neue Position in der Betriebssystem-internen AppBar-Liste einträgt. Da Windows ein Multitasking-Betriebssystem ist, kann es sein, dass zwischen dem Aufruf von ABM_QUERYPOS und dem Aufruf von ABM_SETPOS eine andere Applikation die Workarea verändert hat, so dass das Rechteck, das nach ABM_QUERYPOS zurückgegeben wurde, nicht mehr gültig ist. Deshalb wird das Rechteck erneut überprüft und korrigiert. Nachdem die neue Position registriert ist, müssen Sie noch das AppBar-Formular an die neue Position verschieben. Dies geschieht nicht automatisch! Am besten verwenden Sie dazu die API-Funktion SetWindowPos. Da diese Funktion auch mit Pixeln arbeitet, können Sie direkt die Rechteckeigenschaften verwenden, ohne diese zuerst in Twips umzurechnen (was Sie bei der Move-Methode des Formulars machen müssten). Der Aufruf sieht dann so aus:

SetWindowPos frmAppBar.hwnd, 0, AppBar.rc.Left, AppBar.rc.Top, AppBar.rc.Right 
- AppBar.rc.Left, AppBar.rc.Bottom - AppBar.rc.Top, SWP_NOACTIVATE Or 
SWP_NOZORDER 

Das genügt schon, um die Position der AppBar zu verändern. Mit dem Klassenmodul clsAppBar ist das Ganze noch ein Stück einfacher.

An die Bildschirmkante andocken
Um die Bildschirmkante zu ändern, weisen Sie der Eigenschaft Edge des clsAppBar-Objekts die Bildschirmkante zu, an der sie andocken soll. Über die Eigenschaften VertDockSize bzw. HorzDockSize ändern Sie Breite bzw. Höhe der AppBar. Den Rest übernimmt das Klassenmodul.

AppBar Notification Messages
In diesem Abschnitt wird erklärt, was die einzelnen AppBar Notification Messages bedeuten und wie Sie darauf reagieren können. Eine Zusammenfassung aller AppBar Notification Messages sehen Sie in Tabelle 3. Die Beispielapplikation reagiert auf sie in der Funktion OnAppBarCallbackMsg (s. Listing 1).

ABN_STATECHANGE
Diese Meldung informiert die AppBar darüber, dass sich die AlwaysOnTop- oder die Autohide-Eigenschaft der Windows-Tasklist geändert hat, der Benutzer die betreffenden Kontrollkästchen im Eigenschaftendialog der Tasklist also gelöscht oder markiert hat.

Sie können diese Meldung verwenden, um die Autohide- und die AlwaysOnTop-Eigenschaft Ihrer AppBar automatisch an die der Tasklist anzupassen. Um festzustellen, ob die entsprechenden Eigenschaften der Tasklist aktiviert oder deaktiviert sind, senden Sie die App-Bar Message ABM_GETSTATE. Der Rückgabewert ist entweder ABS_ALWAYSONTOP, ABS_AUTOHIDE (auch kombiniert) oder Null, wenn keine der beiden Eigenschaften aktiviert ist.

Const ABS_ALWAYSONTOP = &H2  
Const ABS_AUTOHIDE = &H1

ABN_POSCHANGED
Ihre AppBar empfängt diese Meldung, wenn ein Ereignis aufgetreten ist, das die Größe oder Position Ihrer AppBar beeinflussen kann. Zu diesen Ereignissen gehören sowohl das Ändern der Größe oder der Position der Tasklist als auch das Hinzufügen, Verändern oder Entfernen von anderen Application Desktop Toolbars.
Wenn Sie diese Meldung empfangen, müssen Sie die Position und die Größe Ihrer AppBar neu berechnen und in die interne Liste des Betriebssystems eintragen. Wie das geht, wurde bereits im Abschnitt Größe und Position erläutert.

ABN_FULLSCREENAPP
Diese Meldung informiert die AppBar darüber, dass eine FullScreenApplication (siehe Kasten 1) gestartet oder beendet wurde. Der Parameter lParam, der auch an die Callback-Funktion übergeben wird, ist eine Boolean-Variable. Falls diese den Wert True hat, wurde eine FullScreenApplication gestartet. In diesem Fall müssen Sie die AppBar an das Ende der zOrder stellen. Das erreichen Sie, indem Sie die API-Funktion SetWindowPos aufrufen und als zweiten Parameter (hWndInsertAfter) die API-Konstante HWND_BOTTOM angeben:

SetWindowPos frmAppBar.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE 
Or SWP_NOACTIVATE

Wenn der Parameter lParam der Callback-Funktion hingegen False ist, bedeutet das, dass die FullScreenApplication beendet wurde. Sie können dann die ursprüngliche zOrder wiederherstellen.

ABN_WINDOWARRANGE
Sobald im Kontextmenü der Tasklist einer der drei Menüpunkte "Überlappen", "Untereinander" oder "Nebeneinander" gewählt wird, empfängt die AppBar diese Meldung. Genau genommen empfängt sie sie sogar zweimal: Bevor die Fenster angeordnet werden, ist der Parameter lParam = True, danach hat dieser Parameter den Wert False.

Um Ihr Formular von dieser Fensteranordnung auszuschließen, sollten Sie das AppBar-Formular beim ersten Empfang dieser Meldung ausblenden und beim zweiten Mal wieder einblenden. Das geschieht mit folgendem Code:

Dim bBeginning as Boolean 
bBeginning = CBool(lParam) 
If bBeginning = True Then 
frmAppBar.Visible = False 
Else 
frmAppBar.Visible = True 
End If

Special Effects
Autohide
Eine Autohide-AppBar unterscheidet sich von einer normalen AppBar dadurch, dass sie normalerweise nur wenige Pixel breit ist. Erst wenn eine Mausaktion über diesen Pixeln registriert wird, dehnt sich die AppBar zur vollen Größe aus. Wenn die Maus den Formularbereich wieder verlässt und ein anderes Fenster aktiviert, verschwindet die AppBar wieder. Das hat den Vorteil, dass die Workarea deutlich weniger eingeschränkt wird, als wenn die AppBar immer ganz sichtbar wäre. Einzelne Benutzer könnten es aber als störend empfinden, wenn eine AppBar wiederholt ein- und ausgeblendet wird, nur weil der Mauszeiger ohne Absicht den Bildschirmrand berührt. Deshalb sollten Sie ihnen die Möglichkeit geben, diese Eigenschaft auszuschalten. Im Beispielprogramm können Sie diese und andere Eigenschaften über das Kontextmenü der AppBar einstellen.

Es gibt zwei Möglichkeiten, Ihre AppBar in eine Autohide-AppBar zu verwandeln: Entweder entfernen Sie Ihre AppBar mit ABM_REMOVE oder Sie weisen ihr ein Rechteck mit den Koordinaten (0,0,0,0) als Größe zu. Das ist nötig, weil das Betriebssystem normale AppBars und Autohide-AppBars in getrennten Tabellen verwaltet. Wenn Sie keines von beidem tun, wird für Ihre AppBar immer noch Platz reserviert, obwohl Autohide-AppBars die Workarea nicht einschränken.

Danach müssen Sie die AppBar Message ABM_SETAUTOHIDEBAR senden. Sie verlangt die Parameter cbSize, hWnd, uEdge und lParam. lParam gibt an, ob Sie die Autohide-AppBar registrieren (lParam = True) oder entfernen (lParam = False) wollen.

Dim AppBar As AppBarData 
Dim bAutohide as Boolean 
AppBar.cbSize = Len(AppBar) 
AppBar.hWnd = frmAppBar.hWnd 
AppBar.uEdge = EckeAnDerDieAppBarAngedocktWerdenSoll 
AppBar.lParam = True 
bAutohide = SHAppBarMessage(ABM_SETAUTOHIDEBAR, AppBar)

Falls bAutohide <> False ist, ist Ihre AppBar als Autohide-AppBar an der gewählten Bildschirmkante, anderenfalls befindet sich an dieser Kante bereits eine andere Autohide-AppBar. Die AppBar-Message ABM_GETAUTOHIDEBAR liefert die Handle des Autohide-AppBarFensters an der angegebenen Kante.

Wenn die Maus über dem Formular bewegt wird, sendet das Betriebssystem die Window Message WM_NCMOUSEMOVE an die WindowProc (in diesem Fall also an die Callback-Funktion). Beim Erhalt dieser Nachricht müssen Sie das AppBar-Formular einblenden. Da die Workarea nicht verkleinert werden soll - die AppBar wird über den maximierten Anwendungen angezeigt - reicht es, wenn Sie das Formular mit der API-Funktion SetWindowPos oder der Move-Methode des Formulars verschieben. Sie müssen also weder eine ABM_QUERYPOS- noch eine ABM_SETPOS-Meldung an das Betriebssystem schicken.

Sobald Sie in der Callback-Funktion die Window Message WM_TIMER empfangen, müssen Sie mithilfe der API-Funktion GetActiveWindow überprüfen, ob das AppBar-Formular das aktive Fenster ist. Wenn dies nicht der Fall ist und sich auch der Mauszeiger nicht mehr über dem Formular befindet, können Sie die AppBar wieder ausblenden. Auch hier müssen Sie keine ABM_SETPOS-Meldung senden, sondern nur das Formular an die neue Position bewegen.

Um eine AppBar, die auf dem Klassenmodul clsAppBar basiert, in eine Autohide-AppBar zu verwandeln, müssen Sie nur die Eigenschaft Autohide des clsAppBar-Objekts auf True stellen.

Slide
Mit Slide bezeichnet man den Effekt, bei dem sich die AppBar nicht auf einen Schlag ausblendet, sondern in kleinen Schritten. So entsteht der Eindruck, dass die AppBar aus dem Bildschirm "rutscht". Dieser Effekt lässt sich relativ einfach programmieren. Sie müssen lediglich an den Codestellen, an denen Sie die AppBar aus- oder einblenden, anstatt einer einzelnen Anweisung für die komplette Aus-/Einblendung eine Schleife schreiben, die die AppBar nach und nach ausblendet. Das heißt, in jedem Schleifendurchlauf wird eine Kante des AppBar Formulars um einen bestimmten Wert verkleinert oder vergrößert. Welche Kante betroffen ist, hängt davon ab, wo Sie Ihre AppBar angedockt haben.

Die Klasse clsAppBar besitzt die Eigenschaft SlideEffect (und SlideTime). Über diese Eigenschaft können Sie mit einer Codezeile den Slide-Effekt der AppBar ein- oder ausschalten.

Wechseln zwischen AppBar und Toolwindow
Häufig können AppBars auch als Toolwindows angezeigt werden. Das sind kleine Fenster, die immer zuoberst auf dem Bildschirm liegen. Um eine AppBar in ein Toolwindow zu verwandeln, gibt es zwei Möglichkeiten:

  • Sie entfernen zuerst Ihre AppBar aus der AppBar-Liste, indem Sie die AppBar Message ABM_REMOVE senden. Danach können Sie das AppBar-Formular als Toolwindow anzeigen. Oder:

  • Ihre AppBar bleibt registriert. Sie weisen ihr in der OS-internen AppBar Tabelle als Größe ein Rechteck mit den Koordinaten (0,0,0,0) zu. Dadurch wird auch die Workarea nicht unnötig eingeschränkt.

Das Anzeigen des Toolwindows funktioniert in beiden Fällen mit SetWindowPos:

SetWindowPos frmAppBar.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE 
Or SWP_NOACTIVATE

Falls Sie eine AppBar, die auf der Beispielklasse basiert, in ein Toolwindow verwandeln möchten, müssen Sie der Eigenschaft Edge Ihrer Objektvariablen den Wert abeFloat zuweisen.

Schlusswort
Sie haben jetzt alle Kenntnisse, die Sie brauchen, um Ihr Programm mit einer AppBar zu erweitern oder eine eigenständige Application Desktop Toolbar zu programmieren. Diese Technik wird in Programmen noch viel zu selten verwendet, obwohl sie sehr nützlich ist. Überraschen Sie also Ihre Kunden mit einer Erweiterung, wie sie bisher nur bei Microsoft-Produkten zu finden ist!

In diesem Artikel wurden nur die Grundlagen von AppBars besprochen. Für zusätzliche Funktionen, wie z.B. das Speichern der Einstellungen in der Registry oder das Ändern der Bildschirmkante mit der Maus, empfehle ich einen tieferen Blick in den Artikel von J. Richter [2].
Quellen
[1] http://www.geocities.com/SiliconValley/9486/AppBar14.zip : VB Klasse "TAppBar" von Paolo Giacomuzzi (paolo.giacomuzzi@usa.net)

[2] Jeffrey Richter: Extend the Windows 95 Shell with Application Desktop Toolbars; MSJ, März 1996

Für Fragen und Anregungen erreichen Sie Christoph Haltiner per E-Mail an haltiner@swissonline.ch