Einfärben von ListBox und ListView controls
Die Aufgabenstellung selbst erscheint relativ simpel: Man möchte in einer ListBox bzw. in einem ListView einen Eintrag mit einer Hintergrundfarbe hinterlegen, um diesen z.B. besonders hervorzuheben.
Leider unterscheiden sich die Methoden hierfür bei ListBox und ListView erheblich.
Beim ListView ist das Ganze relativ einfach zu lösen:
Das ListView sendet eine WM_NOTIFY
Message an den Parent-Dialog, der das Control beinhaltet. Als lParam
erhält man eine LPNMLISTVIEW
Struktur, welche im hdr
Member wiederum einen Member code
enthält, welcher den eigentlichen Notification code angibt. Für das ListView ist hier für uns der Code NM_CUSTOMDRAW
interessant. Durch Erhalt der Message ist sichergestellt, dass es sich bei der in lParam an uns übergebene Struktur um eine NMLVCUSTOMDRAW
Struktur handelt. In deren Member nmcd
befindet sich die zur Message zugehörige Struktur NMCUSTOMDRAW
, welche wiederum den Member dwDrawStage
beinhaltet, der uns über den aktuellen Zeichnungsstatus informiert. Erhalten wir hier die Nachricht CDDS_PREPAINT
, wissen wir, dass das Zeichnen des ListViews gerade beginnt. An dieser Stelle müssen wir nun unser Interesse an den Notifications für die einzelnen Items der Liste anmelden. Das geht ganz einfach mit folgendem Kommando:
SetWindowLong (hWnd, DWL_MSGRESULT, CDRF_NOTIFYITEMDRAW);
Mit besagtem Kommando teilen wir dem Notifier unsere Antwort mit, die da eben lautet CDRF_NOTIFYITEMDRAW
.
Nun können wir den Drawstage pro Item mit der Nachricht CDDS_ITEMPREPAINT
dispatchen.
An dieser Stelle können wir nun auf den Zeichenprozess einfluss nehmen, indem wir die Members de rStruktur in lParam entsprechend modifizieren und den Notifier diese Änderung zur Kenntnis bringen.
Hier ein Beispiel, welches den Text rot färbt:
lplvcd->clrText = RGB(255,0,0);
SetWindowLong (hWnd, DWL_MSGRESULT, CDRF_NEWFONT);
Den kompletten Source zur besseren Übersicht gibt’s hier
Bei der ListBox ist das Ganze leider nicht ganz so einfach. Diese bietet nämlich leider keinen so bequemen WM_NOTIFY
-Mechanismus. Stattdessen muss man sich hier mit einem owner-Drawn control aushelfen, was natürlich einiges an Arbeit mit sich bringt. Daher sollte man als Style für das Control LBS_OWNERDRAWFIXED
verwenden. Ein LBS_HASSTRINGS
könnte sich auch als nützlich erweisen.
Bei einem Owner-Drawn control erhält der Parent eine WM_DRAWITEM
Notification, welche entpsrechend behandelt werden muss.
Als lParam erhält man ein LPDRAWITEMSTRUCT
, welches den Member itemAction
hat. Interessant sind hierbei die Actions ODA_SELECT
und ODA_DRAWENTIRE
.
Ein Zeichnen des ListBox-Eintrags im entsprehcenden Style erreicht man hier mittels Modifikation des device contexts, welcher sich im hDC
Member des DRAWITEMSTRUCT
s befinder.
Je nach itemState
Member sollte man die Vordergrund- und Hintergrundfarbe des Eintrags entsprechend setzen. Um die Systemfarben zu ermitteln, empfiehlt sich der Einsatz der Funktion GetSysColor
.Mit FillRect
die Auswahlmarkierung erzeugen und mit TextOut
schließlich den Text zeichnen. Also ein relativ hoher Aufwand, um nur die Farbe des Textes zu ändern.
Ein Codebeispiel gibt’s wie immer hier.