Die Community zu .NET und Classic VB.
Menü

WinXP-Styles

 von 

Übersicht 

Dieser Artikel betrifft nur die Entwicklung von Anwendungen für Windows XP und höhere Versionen. 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.

Update: Als ergänzenden Artikel finden Sie bei uns auch eine Kolumne zu diesem Thema.

Mit freundlichen Grüßen
Herfried Karl Wagner

Einführung  

Windows XP Visual Styles

Windows XP (Whistler) brachte neben den bereits bestehenden Desktop-Schemas, den Themes, auch 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, die des Non-Client-Bereichs, das sind Rahmen und Titelleiste, und die des Client-Bereichs, den Steuerelementen auf dem Formular.


Abbildung 1: Anwendung ohne Visual Styles

Microsoft hat zum Zeitpunkt des Entstehens dieses Dokuments erst unzureichende Spezifikationen der Visual Styles unter Windows XP sowie der dahinterliegenden API in der uxthemes.dll zur Verfügung gestellt. Die Informationen können unter Using Windows XP Visual Styles abgerufen werden. Sobald genauere Informationen erhältlich sind, werden wir uns nach Möglichkeit in einem weiteren Artikel dem uxThemes-API annehmen.


Abbildung 2: Die selbe Anwendung mit Visual Styles

Themes und Visual Styles

Für das Verständnis der folgenden Kapitel ist es wichtig, dass 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 vom Windows unterstützten Desktopschemas. Sie bestehen aus einem Farbschema für Fenster, Schrifteinstellungen, Mauszeiger und Icons und einem Hintergrundbild sowie Sounds. Mit Themes war es jedoch nicht möglich, Einfluss auf die Darstellung von Steuerelementen zu nehmen, abgesehen von Farbe und Schrift. Die Dateien, in denen Themes enthalten sind, tragen die Dateiendung .theme und können auch von ISVs (Independent Software Vendors) erstellt und vertrieben werden.

Visual Styles

Visual Styles wurden erstmals mit Windows XP eingeführt, das eine völlig neue GUI-Rendering-Engine mit sich bringt. Diese Engine ermöglicht es, Visual Styles mit herkömmlichen Anwendungen zu verwenden. Im Gegensatz zu Themes kann dadurch auch die Form und Darstellungsart der Steuerelemente beeinflusst werden. Mit dieser Engine wurde auch gleich eine umfangreiche API eingeführt, um grösstmögliche Dynamik in die Darstellung von Anwendungsoberflächen anzubieten. Bei benutzerdefinierten Steuerelementen kann der Programmierer via API 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 Buttons einer Werkzeugleiste angezeigt werden. In Windows XP werden die Styles des gerade installierten Visual Styles automatisch auf die Elemente des Non-Client-Bereichs von Formularen angewendet, die Anwendung auf den Client-Bereich der Formulare muss über ein Manifest erwirkt werden.

Common Controls

Um Common Controls im Client-Bereich des Formulars Visual Styles zuzuweisen, muss 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 dieser DLL nicht weitergegeben werden, eine Auslieferung mit der Anwendung ist dadurch nicht möglich. Die einzige Möglichkeit, Version 6 zu verwenden, ist es, ein Betriebsssystem zu einzusetzen, auf der sie installiert ist. Windows XP enthält sowohl Version 5 als auch Version 6 der DLL. Standardmässig 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, muss ein Anwendungsmanifest erstellt werden, das angibt, dass die Version 6 der DLL verwendet werden soll, sofern diese 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össte Änderung ist aber, dass das Aussehen von Steuerelementen in einem Fenster je nach gerade eingestelltem Visual Style angepasst werden kann.

Manifests  

Die Verwendung von Manifests, bei denen es sich um spezielle XML-Dateien handelt, ist vielseitig. In Zukunft wird XML eine wichtige Rolle speielen, wie man bereits in VB.net erkennen kann. Für diesen Artikel wird aber nur die Anwendung in Bezug auf die Windows XP Visual Styles herausgegriffen. Manifests können mit einem Texteditor wie z.B. Notepad oder aber auch mit einem beliebigen XML-Editor erstellt werden. Im Normalfall wird man aber auf eine Vorlage, wie den folgenden Code, zurückgreifen und nicht das ganze XML-Dokument neu schreiben.

Im Weiteren gehen wir davon aus, dass unsere kompilierte Anwendung in der Datei MyApp.exe vorliegt bzw. vorliegen soll. Um den neuen Darstellungsmodus nutzen zu können, muss eine Plain-Text-Datei erstellt werden, die aussieht, wie im folgenden Codebeispiel angegeben.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="X86"
    name="MyCompany.MyProduct.MyApp"
    type="win32"
  />
  <description>Application description text goes here!</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        processorArchitecture="X86"
        publicKeyToken="6595b64144ccf1df"
        language="*"
      />
    </dependentAssembly>
  </dependency>
</assembly>

Anstelle von "1.0.0.0" beim Attribut version des assemblyIdentity-Tags muss die Programmversion, für die dieses Manifest erstellt wird, angegeben werden; der Wert "MyCompany.MyProduct.MyApp" des Attributs name muss 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 über eine Ressourcendatei eingebunden werden, müssen die Versionsinformationen und sonstigen Informationen im Manifest mit denen der EXE-Datei übereinstimmen, andernfalls wird beim Starten des Programms eine Fehlermeldung ausgegeben. Ausserdem müssen einige der Angaben nicht genau gemacht werden, bei processorArchitecture würde auch ein "*" als Wert genügen.

Die Datei muss unter dem Namen MyApp.exe.manifest im Anwendungsverzeichnis bzw. Quellverzeichnis des Ressourcenscripts abgespeichert werden.

Verwendung mit VB  

Es stehen dem Programmierer zwei Möglichkeiten zur Verfügung, das Manifest-XML 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.

Separate Datei

Hier reicht es, die Manifest-Datei 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 in die EXE einkompiliert wurde. Bei meinen Tests unter Windows XP mussten beim Einsatz einer externen Manifestdatei die angegebenen Informationen zur Version und den Programmnamen nicht ganz mit denen der EXE-Datei übereinstimmen.

Vorteile

Da die Informationen nicht genau übereinstimmen müssen, ist die Verwendung mit Anwendungen, die automatisches Inkrementieren der Buildnummer benutzen, bedeutend einfacher, schlimmstenfalls stehen falsche Versionsinformationen in der Manifestdatei.

Es ist leicht, im Nachhinein Anwendungen eine Manifestdatei hinzuzufügen, sofern diese die API-Funktion InitCommonControls aufrufen. Beispiel dafür wäre die VB-IDE, die in der VB6.exe implementiert ist. 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 übernommen. Leider gibt es in der Darstellung der IDE einige kleine Fehler, so werden z.B. die benutzerdefinierten Farben im Farbwahl-Dialog der IDE nicht angezeigt. Es besteht also in vielen Fällen die Möglichkeit, alte Anwendungen zumindest optisch auf Windows XP nachzurüsten.

Man könnte dem Benutzer auch freistellen, Windows XP-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 aber, auf die jeweilige API-Funktion zurückzugreifen.

Nachteile

Separate Dateien neigen dazu, verloren zu gehen oder vom Benutzer irrtümlich gelöscht zu werden. Es könnte auch sein, dass sich der Dateiname irrtümlicherweise verändert und damit das Manifest nicht mehr als zur EXE gehörig erkannt wird.

Ressourcendatei

Damit die Anwendung nicht auf externe Dateien angewiesen ist, kann das Manifest auch in einer Ressourcendatei abgelegt und einkompiliert werden. Dazu muss eine entsprechende Definition in der Ressourcendatei erfolgen. Am besten geht das durch Manipulation des Ressourcenscripts der Anwendung. Inoffiziellen Informationen Microsofts zufolge muss ein Ressourceneintrag vom Ressourcentyp RT_MANIFEST erstellt werden, bei dem die Manifestdatei mit der Ressourcennummer 1 angegeben wird. Der Ressourcentyp muss im Allgemeinen 24 sein, man kann aber auch über ein #define im Ressourcenscript den Ressourcentyp RT_MANIFEST als 24 definieren. Der Einfachheit und Übersichtlichkeit halber wurde das Ressourcenscript für das Beispiel nicht mit Microsoft Visual C++ erstellt, um nicht unnötige Header-Informationen und Code verwalten zu müssen, die für eine VB-Anwendung keinerlei Bedeutung haben. In die Ressourcendatei sollte der im folgenden Codeausschnitt angegebene Text eingefügt werden.

//////////////////////////////////////////////////////////////////////_
///////
//
// 24
//

1                       24                      "MyApp.exe.manifest"

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 Microsoft Visual C++ oder aber über den Befehlszeilencompiler für Ressourcendateien, rc.exe, durchgeführt werden.

Vorteile

Es muss keine separate Datei ausgeliefert werden. Rein optisch gesehen ist das die sauberere Methode, da nicht eine unzuordenbare Datei entsteht, sondern das Manifest direkt mit der EXE in Zusammenhang steht und nicht verloren gehen kann.

Nachteile

Die im Manifest angegebenen Daten müssen mit denen von der EXE übereinstimmen, es ist daher erforderlich, vor jedem Buildvorgang die Manifestdatei anzupassen, sofern automatisch die Buildnummer erhöht wird.

Überlegungen

Hier stellen sich dem Leser wahrscheinlich einige Fragen.

Wie sieht es z.B. mit Anwendungen aus, die ein Manifest verwenden und unter früheren Windows-Versionen ausgeführt werden? Die Antwort ist mehr als trivial, es werden die Angaben schlicht und einfach ignoriert.

Warum prüft Windows zuerst, ob ein Manifest in einer externen Datei vorhanden ist? Hier kann man nur taktische Überlegungen machen. Wahrscheinlich soll es in viel späteren Versionen von Windows dieses Feature nicht mehr geben, es dient nur zum Übergang.

InitCommonControls

Damit die Anwendung auch wirklich die Manifestdatei verwendet, muss die API-Funktion InitCommonControls aufgerufen werden. Im Folgenden ist die Deklaration dieser Funktion angegeben. Normalerweise sollte der Aufruf in der Sub Main oder der Sub Form_Load bzw. Form_Initialize des Startformulars durchgeführt werden.

Private Declare Sub InitCommonControls Lib "comctl32" ()

Der Aufruf könnte dann wie folgt aussehen.

Private Sub Form_Load()
    Call InitCommonControls
    .
    .
    .
End Sub

Common Controls ActiveX

Da die Verwendung von Steuerelementen mit API-Funktionen und Subclassing in Visual Basic nur schwer möglich ist, man denke hier nur an das Problem mit der Tabulator-Reihenfolge bei Steuerelementen, die über APIs erstellt wurden, werden von Microsoft mit Visual Basic auch ActiveX-Komponenten ausgeliefert, die die Windows Common Controls kapseln. Dabei handelt es sich um nichts anderes als um eine Umhüllung der darunterliegenden API durch UserControls. Der Programmierer, in diesem Fall der Benutzer dieser Steuerelemente, sieht diese als Black-Box und muss sich nicht mit den Details der Implementierung der Komponente abgeben.

In den Versionen 5 und 6 von Visual Basic werden zwei verschiedene Versionen dieser ActiveX-Steuerelemente angeboten, abgesehen von einigen Updates über Service-Packs. Auch diese Steuerelemente können mit den neuen Visual Styles eingesetzt werden, allerdings nur, wenn die Version 5 der ActiveX-Komponente benutzt werden. Mit der Version 6 funktioniert das nicht, es werden sich also alle Programmierer freuen, die ihre Projekte nicht auf die neuere Version upgedatet haben. Der Grund dafür ist, dass die Version 6 dieser Komponente nicht von der ComCtl32.dll abhängig ist, weshalb auch ein Manifest nichts ändert.

