ListView und Filter, nur wie am besten?

  • Ein wenig klarer wurde es, danke.
    Aber die Frage ist nun, warum möchtest du die Aktualisierung des LV erstmal unterbinden?

    Zitat

    Da ich den Inhalt des ListViews immer wieder verändere, sollte auch das Redraw gestoppt werden, während ich z.B. die Spaltenbreite einstelle.
    Normalerweise gibt es dazu ja _GUICtrlListView_BeginUpdate und _GUICtrlListView_EndUpdate, aber das scheint den WM_NOTIFY nicht wirklich zu interessieren, oder gibt es da auch was dazu?

    Dieser Teil enthält zwar die Beantwortung, aber eben diesen verstehe ich nicht.

    In kurz:
    Warum willst du die Aktualisierung verzögern?

  • Hello again,

    ich will nichts verzögern, ich will es beschleunigen! :)

    Kennst Du die Befehle _GUICtrlListView_BeginUpdate und _GUICtrlListView_EndUpdate?

    Um es in wenigen Worten zu erklären:
    Wenn die beiden oberen Befehle nicht benutzt werden, dann wird, sobald irgendeine Veränderung mittels irgendeiner Funktion auf das ListView gemacht wird, sofort in der Gui nachgezeichnet, auch wenn es nicht sichtbar ist, oder auch wenn mehrere Operationen hintereinander gemacht werden. Das kostet unnötig Zeit.

    Machen wir es an einem Beispiel deutlich. Das sichtbare Fenster des Listviews ist 10 cm breit. Ich habe 10 Spalten a 2cm. D.h. die ersten 5 Spalten werden angezeigt. Wir vernachlässigen jetzt mal die Reihen.
    Jetzt will ich aber, dass jede Spalte 4 cm breit wird, also wird die erste Spalte 4 cm breit gemacht, dadurch teilweise neu gepinselt und die Spalte 2 nach rechts verschoben und ebenfalls neu gepinselt usw. bis zur letzten Spalte.
    Dann wird die 2. Spalte 4 cm breit gemacht und wird erneut frisch gepinselt und alle darauf folgenden auch. Und das, bis alle Spalten die Breite von 4 cm haben. D.h. viele Spalten werden (unnötigerweise) mehrfach gepinselt.

    Wenn jetzt aber die "Ausgabe" der Gui unterbunden wird, bis alle Spalten 4 cm breit sind, muss nach der Freigabe zum Repaint nur einmal das Endergebnis gezeichnet werden. Dadurch ist die Gui viel schneller, denn nicht das Verbreitern der Spalten kostet Zeit, sondern das Darstellen am Bildschirm in der Gui und nicht der Update des Speichers.

    Und je nach dem wie groß das ListView ist, kann man einiges an Zeit gewinnen. Und wie Du mit dem wm_notify siehst, ist die Funktion eh nicht besonders schnell und wenn da 10 Spalten verbreitert werden müssen, gehen auf meinem Pentium 4 viele Sekunden (!) verloren, bis alle Spalten die optimale Breite haben.

    Ist es jetzt klarer?

    happy computing!
    R@iner

  • Jo, viel klarer.
    Aber als Zwischenfrage:
    Willst du, dass man die Spalten verbreitern kann, oder sollen die fix bleiben? (Die Breite der Spalten, also, dass man sie nicht verschieben kann?)
    oder willst du,
    dass die Spalten sich der Länge des Textes anpassen?

    Weil wenn eins von den beiden zutrifft, ist es ja egal,dass die Redraw Funktion einsetzt, bzw. bei Variante 2 lässt man sie dann nach der Anpassung einsetzen, sprich man fügt halt das passende in die Notify Message hinzu.

  • Willst du, dass man die Spalten verbreitern kann, ...


    Ja

    Zitat

    oder willst du, dass die Spalten sich der Länge des Textes anpassen?


    Ja, nachdem die Liste erweitert, ergänzt, Elemente gelöscht oder sonst irgendwie modifiziert wurde.

    Zitat

    Weil wenn eins von den beiden zutrifft, ist es ja egal,dass die Redraw Funktion einsetzt, ...


    Nein ist es nicht! Warum habe ich bereits erklärt.

    Nochmal meine Frage:
    Ist es irgendwie möglich, den Redraw, also die kontinuierliche Aktualisierung der GUI während dem wm_notify irgendwie zu unterbinden? Und wenn ja, wie? Gibt es vergleichbares zu _GUICtrlListView_BeginUpdate und _GUICtrlListView_EndUpdate?

    Happy computing!
    R@iner

    • Offizieller Beitrag

    Da ich den Inhalt des ListViews immer wieder verändere, sollte auch das Redraw gestoppt werden, während ich z.B. die Spaltenbreite einstelle.
    Normalerweise gibt es dazu ja _GUICtrlListView_BeginUpdate und _GUICtrlListView_EndUpdate, aber das scheint den WM_NOTIFY nicht wirklich zu interessieren, oder gibt es da auch was dazu?


    Bei jeder Aktion, die eine Änderung der Darstellung bewirkt, wird ein Listview (bzw. der sichtbare Teil) neugezeichnet. Wenn keine Farben im Spiel sind ist das kaum merkbar. Um die wechselnden Farben zu realisieren ist es erforderlich auf jede Veränderung zu reagieren. Ein BeginUpdate/EndUpdate läßt sich nicht verwirklichen - woher sollte WM_NOTIFY wissen, dass keine Veränderung mehr erfolgt und erst dann alles bisherige neuzeichnen?
    Man könnte evtl. über eine Zeit-Variable eine erste Änderung registrieren und _BeginUpdate setzen und wenn innerhalb einer Zeit X keine weitere Änderung erfolgt _EndUpdate setzen. Kannst du ja mal testen.

  • Nein, die beiden Funktionen sind leider unwirksam, sobald wm_notify am Arbeiten ist. Schau dir Dein von mir modifizierte Beispiel an:

    ich benutze die beiden Funktionen. Auszug:

    [autoit]

    Func SetOptimalColumnWidth()

    [/autoit][autoit][/autoit][autoit]

    _GUICtrlListView_BeginUpdate($ListView1)
    For $c = 1 To $MaxCols
    _GUICtrlListView_SetColumnWidth($ListView1, $c - 1, $LVSCW_AUTOSIZE)
    Next
    _GUICtrlListView_EndUpdate($ListView1)

    [/autoit][autoit][/autoit][autoit]

    EndFunc ;==>SetOptimalColumnWidth

    [/autoit]

    Neu gezeichnet wird normalerweise immer erst nach dem GUICtrlListView_EndUpdate($ListView1). Und zwar nur der sichtbare Teil. Da hast Du recht.

    Das funktioniert, wenn nicht die wm_notify im Spiel ist. Ich hab es auch schon mit sleep gebremst um zu sehen, ob wirklich nichts gezeichnet wird. Es wird definitiv erst das Resultat nach GUICtrlListView_EndUpdate($ListView1) gezeichnet. Aber durch wm_notify funktionieren diese beiden Funktionen eben nicht mehr.

    Happy computing!
    R@iner

    • Offizieller Beitrag

    Der Aufruf der Funktionen muß innerhalb der WM_NOTIFY erfolgen, im:
    Case $NM_CUSTOMDRAW
    Ob er wirksam ist hab ich noch nicht getestet.
    Kannst ja die Funktionen direkt verwenden:

    [autoit]

    ; BeginUpdate
    _SendMessage($hListView, 0x000B)

    [/autoit][autoit][/autoit][autoit]

    ; EndUpdate
    _SendMessage($hListView, 0x000B, 1)

    [/autoit]
  • Hallo BugFix,

    entweder versteh ich Dich nicht, oder Du mich nicht. :(

    Der WM_NOTIFY bzw. die darin enthaltene $NM_CUSTOMDRAW wird für jedes Item aufgerufen, oder? Das heißt, bei 1.000 Reihen und 10 Spalten wären es 10.000 Aufrufe bis einmal ganz die Tablelle "gezeichnet" wird.

    Was soll das jetzt bringen, wenn ich _GUICtrlListView_BeginUpdate direkt vor dem $NM_CUSTOMDRAW aufrufe und gleich danach _GUICtrlListView_EndUpdate? Dann wird ja sofort danach trotzdem gezeichnet, also auch wieder 10.000 Mal.

    Genau deshalb habe ich die beiden Befehle quasi eine "Stufe" höher angesetzt, und dort benutzt. Aber das bringt nix.

    Ich probier es heute Abend trotzdem mal aus.

    Happy computing!
    R@iner