Einfärben von ListBox und ListView controls

By dose | March 15, 2007
Under: technical stuff, Uncategorized

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 DRAWITEMSTRUCTs 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.

Leave a Comment

Name:

E-Mail :

Subscribe :
Website :

Comments :