Auch hier ist wieder etwas wichtiges zu beachten, das, wenn es nicht befolgt wird, dazu führen kann, dass die Anwendung nicht ausgeführt werden kann. Beim Start der Anwendung wird ein Beep ausgegeben und die Anwendung wird beendet. Dieser Fehler tritt nur ein, wenn neben den normalen Steuerelementen auch die Common Controls verwendet werden. Nachforschungen ergaben, dass 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.

Steuerelement von Visual Styles ausnehmen

Über das hinter den Visual Styles liegende API ist es möglich, Steuerelemente von der Anzeige mit den neuen Styles zur Laufzeit auszunehmen oder die Darstellung mit diesen wieder zu aktivieren. Im nachfolgenden Codeausschnitt sind die Deklarationen der erforderlichen API-Funktionen angegeben. Damit man sich eine eigene VB-Funktion ersparen kann, wurden die Deklarationen für die entsprechende Funktion adaptiert.

Private Declare Function ActivateWindowTheme Lib _
"uxtheme" Alias "SetWindowTheme" ( _
    ByVal hWnd As Long, _
    Optional ByVal pszSubAppName As Long = 0, _
    Optional ByVal pszSubIdList As Long = 0 _
) As Long
Private Declare Function DeactivateWindowTheme Lib _
"uxtheme" Alias "SetWindowTheme" ( _
    ByVal hWnd As Long, _
    Optional ByRef pszSubAppName As String = " ", _
    Optional ByRef pszSubIdList As String = " " _
) As Long

Wollen wir nun den Button cmdOK trotz Manifest in herkömmlicher Art und Weise darstellen, muss folgender Aufruf erfolgen.

Call DeactivateWindowTheme(cmdOK.hWnd)

Das Aktivieren funktioniert ähnlich über die andere Version der API-Funktion, wie das folgende Beispiel zeigt.

Call ActivateWindowTheme(cmdOK.hWnd)

Visual Styles und Regions

Werden in einem Formular Regions verwendet, d.h. das Formular wird in einer benutzerdefinierten Form dargestellt, wird das von der Rendering-Engine erkannt und der Standard-Modus für dieses Fenster aktiviert. Windows nimmt in diesem Fall an, dass die korrekte Darstellung vom Besitzer des Formulars, der Anwendung, übernommen wird.

Fehler unter Visual Basic

Der Einsatz von Visual Styles bei Anwendungen, die mit Visual Basic geschrieben wurden, ist nicht unproblematisch, da es einige Fehler gibt, die deren Verwendung und die Benutzerfreundlichkeit einschränken.

  • Frames auf TabStrips
    Der Hintergrund von Frames lässt sich nicht transparent machen, weshalb das Plazieren von Frames auf den Laschen zu einem unschönen Anzeigeresultat führt.
  • Buttons und OptionButtons in Frames
    Werden Buttons oder OptionButtons in Frames plaziert, wird deren Hintergrund schwarz angezeigt.
  • Kurztasten-Modus
    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, die Kurztasten nicht zu unterstreichen und Fokusrechtecke auszublenden, ist dies bei der Verwendung von Visual Styles unter Windows XP genau umgekehrt. Dadurch können Benutzer, die nur mit der Tastatur arbeiten, Probleme haben, da die Zugriffstasten nicht sichtbar sind.

Schlusswort  

Auch wenn Visual Styles eine interessante Möglichkeit, Anwendungen ein besseres optisches Erscheinungsbild zu geben, sprechen doch sehr viele Fakten gegen ihren Einsatz. Es wird also 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 mit dem Programm zu interagieren.

Tutorial und Beispielprojekt als Download [42400 Bytes]

Ihre Meinung  

Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.