Entwickler-Ecke

Windows API - Listview neu zeichnen


UC-Chewie - Do 31.07.03 21:13
Titel: Listview neu zeichnen
Ich zeichne in ein ListView mithilfe der GDI, um das Selektieren von Spalten und Spaltenteilen zu simulieren. Es handelt sich hierbei um ein nonVCL-ListView)
Nun will ich dieses Gezeichnete wieder entfernen, doch wie mach ich das?
Wenn ich eine WM_PAINT-Message an das ListView schicke, bekomme ich eine AccessViolation, wenn ich ListView_RedrawItems aufrufe, dann krieg ich ein Flimmerkonzert.

Schade, dass es hier keine Anhänge gibt, aber ich such mir mal einen Server und lad den Code drauf (Er ist etwas länger, da es eine ganze Klasse ist). Weiß nicht, ob man ihn braucht, aber schaden kanns nicht.

Die Klasse: http://www.trabi2003.de/stuff/HexListView.pas
Ein Testprojekt: http://www.trabi2003.de/stuff/HexListView.EXE


Delete - Do 31.07.03 21:36

InvalidateRect?


UC-Chewie - Do 31.07.03 21:42

Da blinkt jetzt zwar nicht die ganze Zeile, sondern nur das, was ich in eine Spalte gezeichnet hab.
Also wieder nix.


lemming - Fr 01.08.03 10:35

Repaint ?


UC-Chewie - Fr 01.08.03 10:52

Repaint? Wo gibts das? Bestimmt nicht in der GDI.


Tana´Ri - Fr 01.08.03 11:41


Delphi-Quelltext
1:
2:
3:
listview.beginupdate;
 Change;
listview.endupdate;


gibs da diese fkt net ?

Moderiert von user profile iconKlabautermann: Delphi-Tags hinzugefügt.

Zitat:

BOOL ListView_Update(
HWND hwnd,
int iItem
);
// or
lResult = SendMessage( // returns LRESULT in lResult (HWND) hWndControl, // handle to destination control (UINT) LVM_UPDATE, // message ID (WPARAM) wParam, // = (WPARAM) (int) iItem; (LPARAM) lParam // = 0; not used, must be zero );


UC-Chewie - Fr 01.08.03 12:15

Hey, super, mit ListView_Update klappts! Leider flackert da das ganze etwas, aber das krieg ich vielleicht auch noch weg. Vielen Dank!


Tana´Ri - Fr 01.08.03 12:22

lass zeichnen erst wieder zu wenn deine updates durch sind, das könnte das flackern verhindern

in WndProc des Listview

if message.msg = WM_PAINT then
if updating then // <- EXIT or message löschen


UC-Chewie - Fr 01.08.03 12:56

OK, aber Updating gehört ja zur VCL, ich mach das genze aber ohne die VCL, hab also kein Updating.


Tana´Ri - Fr 01.08.03 13:02

mein gedanke war der, selbst nen bool dazu zu verwenden sobald du mit Listview_update() beginnst, also direkt davor diese bool auf true setzen und danch auf false, sodas incoming paint messages während dessen von dir neutralisiert werden, insofern das funzt ... ich würds halt so mal testen.


UC-Chewie - Fr 01.08.03 14:22

Ne, das macht das ganze noch schlimmer.

Die Nachrichtenschleife des ListViews sieht so aus:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
//[...]
case uMsg of
    WM_PAINT:
      begin
        if Parent.FLVUpdating then Exit;  //bei diesem Befehl flimmert die ganze Zeile
        Result  := CallWindowProc(OldListViewWndProc, hwnd, uMsg, wParam, lParam);
        if Parent.FSelCol.Selected then
        begin
          Rect := Parent.GetSubItemRect(Parent.FSelCol.iItem, Parent.FSelCol.iSubItem)^;
          Parent.ColDrawRoutine(Rect, Parent.FSelCol.iItem, Parent.FSelCol.iSubItem);
        end;
      end;


FLVUpdating wird so gesetzt:


Delphi-Quelltext
1:
2:
3:
FLVUpdating := True;
  ListView_Update(ListViewHandle, FSelCol.iItem);
  FLVUpdating := False;


Delete - Fr 01.08.03 14:40

Hast du mal WM_SETREDRAW angeschaut? Das entspricht dem BeginUpdate/EndUpdate der VCL und blockiert die Bildschirmausgabe (über einen der beiden Params - sorry, hab nichts zum Nachschlagen hier). Das Flimmern müsstest du damit evtl. beseitigen können.


UC-Chewie - Fr 01.08.03 14:51

Danke, aber das ändert auch nix.