Die Optik von Common Controls

Raymond Chen hat einige schöne Artikel zum Thema Common Controls verfasst.

Doch wie nutzt man die Windows Common Controls nun am Besten?


Manifest

Am Anfang hat man uns beigebracht, man müsse einfach eine MYPROGRAM.EXE.manifest Datei mit folgendem Inhalt erstellen

 1<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
 2<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
 3  <assemblyIdentity
 4    version="1.0.0.0"
 5    processorArchitecture="*"
 6    name="CompanyName.ProductName.YourApplication"
 7    type="win32"
 8  />
 9  <description>Your application description here.</description>
10  <dependency>
11    <dependentAssembly>
12      <assemblyIdentity
13        type="win32"
14        name="Microsoft.Windows.Common-Controls"
15        version="6.0.0.0"
16        processorArchitecture="*"
17        publicKeyToken="6595b64144ccf1df"
18        language="*"
19      />
20    </dependentAssembly>
21  </dependency>
22</assembly>

und neben die EXE legen. Windows macht den Rest. Das war zu Zeiten von Windows XP auch die einzige Möglichkeit, weil Programme noch mit dem klassischen VB6 oder VC6 geschrieben wurden und es keine Tools gab um “Manifest” Dateien für Programme zu erstellen.

Erst Visual Studio 2002 brachte Werkzeuge für das Erstellen von Programmen mit, in denen das Manifest in der EXE selbst untergebracht war.
Nun erstellt man .manifest Dateien und lässt sie vom Resourcen Compiler in die EXE mitaufnehmen. Und wenn wir uns so an die Common-Controls 6.0 binden, erhalten wir neben “smootheren” Listviews und Treeviews auch neue Features wie z.B. die Tile-Ansicht (Mehrzeilige Listeneinträge in einem Block).

Statische Bibliotheken

Was mich bei der .manifest Datei ein bisschen “ankotzt”, ist die Tatsache, dass ich UI-Special-Features in einer Bibliothek habe und das EXE-Projekt dann wegen der UI-Lib “angepasst” werden muss, damit es das manifest in sich aufnimmt. Ist die UI eine dynamische Bibliothek, könnte man das Manifest dort anbringen, aber bei statischen Bibliotheken geht das nicht.

Außer …

Man kann jedoch ein klassisches Microsoft-C Features nutzen, nämlich #pragma comment(linker, "...") und dort dem Linker ein paar Zusatzanweisungen geben. Statische Bibliotheken geben diese Info auf diese Weise an das EXE-Projekt weiter und wir können so einen Manifestinhalt per Linker-Option anfügen.

Das sieht dann etwa so aus: #pragma comment(linker, "\"/manifestdependency:type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

Fazit

Treeview und Listview sind neben Tabs und Toolbars nach wie vor die häufigsten UI Elemente aus den “Common Controls”, ohne die ich keine UI bauen könnte. (Buttons und Textfelder sind eben nicht genug.)
Dass die Elemente aus Kompatibilitätsgründen nur dann das “aktuelle” Windows Design erhalten, wenn sie per Manifest dafür freigeschaltet sind, ist ärgerlich. Das liegt vor allem an jenen Entwicklern, die sich unsauber an nicht dokumentierte Features geheftet haben und Microsoft dann deren Versagen auszugleichen versuchte.

Wie auch immer … mit der pragma Lösung kann ich leben. Natürlich steht dieses Feature nicht unter anderen Compilern zur Verfügung, aber ich erstelle offizielle Windows Programme nur mit MSVC. Den MinGW nutze ich nur zur Verifizierung, dass alles portabel implementiert ist und da kann man mal auf Manifeste verzichten.

Von daher: Ein Hoch auf pragma
!Aber nur hier in diesem Sondernfall, ansonsten ist pragma meist böse!


Wenn sich eine triviale Erkenntnis mit Dummheit in der Interpretation paart, dann gibt es in der Regel Kollateralschäden in der Anwendung.
frei zitiert nach A. Van der Bellen
... also dann paaren wir mal eine komplexe Erkenntnis mit Klugheit in der Interpretation!