An für sich ist das nicht kompliziert, eher nur malen nach Zahlen, d. h. du hast deine Canvas auf der du zeichnest. Das ist fast genauso wie zeichnen auf dem Canvas des Formulars, einer Bitmap oder Image. Allerdings müssen hier vor allem drei Punkte beachtet werden.
Der erste ist, dass du schon auf der richtigen Canvas zeichnen mußt. Als Parameter bekommst du nur
Control: TWinControl
und nicht
TListBox
. Du mußt
Control
also sagen, dass es eine TListbox ist. Das machst du mit
with (Control as TListbox) do
Delphi-Quellcode:
procedure TForm1.ListBox1DrawItem(Control: TWinControl;
Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin
with (Control as TListbox) do
begin
...
end;
end;
Ob du nun mit With arbeitest (mußt du nicht, du kannst aber) oder anders, z. B. so
Delphi-Quellcode:
procedure TForm1.ListBox1DrawItem(Control: TWinControl;
Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
MyListBox: TListBox;
begin
MyListBox := (Control as TListbox);
MyListBox.Canvas. ...
ist eigentlich egal. Beides geht.
Der zweite wichtige Punkt ist, dass du eigentlich auf der ganzen ListBox Canvas zeichnen kannst, aber das willst du ja nicht. Du willst nur auf dem kleinem Streifen des Items zeichnen. Dazu bekommst du den Parameter
Rect: TRect
. Jedes Item hat seinen eigenen Rect Bereich. Du mußt beim Zeichnen also in dem Bereich bleiben.
Die Prozedur
OnDrawItem
funktioniert so: sie wird so oft aufgerufen wie viele Items sichtbar sind. Sind fünf Items sichtbar, wird die Prozedur auch fünf mal aufgerufen. Nur bekommst du jedes Mal passend zu dem Item andere
Rect
Werte. Willst du also an Koordinate 1 und 1 einen Punkt setzten, dann nicht
MyListBox.Canvas.Pixels[1, 1] := clBlack
, sondern
MyListBox.Canvas.Pixels[Rect.Left + 1, Rect.Top + 1] := clBlack
. Du mußt also immer im Verhältnis zu Rect zeichnen. Läßt du es weg, zeichnest du alles oben in der ListBox.
Nur bedenke, man kann auch drüberzeichen in das darunterliegende Item. Die Begrenzung nach unten ist
Rect.Bottom
, nach rechts
Rect.Right
. Also immer schön im im Bereich bleiben und es immer wieder überprüfen. Außerdem sollte man bedenken, dass es auch eine Funktion Rect gibt. Die Namenswahl des Parameters ist nicht sonderlich glücklich, aber auch keine Katastrophe. Man muß eben aufpassen. Wenn eine Fehlermeldung kommt, dann sollte men es nur wissen um was es geht.
Der dritte wichtige Punkt ist, dass man die
State: TOwnerDrawState
Parameter betrachten sollte. Denn die sagen einem was für ein Item das aktuelle Item ist. Ist es ein normales Item oder eine der den Fokus besitz oder ist er gerade selektiert.
Delphi-Quellcode:
with (Control as TListbox) do
begin
if odSelected in State then
Canvas.Font.Color := clInactiveCaptionText
else
Canvas.Font.Color := clWindowText;
Das Beispiel fragt ab ob der Item gerade selektiert ist. In diesem Fall ändert sich die Schriftfarbe. Die Hintergrundfarbe ist schon automatisch in Brush.Color eingestellt. Eigentlich mußt du die Textfarbe und Hintergrundfarbe nicht einstellen, da sie schon voreingestellt sind. Das ist nur dann wichtig wenn du deine eigenen Farben wählen willst. Ansonsten bekommst du die Systemfarben voreingestellt.
Wenn man sein eigenes Design wählen will, dann muß man die Hintergrundfarbe ändern, die Schriftfarbe, dann den Focus löschen und durch seinen eigenen ersetzte. Aber das erkläre ich evt. später, sonst verwirrt das alles nur.
Zuletzt noch der Hinweis, dass
Index: Integer
den Index beinhaltet der bei dem Durchlauf gerade gezeichnet wird.