Standardimplementierung für ListView OwnerDraw

8

Ich habe eine ListView , in der ich die Zeichnung optimieren möchte von Elementen (zum Beispiel das Hervorheben bestimmter Strings in Listenansichts-Items), jedoch möchte ich die Art und Weise, wie Elemente angezeigt werden, nicht radikal ändern.

Ich habe OwnerDraw auf true gesetzt und kann Wenn ich versuche, die Standardimplementierung zu verschieben, um den Rest der Listenansicht zu zeichnen, gehen die Dinge schief und ich habe eine Menge grafischer Probleme, die darauf hindeuten, dass Ich bin komplett falsch gelaufen.

Gibt es irgendwo, dass ich sehen kann, was die "Standard" Handler für die DrawItem und DrawSubItem Ereignisse, damit ich mein Verständnis verbessern und meinen Code leichter verändern kann?

Als Referenz hier ist ein Ausschnitt, der zeigt, was ich gerade mache:

%Vor%     
Justin 30.01.2012, 15:36
quelle

5 Antworten

10

Ich habe jetzt nicht die Zeit, eine vollständige Antwort zu schreiben, stattdessen werde ich ein paar kurze Notizen machen und später darauf zurückkommen.

Wie LarsTech sagte, ist das Zeichnen eines Controllers ListView ein Problem - die Klasse .Net ListView ist ein Wrapper um das zugrunde liegende Win32 List View Control und die Fähigkeit zu" Owner Draw "wird von der NM_CUSTOMDRAW Benachrichtigungscode . Daher gibt es keine ".Net-Standardimplementierung" - standardmäßig wird das zugrunde liegende Win32-Steuerelement verwendet.

Um das Leben noch schwieriger zu machen, müssen einige zusätzliche Überlegungen angestellt werden:

  • Wie LarsTech herausstellte, repräsentiert der erste Unterpunkt tatsächlich das übergeordnete Element selbst. Wenn Sie also das Rendering in DrawItem und DrawSubItem behandeln, zeichnen Sie möglicherweise den Inhalt der ersten Zelle zweimal.
  • Es gibt einen Fehler im zugrunde liegenden ListView-Steuerelement (dokumentiert in der Anmerkung zu diese Seite ), was bedeutet, dass ein DrawItem -Ereignis ohne entsprechende DrawSubItem -Ereignisse auftritt, was bedeutet, dass wenn Sie einen Hintergrund im DrawItem -Ereignis zeichnen und dann den Text in DrawSubItem zeichnen Event wird Ihr Artikeltext verschwinden, wenn Sie mit der Maus darüber fahren.
  • Ein Teil des Renderings scheint standardmäßig nicht doppelt gepuffert zu sein
  • Ich habe auch festgestellt, dass die Eigenschaft ItemState nicht zutrifft immer korrekt, zum Beispiel direkt nach der Größenänderung einer Spalte. Folglich habe ich sein Bestes gefunden, mich nicht darauf zu verlassen.
  • Sie müssen auch sicherstellen, dass Ihr Text nicht über mehrere Zeilen verteilt wird, da sonst die oberen paar Pixel der unteren Zeile am unteren Rand der Zelle gerendert werden.
  • Beim Rendern der ersten Zelle muss auch besondere Berücksichtigung gefunden werden, um die zusätzliche Auffüllung zu berücksichtigen, die die systemeigene Listenansicht verwendet.
  • Da das DrawItem -Ereignis zuerst auftritt, kann alles, was Sie im DrawItem -Handler zeichnen (z. B. der Selektionseffekt), möglicherweise von Dingen überlagert werden, die Sie im DrawSubItem -Handler machen (z. B. bestimmte Zellen mit einem anderen Hintergrund) Farbe).

Alles in allem ist die Handhabung der Eigentümerzeichnung eine ziemlich komplizierte Angelegenheit - ich fand es am besten, die all Zeichnung im DrawSubItem -Ereignis zu handhaben, es ist auch am besten, Ihre eigene Doppelpufferung mit Hilfe der BufferedGraphics Klasse.

Ich fand auch, dass ich den Quellcode für ObjectListView sehr praktisch finde.

Letztendlich dient all dies nur dazu, den Detailmodus der Listenansicht zu handhaben (der einzige Modus, den ich benutze), wenn Sie möchten, dass die anderen Modi auch funktionieren, dann glaube ich, dass es noch zusätzliche Dinge zu berücksichtigen gibt.

Wenn ich eine Chance bekomme, werde ich versuchen, meinen Arbeitsbeispiel-Code zu veröffentlichen.

    
Justin 01.02.2012, 13:41
quelle
3

Ich weiß nicht, ob dir das vollständig helfen wird, aber ich füge ein paar Anmerkungen hinzu:

Beachten Sie, dass DrawSubItem auch das erste Element zeichnet, und das ist wahrscheinlich der Ort, von dem Sie den double-rendered -Look erhalten.

Einige Dinge zu versuchen (nicht für die Geschwindigkeit berücksichtigt):

%Vor%

Stellen Sie für Ihre DrawSubItem-Routine sicher, dass Sie nicht in die erste Spalte zeichnen und die DrawBackground() -Routine hinzugefügt haben. Ich fügte dem Highlight-Rechteck etwas Ausschnitt hinzu, damit es nicht außerhalb der Spaltenparameter malte.

%Vor%

Im Allgemeinen begrüßt der Besitzer, der ein ListView-Steuerelement zeichnet, in einer Welt voller Verletzungen. Sie zeichnen keine visuellen Stile mehr, Sie müssten das auch selbst tun. Ugh.

    
LarsTech 30.01.2012 17:14
quelle
2

Die ausgewählte Hintergrundfarbe wurde geändert. Standardmäßig blau in Windows. Dieser Code wird dir in allen Farben helfen:

%Vor%     
user2955748 05.11.2013 09:49
quelle
1

ComponentOwl hat kürzlich eine Freeware-Komponente namens Better ListView Express veröffentlicht.

Es sieht aus und verhält sich genau wie der ListView, hat aber einen viel mächtigeren Besitzer Zeichnen Fähigkeiten - Sie können genau über alle Elemente zeichnen und sogar einige Zeichnungen abstellen (zB Auswahl, um Sie anzumachen).

    
Libor 01.02.2012 14:52
quelle
0
%Vor%     
user2955748 05.11.2013 09:52
quelle

Tags und Links