Verwenden von Visual Styles
Kurzfassung
Mit Windows XP können Benutzeroberflächen grafisch aufwendiger ausgeführt werden, indem für die Fenster Visual Styles aktiviert werden. Wie man dabei vorgeht und welche Einschränkungen man dadurch bei mit Visual Basic erstellten Anwendungen in Kauf nehmen muß, wird in diesem Artikel beschrieben.
Einleitung
Dieser Artikel betrifft nur die Entwicklung von Anwendungen für Windows XP und neuere Versionen, etwa Windows Server 2003. Die hier angegebenen Informationen beziehen sich auf Microsoft Visual Basic 6.0, sind aber auch für Visual Basic 5.0 und andere Programmiersprachen relevant. Die hier angegebenen Methoden lassen sich auch unter Anwendungen, die auf dem .NET Framework aufbauen, benutzen. Dazu muß bei Steuerelementen wie Schaltflächen die FlatStyle
-Eigenschaft auf System
eingestellt werden.
Windows XP Visual Styles
Windows XP brachte neben den bereits bestehenden Desktopschemas, den Themes, sogenannte Visual Styles mit sich. Damit ist es möglich, Anwendungen in einem erweiterten grafischen Darstellungsmodus auszuführen und/oder für diesen zu erstellen. Die Änderungen der grafischen Darstellung von Anwendungsoberflächen betrifft zwei Bereiche: den Non-Clientbereich, das sind Rahmen und Titelleiste, und den Clientbereich, der die Steuerelemente auf dem Formular aufnimmt.
Microsoft hat zum Zeitpunkt des Entstehens dieses Dokuments erst unvollständige Spezifikationen der Visual Styles unter Windows XP sowie der dahinterliegenden UxTheme.dll
zur Verfügung gestellt. Informationen dazu finden sich im Artikel Using Windows XP Visual Styles.
Themes und Visual Styles
Für das Verständnis der folgenden Kapitel ist es notwendig, daß man den Unterschied zwischen Themes und Visual Styles kennt. Daher wird dieser hier kurz erläutert.
Themes
Themes gibt es seit Windows 95, bei dem sie im Plus!-Paket enthalten waren; auch spätere Versionen von Windows unterstützten Desktopschemas. Sie bestehen aus einem Farbschema für Fenster, Schrifteinstellungen, Mauszeiger, Symbolen und einem Hintergrundbild sowie Klängen. Mit Themes war es jedoch nicht möglich, Einfluß auf die Darstellung von Steuerelementen zu nehmen, wenn man von Farbe und Schrift absieht. Die Dateien, in denen Themes enthalten sind, tragen die Dateiendung .theme
und können auch von ISVs erstellt und vertrieben werden.
Visual Styles
Visual Styles wurden erstmals mit Windows XP eingeführt, das eine überarbeitete Renderingengine namens Luna mit sich bringt. Diese ermöglicht es, Visual Styles in herkömmlichen Anwendungen zu benutzen. Im Gegensatz zu Themes kann dadurch auch die Form und Darstellungsart der Steuerelemente beeinflußt werden. Zugleich wurde eine umfangreiche Programmierschnittstelle eingeführt, um größtmögliche Dynamik in die Darstellung von Anwendungsoberflächen zu bringen. Bei benutzerdefinierten Steuerelementen kann der Programmierer festlegen, in welcher Darstellungsklasse sie als Ganzes oder auch nur teilweise angezeigt werden sollen; beispielsweise könnten die Tageseinträge in einem Kalender-Steuerelement gleich wie Schaltflächen einer Werkzeugleiste angezeigt werden. In Windows XP werden die Stile der gerade installierten Visual Styles automatisch auf die Elemente des Non-Clientbereichs von Formularen angewendet, die Anwendung auf den Clientbereich der Formulare muß über ein Manifest explizit erwirkt werden.
Anwendungsmanifeste
Die Verwendung von Manifesten, das sind spezielle XML-Dateien, ist vielseitig. Für diesen Artikel wird nur die Anwendung in Bezug auf die Visual Styles herausgegriffen. Manifeste können mit einem Texteditor wie dem Windows-Editor oder aber auch mit einem beliebigen XML-Editor erstellt werden. Im Normalfall wird man aber auf eine Vorlage, wie im folgenden Listing zu sehen, zurückgreifen, anstatt das XML-Dokument neu zu schreiben.
Im Weiteren gehen wir davon aus, daß unsere kompilierte Anwendung in der Datei MyApp.exe
vorliegt. Um den neuen Darstellungsmodus nutzen zu können, muß eine Textdatei erstellt werden, die aussieht, wie im folgenden Codebeispiel angegeben:
Anstelle von „1.0.0.0“ als Wert des Attributs version
des assemblyIdentity
-Elements muß die Programmversion, für die dieses Manifest erstellt wird, angegeben werden; der Wert MyCompany.MyProduct.MyApp
des Attributs name
muß durch die entsprechenden Daten ersetzt werden. Am Einfachsten ist es, die Anwendung zu kompilieren und danach die Daten aus dem Dateieigenschaftsdialog der fertigen EXE-Datei abzulesen. Soll die Manifestdatei in die EXE-Datei über eine Ressourcendatei eingebunden werden, müssen die Versionsinformationen und sonstigen Informationen im Manifest mit denen der Anwendung übereinstimmen, andernfalls wird beim Starten des Programms eine Fehlermeldung ausgegeben. Einige der Angaben müssen nicht genau erfolgen, bei processorArchitecture
würde auch ein *
als Wert genügen.
Die Manifestdatei muß unter dem Namen MyApp.exe.manifest
im Anwendungsverzeichnis bzw. Quellverzeichnis des Ressourcenscripts abgespeichert werden. Wird eine Anwendung, die ein Manifest enthält, unter einer früheren Version von Windows als Windows XP ausgeführt, dann wird das Manifest ignoriert.
Aktivieren von Visual Styles
Es stehen dem Programmierer zwei Möglichkeiten zur Verfügung, die Manifestdatei zum Einsatz zu bringen. Normalerweise wird wohl eher die zweite der beschriebenen Methoden mit den Ressourcendateien den Vorzug bekommen, aber auch die Methode mit der separaten Datei kann sich in einigen Fällen als nützlich erweisen.
Manifest als separate Datei
Bei dieser Möglichkeit reicht es, die Manifestdatei im Verzeichnis der EXE-Datei auszuliefern. Windows prüft beim Start einer Anwendung, also bei Aufruf der API-Funktion CreateProcess
, ob ein externes Manifest vorhanden ist. Wird eines gefunden, verwendet es Windows, sonst wird geprüft, ob das Manifest eventuell als Ressource in der EXE-Datei enthalten ist. Bei meinen Tests unter Windows XP mußten beim Einsatz einer externen Manifestdatei die angegebenen Informationen zur Version und den Programmnamen nicht zur Gänze mit denen der EXE-Datei übereinstimmen.
Vorteile
Da die in der Manifestdatei angegebenen Daten nicht genau mit jenen der Anwendung übereinstimmen müssen, ist die Verwendung mit Anwendungen, die automatisches Inkrementieren der Versionsnummer benutzen, einfacher. Schlimmstenfalls stehen falsche Versionsinformationen in der Manifestdatei. Außerdem ist leicht, im Nachhinein Anwendungen eine Manifestdatei hinzuzufügen, sofern diese die API-Funktion InitCommonControls
aufrufen.
Beispiel dafür wäre die Entwicklungsumgebung von Visual Basic (VB6.exe
). Will man nun direkt mit Windows XP-Steuerelementen in der Entwicklungsumgebung arbeiten, kann man ein Manifest mit dem Dateinamen VB6.exe.manifest
erstellen und im Anwendungsverzeichnis von Visual Basic ablegen. Die VB6.exe
ruft intern InitCommonControls
auf, deshalb werden auch die Steuerelemente problemlos ins neue Aussehen übernommen. Leider gibt es in der Darstellung der Entwicklungsumgebung einige störende Fehler, so werden die benutzerdefinierten Farben im Farbauswahldialog nicht angezeigt. Es besteht also in vielen Fällen die Möglichkeit, alte Anwendungen zumindest optisch an Windows XP anzupassen.
Weiters könnte man dem Benutzer freistellen, Visual Styles in der Anwendung zu aktivieren. In diesem Fall würde es reichen, entweder eine Manifestdatei automatisch im Anwendungsverzeichnis zu generieren oder auf Wunsch wieder zu löschen. Eleganter wäre es jedoch, auf die entsprechende API-Funktion zurückzugreifen, um Visual Styles wahlweise zu deaktivieren.
Nachteile
Separate Dateien neigen eher dazu, verloren zu gehen oder vom Benutzer irrtümlich gelöscht zu werden. Bei einer Änderung von Dateinamen und -versionen kann es vorkommen, daß die Manifestdatei nicht mehr als zur Anwendung gehörig erkannt wird.
Manifestdatei als Ressource
Damit die Anwendung nicht auf externe Dateien angewiesen ist, kann das Manifest in einer Ressource abgelegt und einkompiliert werden. Dazu muß eine entsprechende Definition in der Ressourcendatei erfolgen. Am Einfachsten geht das durch Manipulation des Ressourcenscripts der Anwendung.
Dazu muß ein Ressourceneintrag vom Ressourcentyp RT_MANIFEST
erstellt werden, bei dem die Manifestdatei mit der Ressourcennummer 1 angegeben wird. Der Ressourcentyp muß im Allgemeinen 24 sein, man kann aber über ein #define
im Ressourcenscript den Ressourcentyp RT_MANIFEST
als 24 definieren oder ihn durch Inkludieren der Headerdatei WinUser.h
verfügbar machen. CREATEPROCESS_MANIFEST_RESOURCE_ID
besitzt den Wert 1 und stammt ebenfalls aus dieser Headerdatei.
Der Einfachheit und Übersichtlichkeit halber wurde das Ressourcenscript für das Beispiel nicht mit Visual C++ erstellt, um nicht unnötige Headerinformationen und Code mit keinerlei Bedeutung für eine Visual-Basic-Anwendung verwalten zu müssen. In die Ressourcendatei sollte der im folgenden Codeausschnitt angegebene Text eingefügt werden:
Danach kann das Ressourcenscript zu einer Ressourcendatei mit der Dateiendung .rc
kompiliert und in das Visual-Basic-Projekt eingebunden werden. Das Kompilieren des Ressourcenscripts kann entweder mit Visual C++ oder über den Befehlszeilencompiler für Ressourcendateien, rc.exe
, erfolgen.
Aus ungeklärtem Grund muß darauf geachtet werden, daß die Länge der Manifestdatei ohne Rest durch 4 teilbar ist. Eventuell müssen Leerzeichen eingefügt werden, damit dies der Fall ist. Weist die Manifestdatei beispielsweise eine Länge von 657 Byte auf, dann kann auf 660 Byte aufgefüllt werden. Wenn die Länge der Datei nicht diesen Vorgaben entspricht, kommt es beim Laden der Anwendung zu einem Fehler.
Vorteile
Es muß keine separate Datei ausgeliefert werden. Rein optisch gesehen ist das die sauberere Methode, da nicht eine unzuordenbare Datei entsteht, das Manifest direkt mit der Anwendung in Zusammenhang steht und nicht verloren gehen kann.
Nachteile
Die im Manifest angegebenen Daten müssen mit jenen der EXE-Datei übereinstimmen, es ist daher erforderlich, vor jedem Kompilieren die Manifestdatei anzupassen, sofern automatisch die Versionsnummer erhöht wird.
Visual Styles und die Common Controls
Um Common Controls im Clientbereich des Formulars Visual Styles zuzuweisen, muß die ComCtl32.dll
in der Version 6 oder höher verwendet werden. Gleich wie bei früheren Versionen dieser Datei kann auch die Version 6 nicht weitergegeben werden, eine Auslieferung mit der Anwendung ist dadurch nicht möglich. Die einzige Möglichkeit, Version 6 zu verwenden, ist der Einsatz eines Betriebsssystem, auf dem sie installiert ist. Windows XP enthält sowohl Version 5 als auch Version 6 der Common Controls. Standardmäßig verwenden Anwendungen die Steuerelemente aus der User32.dll
und die Common Controls aus der ComCtl32.dll
Version 5.
Soll nun eine Anwendung Visual Styles verwenden, muß ein Anwendungsmanifest erstellt werden, das angibt, daß die Version 6 der DLL verwendet werden soll. Das hat nur eine Auswirkung, wenn diese Version zur Verfügung steht. Die Version 6 enthält einige neue Steuerelemente, z. B. das SysLink-Steuerelement, und zahlreiche neue Optionen für die bereits vorhandenen Steuerelemente. Die größte Änderung ist aber, daß das Aussehen von Steuerelementen in einem Fenster je nach gerade eingestellten Visual Styles angepaßt werden kann.
Die Funktion InitCommonControls
Damit die Anwendung auch wirklich die Manifestdatei verwendet, muß die API-Funktion InitCommonControls
aufgerufen werden. Im Folgenden ist die Deklaration dieser Funktion für Visual Basic angegeben. Normalerweise sollte der Aufruf in der Sub Main
oder der Sub Form_Load
(dies funktioniert angeblich manchmal nicht) bzw. Form_Initialize
des Startformulars durchgeführt werden:
Anwendungen, welche die Microsoft Common Controls 5.x verwenden, müssen diesen Aufruf nicht durchführen, da bereits die ActiveX-Komponente dies erledigt, um die Steuerelemente nutzen zu können.
Die Common Controls-ActiveX-Komponente
Da das Erstellen von Steuerelementklassen bzw. das Kapseln der von Windows bereitgestellten Steuerelementklassen und die Verwendung dieser in mit Visual Basic erstellten Anwendungen mit Problemen verbunden ist (Schwierigkeiten beim Setzen der Tabulatorreihenfolge von Steuerelementen, die derartig erstellt wurden), werden mit Visual Basic ActiveX-Komponenten ausgeliefert, welche die Windows Common Controls kapseln. Dabei handelt es sich um eine Umhüllung der vom System bereitgestellten Programmierschnittstellen.
In den Versionen 5 und 6 von Visual Basic werden zwei verschiedene Versionen dieser ActiveX-Steuerelemente angeboten, wenn man von Aktualisierungen durch >Service-Packs absieht. Auch diese Steuerelemente können mit Visual Styles versehen werden. Dies beschränkt sich jedoch auf Version 5 der Komponente, Steuerelemente aus der Version Version 6 können nicht dazu bewegt werden, mit Visual Styles angezeigt zu werden. Es werden sich also alle Programmierer freuen, die ihre Projekte nicht auf die neuere Version aktualisiert haben. Der Grund dafür ist, daß die Version 6 dieser Komponente nicht von der ComCtl32.dll
abhängig ist.
Auch hier ist wieder etwas zu beachten, das, wenn es nicht befolgt wird, dazu führen kann, daß die Anwendung nicht ausgeführt werden kann. Beim Start der Anwendung wird ein Piepton ausgegeben und die Anwendung wird nicht gestartet. Dieser Fehler tritt nur ein, wenn neben den normalen Steuerelementen auch die Common Controls verwendet werden. Tests ergaben, daß dieser Fehler nicht auftritt, wenn sich auf einem Formular ein Steuerelement der Common Controls auf oberster Ebene (Z-Reihenfolge) befindet. Man darf also nicht vergessen, vor der Kompilierung eines dieser Steuerelemente in den Vordergrund zu holen.
Der Umgang mit Visual Styles
Steuerelemente von Visual Styles ausnehmen
Über die Programmierschnittstelle der Visual Styles ist es möglich, Steuerelemente von der Anzeige mit Visual Styles zur Laufzeit auszunehmen oder die Darstellung mit diesen wieder zu aktivieren. Im nachfolgenden Codeausschnitt sind die Deklarationen der erforderlichen Funktionen angegeben. Die Deklarationen wurden so angepaßt, daß die Funktionen mit sprechenden Namen direkt aufgerufen werden können:
Das Aktivieren und Deaktivieren von Visual Styles für eine Schaltfläche mit dem Namen cmdOK
erfolgt dann durch Aufrufe von ActivateWindowTheme
bzw. DeactivateWindowTheme
, wobei im ersten Parameter die Fensterzugriffsnummer der Schaltfläche (cmdOK.hWnd
) übergeben wird und die optionalen Parameter nicht mit Werten belegt werden.
Fenstern andere Stilklassen zuweisen
Stile sind nicht nur für ein spezielles Steuerelement anwendbar, sondern man kann beispielsweise den Stil einer Schaltfläche auch auf ein Formular anwenden. Zu entscheiden, ob dies sinnvoll ist, bleibt dem Leser überlassen. Trotzdem kann dies in einigen Fällen durchaus Sinn haben, so kann man etwa einer Schaltfläche das Aussehen der Schaltflächen einer Werkzeugleiste zuweisen. Um all dies durchführen zu können, steht die Funktion SetWindowTheme
zur Verfügung, die wir bereits vorher in etwas anderer Form kennengelernt haben. Im Folgenden sind deren Deklaration sowie ein Beispielaufruf angegeben, bei dem eine Schaltfläche im Stil einer Schaltfläche aus einer Werkzeugleiste dargestellt wird:
Visual Styles und Regionen
Werden in einem Formular Regionen verwendet, d. h., das Formular wird in einer benutzerdefinierten Form dargestellt, wird das erkannt und Visual Styles werden für dieses Fenster deaktiviert. Windows nimmt in diesem Fall an, daß die korrekte Darstellung vom Besitzer des Formulars, nämlich der Anwendung, übernommen wird.
Probleme von Visual Styles mit Visual Basic
Der Einsatz von Visual Styles in Anwendungen, die mit Visual Basic entwickelt wurden, ist nicht unproblematisch. Es gibt einige Fehler in der Anwendung der Visual Styles, die deren Verwendung und die Benutzerfreundlichkeit der Anwendung einschränken:
- Frame-Steuerelemente auf TabStrip-Steuerelementen:
Der Hintergrund von Frame-Steuerelementen läßt sich nicht transparent machen, weshalb das Plazieren von Frame-Steuerelementen auf den Seiten eines TabStrip-Steuerelements zu einem unschönen Anzeigeresultat führt.
- CommandButton-, OptionButton- und CheckBox-Steuerelemente innerhalb von Frame-Steuerelementen:
Werden CommandButton-, OptionButton- und CheckBox-Steuerelemente in Frame-Steuerelementen plaziert, wird ihr Hintergrund schwarz angezeigt.
- Kurztastenmodus:
Seit Windows 2000 können Fenster zwei Darstellungsarten besitzen; bei der einen werden Kurztasten unterstrichen und Fokusrechtecke angezeigt, bei der anderen ist das nicht der Fall. War es unter Windows 2000 nicht möglich, eine Visual-Basic-Anwendung dazu zu bringen, Kurztasten nicht zu unterstreichen und Fokusrechtecke auszublenden, ist es bei der Verwendung von Visual Styles unter Windows XP genau umgekehrt. Benutzer, die mit der Tastatur arbeiten, haben durch das Fehlen der sichtbaren Zugriffstasten Probleme bei der Bedienung.
Die Beispielanwendung ThemeExplorer
Auf der MSDN-Website gab es ein Programm mit dem Namen ThemeExplorer als Visual-C++-Quellcode zum Herunterladen. Dieses Programm erstellt ein TreeView-Steuerelement, das alle verfügbaren Fensterklassen, deren Teile und Anzeigezustände auflistet. Durch Auswahl kann dann ein Beispiel für diesen Teil des eingestellten Theme angezeigt werden. Ich habe dieses Programm nach Visual Basic 6.0 portiert. Einige Dinge sind der Einfachkeit halber anders implementiert.
Das Programm von Microsoft bezieht den Baum aus einer Headerdatei. In diesem sind die gesamten Zeichenfolgen und Konstantenwerte gespeichert. Bei der Visual-Basic-Anwendung wird die Headerdatei im Anwendungsverzeichnis erwartet, da Informationen zu den Visual Styles zur Laufzeit aus dieser Datei geladen werden. Dieser Unterschied bringt Vor- und Nachteile mit sich; einerseits kann jemand, der nur die fertige Anwendung besitzt, sofern er eine neuere Version der Headerdatei besitzt, diese Datei auswechseln und das Programm weiterhin verwenden. Das funktioniert aber nur, wenn innerhalb der Datei die gleichen syntaktischen Regeln eingehalten werden, wie das bis jetzt der Fall war. So enthält die Headerdatei beispielsweise keine Kommentare von der Form /* … */
. Nachteilig ist, daß das Programm auf das Dateiformat angewiesen ist und kleine Fehler in der Datei dazu führen, daß es nicht mehr funktioniert.
Die Visual-Basic-Anwendung liest beim Start die Klassendefinitionen und weiteren Daten aus der Headerdatei und füllt damit das TreeView-Steuerelement. Danach stehen, wie auch bei der C++-Version, mehrere Methoden zur Verfügung:
- Manuelles Navigieren in der Baumstruktur
- Ansehen eines Rundgangs durch die Baumstruktur
- Ein- und Ausklappen aller Knoten mit einem Befehl
Einerseits kann anhand dieses Werkzeugs gezeigt werden, welche Möglichkeiten Visual Styles bieten, andererseits kann man das Programm als Helferlein beim Entwickeln verwenden, um etwa die richtigen Klassennamen und Einstellungen zum Zeichnen eines Steuerelements in einer Anwendung herauszubekommen.
Schlußwort
Auch wenn Visual Styles eine interessante Möglichkeit bieten, Anwendungen ein besseres optisches Erscheinungsbild zu verleihen, sprechen doch viele Fakten gegen ihren Einsatz in Anwendungen, die mit Visual Basic erstellt wurden. Es wird das Beste sein, bei den bisherigen Anzeigearten zu bleiben, um die Benutzerfreundlichkeit nicht zu beeinträchtigen und auch jenen, die nur mit der Tastatur arbeiten, eine Möglichkeit zu gewähren, einfach und sicher mit den Anwendungen zu arbeiten.
Der Funktionsumfang der UxTheme.dll
ist weitreichender, als hier im Artikel beschrieben wurde. Es gibt beispielsweise zahlreiche Funktionen zum Ermitteln von Informationen über ein Theme und zum Zeichnen von Fensterteilen bzw. Grafiken unter Verwendung vordefinierter Stilelemente. Für jene, die sich genauer für Visual Styles interessieren, sei auf die im Abschnitt „Weiterführende Informationen“ angeführten Dokumente verwiesen.
Weiterführende Informationen
- Visual Styles
Spezifikation von Visual Styles mit Beispielen und Dokumentation der Programmierschnittstelle.
- Using Windows XP Visual Styles
Eine allgemein gehaltene Beschreibung von Visual Styles mit einer Anleitung, wie man sie in eigenen Anwendungen verwenden kann.
Downloads
- Beispielprojekt (
VisualStyles.zip
) Projekt im Visual-Basic-6.0-Format.
- Beispielprojekt (
ThemeExplorer.zip
) Projekt im Visual-Basic-6.0-Format.