Die Sortierrichtung im Spaltenkopf anzeigen


Als kleine Ergänzung zur Sortierfunktion wollen wir noch die aktuelle Richtung im Spaltenkopf der List-View anzeigen. Dazu ist zu sagen, dass wir ein wenig auf das Header-Control eingehen müssen, zu dem es kein Tutorial gibt. Wir beschränken uns aber auf das Wesentliche.

Außerdem ist zu sagen, dass wir ab Version 6.0 der Common Controls Bitmaps aus dem System nutzen können. Da aber das Programm evtl. auch auf älteren Windows-Versionen laufen soll, nehmen wir also zunächst unser bevorzugtes Zeichenprogramm (Paint reicht vollkommen!) und gestalten eine Bitmap mit zwei Pfeilen gleicher Breite und Höhe für die Richtungen Aufwärts und Abwärts.

Um herauszufinden, ob wir diese Bitmap überhaupt benötigen, holen wir uns das Handle auf den Header der List-View und senden die Nachricht "CCM_GETVERSION":

hHeader    := ListView_GetHeader(hLV);
iHeaderVer := SendMessage(hHeader,CCM_GETVERSION,0,0);

Ist der Rückgabewert größer oder gleich 6, können wir auf unsere selbst gezeichnete Grafik verzichten. Wir wollen aber davon ausgehen, dass der Wert kleiner als 6 ist. In dem Fall laden wir die Grafik als Imageliste aus den Ressourcen des Programms:

hSortImg := ImageList_LoadBitmap(hInstance,MAKEINTRESOURCE(BMP_SORTBMP),7,1,$00c0c0c0);

und übergeben sie an das Header-Control:

Header_SetImageList(hHeader,hSortImg);

Von besonderem Interesse ist nach meiner Ansicht der oben rot markierte Wert $00c0c0c0. Dieser Wert ergibt sich aus der Hintergrundfarbe meines Beispielbildes: Hellgrau. Durch die Angabe dieses Wertes wird der Hintergrund des Bildes transparent dargestellt. Würden Sie stattdessen einen anderen Wert benutzen, könnten Sie den hellgrauen Hintergrund sehen. Wenn Sie eine andere Hintergrundfarbe in Ihren Grafiken verwenden, dann müssen Sie natürlich deren Wert angeben!


Bitmap aus dem Header entfernen

Auch wenn es sich komisch anhört, zuerst wollen wir eine Grafik aus dem Header entfernen. Das hat nämlich mit unserer Sortierung zu tun. Klicken wir auf den Spaltenkopf, wird ermittelt, ob es sich dabei um eine andere Spalte handelt als bei der letzten Sortierung. Ist das der Fall, dann muss natürlich auch die Bitmap entfernt werden.

Das geht relativ einfach mit dem Makro "Header_GetItem", mit dem wir zunächst alle aktuellen Daten der Spalte ermitteln. Uns interessieren dabei fast alle Parameter, weil wir zwar die Angaben zum Image entfernen, die übrigen Einstellungen aber nicht ändern wollen. Darum sieht die Maske des THDItem-Records so aus:

hi.Mask       := HDI_BITMAP or HDI_FORMAT or HDI_IMAGE or HDI_ORDER or
  HDI_TEXT or HDI_WIDTH;

Damit der Spaltentext auch gesichert werden kann, übergeben wir noch einen Puffer und dessen Größe

hi.pszText    := buf;
hi.cchTextMax := sizeof(buf);

und rufen dann "Header_GetItem" auf:

Header_GetItem(hwndHeader,iIdx,hi);

Da uns die Werte an sich aber nicht interessieren, widmen wir uns lediglich der fmt-Membervariablen und entfernen alles, was irgendwie mit Bitmaps zu tun hat:

hi.fmt        := hi.fmt and not HDF_SORTUP  // Pfeil-nach-oben  (v6.0)
  and not HDF_SORTDOWN                      // Pfeil-nach-unten (v6.0)
  and not HDF_BITMAP_ON_RIGHT               // Bitmap-Position

In den beiden ersten Zeilen sehen Sie die Angaben HDF_SORTUP und HDF_SORTDOWN, die eigentlich nur für neuere Windows-Versionen interessant sind. Aber wir sparen uns damit eine Versionsprüfung. :o)
Das so veränderte Item geben wir nun mit der Funktion "Header_SetItem" an das Header-Control zurück

Header_SetItem(hwndHeader,iIdx,hi);

und haben eine evtl. vorhandene Grafik damit entfernt.


Bitmaps im Header anzeigen

Das Anzeigen einer Grafik entspricht prinzipiell dem eben gezeigten Weg. Zunächst ermitteln wir die aktuellen Daten der Header-Spalte mit "Header_GetItem". Wenn wir diese Daten haben, dann ergänzen wir in der Formatvariablen fmt zunächst, dass wir die Grafik rechts vom Spaltentext anzeigen lassen wollen:

hi.fmt        := hi.fmt or HDF_BITMAP_ON_RIGHT;

Die Grafik selbst wird versionsabhängig angezeigt. Wenn, wie erwähnt, unsere Windows-Version aktuell genug ist und ein Header-Control der Version 6.0 oder aktueller enthält, dann können wir Bitmaps benutzen, die sich bereits im System befinden. In dem Fall brauchen wir unsere Imageliste nicht, sondern wir verwenden das Flag HDF_SORTUP oder HDF_SORTDOWN (abhängig von der Sortierrichtung):

if(iHeaderVer >= 6) then hi.fmt := hi.fmt or fSortBmp[SortOrder=0]

"fSortBmp" ist dabei ein boolean-Array, das die beiden Flags enthält. Ist die Bedingung erfüllt (SortOrder = 0), dann wird HDF_SORTUP verwendet, andernfalls HDF_SORTDOWN. Bei einer älteren Windows-Version greifen wir stattdessen auf unsere Imageliste zu und setzen zunächst das Flag HDF_IMAGE. Damit wird das Header-Control angewiesen, eine Grafik aus der anfangs zugewiesenen Imageliste zu verwenden.

  else begin
    hi.fmt    := hi.fmt or HDF_IMAGE;

Im Fall unseres Beispiels kommt uns zugute, dass wir a) nur in zwei Richtungen sortieren (aufsteigend und absteigend), und dass b) die Imageliste des Headers auch nur zwei Bitmaps enthält. Und weil die Variable "SortOrder" nur die Werte Null und Eins annehmen kann, können wir sie einfach als Index für das gewünschte Bild angeben:

    hi.iImage := SortOrder;
  end;

Mit "Header_SetItem" übergeben wir dem Header-Control die geänderten Einstellungen, und -voilą- erscheint der Pfeil im Spaltenkopf der List-View: