ListBox mit Ownerdraw - Style - Wie Background gestalten?
-
Ich habe eine ListBox, bei der ich die Zeilen abwechselnd unterschiedlich färbe. Wenn ich nun nicht so viel Zeilen habe, daß die ListBox gefüllt ist, wird unterhalb der letzten Zeile der Hintergrund weiß.
Wenn ich nun WM_CTLCOLORLISTBOX bearbeite, kann ich einen Brush zurückgeben, so daß der Hintergrund nicht mehr weiß ist. Er bleibt aber einfarbig; ich würde auch unterhalb der letzten gefüllten Zeile die ListBox mit dem abwechselnd farbigen Hintergrund füllen.
Wie komme ich da ran?
Wäre es zB im Sinne des (Windows)Erfinders, wenn ich bei WM_CTLCOLORLISTBOX das ganze Client-Rechteck wie gewünscht bemale und dann 0 zurückgebe?
-
Okay, ich fülle einfach am Ende der Listbox ein paar Zeilen mit " ", so daß für sie auch WM_DRAWITEM ausgeführt wird.
So sieht es im Moment gut aus.
-
Denk' dran, daß ich die Zeilen trotzdem auswählen kann. Wenn ihc z.B. [Ende] drücke, will ich normalerweise auf den letzten Eintrag, nicht auf zehn dahinter. Auch wird der Scrollbar wohl häufiger angezeigt als nötig - spätestens, wenn ich meinen Font umstelle.
In einem ListView kannst Du mit CustomDraw (http://www.codeproject.com/KB/list/lvcustomdraw.aspx) auch den unbenutzten Bereich zeichnen. Das "Streifenmuster" mußt du dann allerdings selbst erstellen, die Höhe einer Zeile bekommst Du aber mit GetItemRect.
Direkt in WM_CTLCOLORLISTBOX wird wahrscheinlich sogar funktionieren, ist aber nicht so gedacht, da würde ich die Finger von lassen.
-
Mhm, die von Dir geschilderten Probleme hab ich nicht, weil ich verwalte, wieviel Einträge in der Liste sind und wieviel mindestens angezeigt werden müssen.
Ich habe ein anderes Problem:
Wenn der Anzeigebereich der Liste 20 Zeilen umfasst, aktuell aber nur 10 gefüllt sind, dann habe ich ja in den Zeilen 11 - 20 leere Strings, damit ich die Aufforderung zum Zeichnen bekomme.
Wenn ich nun eine Zeile hinzufüge, dann muß ich erst die Zeile 11 löschen, damit der Leerstring da verschwindet, dann die hinzuzufügende Zeile an Platz 11 einfügen. Das erzeugt aber jede Menge Zeichenaufforderungen für die Zeilen 11 - 20, so daß die Anwendung aufflackert. WM_SETREDRAW FALSE vor dem Löschen und TRUE nach dem Einfügen hilft leider nicht, wie ich gerade ausprobiert habe.
Da muß was anderes her - vielleicht einfach als Hintergrund (WM_CTLCOLORLISTBOX) für den unteren Rest die Farbe auswählen, die die nächste anzufügende Zeile bekäme, ich muß mir das mal überlegen.Edit: Wobei mir gerade so einfällt, daß das Löschen vor dem Einfügen wohl überflüssig ist, mal sehen, vielleicht bringt's was, wenn ich das weglasse ...
-
Ich komm irgendwie nicht klar ...
Ich hab noch mal von vorne begonnen, mit einer einfachen ownerdrawn Listbox (mit LBS_HASSTRINGS).
Dabei fällt mir folgendes auf:
Wenn ich nur ein paar Zeilen in der Box habe, so daß noch ein großer Teil der Listbox weiß bleibt, und nun via LB_ADDSTRING eine Zeile hinzufüge, dann bekomme ich nicht nur für die neue hinzugefügte Zeile eine WM_DRAWITEM - Message, sondern auch für alle bereits vorhandenen. Ich denke, daher rührt auch immer ein kurzes Aufflackern.
Meiner Meinung nach gibt es keinen Grund, die vorhandenen Zeilen noch mal zu malen; deshalb verstehe ich nicht, warum Windows mir diese Messages sendet, es sei denn, ich mach irgendwas Grundlegendes falsch.Meine Frage: Ist es normal, daß ich statt nur einer WM_DRAWITEM - Message so viele bekomme?
-
Bereite den Hintergrund in WM_ERASEBKGND korrekt vor. Dann kannst Du auch das gesamte Fenster mit Deinen Frabstreifen füllen.
Dnan zeichnest Du nur noch in WM_DRAWITEM den Text (BkMode TRansparent)
-
Herzlichen Dank! Das war der entscheidende Tip!
-
Jetzt ist doch noch ein Problem aufgetaucht.
Bisher habe ich zu Testzwecken immer sofort Einträge in die ListBox gemacht. Damit läuft alles wie gewünscht.
Wenn die ListBox aber leer ist oder im Programmverlauf geleert wird, ist der Hintergrund wieder weiß.Der Code für WM_ERASEBKGND wird zwar korrekt durchlaufen/ausgeführt, aber irgendwie wird hinterher alles wieder gelöscht - ich kann leider nicht rausfinden, wodurch das geschieht.
Was mir noch aufgefallen ist, obwohl ich den Hintergrund ja selber male und danach 1 (eins) zurückgebe, wird noch WM_CTLCOLORLISTBOX an das Parent gesendet - eigentlich soll doch im Normalfall damit der Hintergrund bearbeitet werden?
Ich denke allerdings nicht, daß das der Grund für das oben geschilderte Verhalten ist, denn die Message kommt auch, wenn die Box Einträge enthält, trotzdem sieht es dann aus, wie gewünscht.
-
Und bekommst Du eine WM_DRAWITEM Nachricht wenn die Box leer ist?
-
Nö, bei leerer Box kriege ich Erasebkgnd und Ctlcolorlistbox, wenn ein Eintrag drin ist, auch, aber im Anschluß daran WM_DRAWITEM.
Aber jetzt wird's komisch:
Wenn ich testweise nach WM_DRAWITEM sofort, ohne irgendwas zu machen, mit return 1 zurückkehre, erhalte ich logischerweise keinen Eintrag angezeigt, aber mein Hintergrund sieht aus wie gewünscht ...... als wenn Windows entscheidet: entweder WM_DRAWITEM senden, oder aber Hintergrund löschen ...
Wenn ich aber auf WM_CTLCOLORLISTBOX einen grauen Brush zurückgebe, dann bleibt der Hintergrund grau, wird also nicht mit weiß gelöscht, wenn die Box leer ist.
Ist dagegen ein Eintrag da, wirkt sich die Reaktion auf WM_CTLCOLORLISTBOX nicht aus, der Hintergrund bleibt wie gewünscht und in WM_ERASEBKGND vorbereitet ...