Listview-Datenbank v3

  • Früher (mit weniger Erfahrung) hielt ich es für eine gute Idee, eine Datenbank ausschließlich mit einem Listview zu verwalten (siehe: Listview-Datenbank-Beispiel).
    Also die Daten direkt in das Listview eintragen, dort sortieren und dort suchen. Von dort aus speichern und auch dahin von der Festplatte laden.
    Mit wenigen Datensätzen ist das machbar und auch schnell genug, deshalb ist mir das erst nicht bewusst geworden.
    Erst als ich so eine "Datenbank" im praktischen Einsatz hatte und die Datensätze immer mehr wurden, wurde mir klar, dass das keine so gute Idee war.


    Lange Rede, kurzer Sinn! Ich handhabe das mittlerweile anders: alle Daten werden in ein Array geladen, eingegeben, sortiert, dort gesucht und von dort gespeichert.
    Das Listview dient im Wesentlichen nur der Anzeige. Auf diese Weise ist das Ganze sehr viel schneller und man kann auch umfangreichere Datensätze verwalten.


    Ich wurde nach einem Beispiel-Script gefragt und so habe ich mich mal hingesetzt und solch ein Beispiel-Script geschrieben.
    Das Script ist ganz schön umfangreich geworden (ca. 47kB), aber rund die Hälfte davon sind Kommentare.
    Dabei habe ich auch an die AutoIt-Anfänger gedacht und jede Zeile kommentiert, mit der Hoffnung, dass das damit verständlich wird.


    Das Script ist nicht nur einfach ein Datenbank-Beispiel geworden. Ich habe auch andere Erfahrungen, speziell mit der GUI-Verwaltung, mit einfliessen lassen:

    • Für AutoIt-Anfänger ist wohl der OnEvent-Modus ein Beispiel dafür.
    • Andere haben mit Arrays so ihre Probleme.
    • Ein größenveränderbares Hauptfenster wird hier ebenso benutzt, wie das abspeichern der Größe und Position des Fensters in einer Inidatei.
    • Auch das abwechselnde benutzen des OnEvent- wie auch des MessageLoop-Modus (z.B. für das Infofenster) wird in dem Beispiel gezeigt.
    • Verwenden einer Menüleiste und einer Statuszeile.
    • Doppelkliick-Auswertung auf ein Listview
    • usw.


    Screenshot:


    LVDB-Beispiel.png


    Bedienung des Programms:
    Es gibt sieben Buttons auf dem Hauptfenster:

    • Neue Datenbank erstellen -> Wenn bereits eine Datenbank geladen ist, wird vorher nachgefragt, ob das wirklich passieren soll.
    • Datenbank laden -> Es öffnet sich ein Dialogfenster, indem man eine Datenbankdatei auswählen kann, die dann geladen wird.
    • Datenbank speichern -> Es öffnet sich ein Dialogfenster, indem man eine Datei angeben kann, unter der die Datenbank gespeichert wird (".lvdb" wird hinzugefügt).
    • Neuen Eintrag erstellen -> öffnet ein Fenster, zur Eingabe eines neuen Datensatzes.
    • Eintrag bearbeiten -> öffnet ein Fenster, in dem man den ersten markierten (bzw. den mit Doppelklick ausgewählten) Eintrag bearbeiten kann.
    • Markierte Einträge löschen -> alle markierten Einträge werden, nach Rückfrage, aus der Datenbank gelöscht.
    • Programm-Informationen -> öffnet ein Fenster mit den Programm-Informationen.

    Außerdem gibt es die Suche, mit dem Suchbegriff-Eingabefeld und dem Lupen-Button.
    Wobei es zwei Arten der Suche gibt:

    • Einmal die "Einzelsuche" (Aufruf ohne gedrückte Shift-Taste), hier wird der Suchbegriff im Listview einzeln angesteuert und der Suchtreffer markiert.
    • Und zum Anderen die "Treffersuche" (Aufruf mit gedrückter Shift-Taste), hier wird ein extra Suche-Listview angezeigt, indem alle Suchtreffer aufgelistet sind (und nur diese).

    Zurück zum normalen Daten-Listview kommt man, wenn man die Suche mit leerem Eingabefeld startet.


    Im ZIP-Archiv (Anhang) findet ihr das komplette Script, sowie eine Beispiel-Datenbankdatei mit über 16.000 Datensätzen (die habe ich mit Zufallsdaten erstellt).
    Die Datenbankdateien bekommen von dem Programm die Endung ".lvdb". Es handelt sich aber um reine Textdateien. Man kann sie also auch mit einem Editor öffnen.


    Lizenz:
    Freeware! Das heißt, ich stelle euch das Script zur freien Verfügung. Ihr dürft es verwenden und verändern, wie ihr wollt. Auch das Infofenster dürft ihr beliebig anpassen.
    Ein Hinweis auf mich als Autor der Vorlage wäre zwar schön, ist aber keine Bedingung.


    Update 31.05.2017 Version3.1:

    • Fehler beim schliessen der Gruppe behoben.
    • Beim aendern der Spaltenbreite des Listview wurde die neue Spaltenbreite erst beim beenden des Programms gespeichert.
    • Beim beenden des Programms wurde für die Nachfrage noch eine MsgBox benutzt. Ich habe nun die Funktion "_ConfirmDelete" in "_Confirm" umbenannt und verwende sie für beide Nachfragen.
    • Einige Kommentare hizugefügt/korrigiert.


    Update 01.06.2017 Version3.2:

    • Beim Listview $LVS_EX_DOUBLEBUFFER hinzugefügt. Damit reduziert sich das flackern beim Resizing.
    • Bei dem Eingabefenster ist das erste Element nun ein Date-Control, so braucht man das eingegebene Datum nicht auf Gültigkeit überprüfen und es erleichert die Eingabe.
    • Das zweite und dritte Input-Control habe ich mit $ES_NUMBER erweitert, weil man dort ja nur Zahlen eingeben soll.
    • Beim begrenzen des Fensters auf ein Minimum werden nun die Systemwerte für den Fensterrahmen ausgelesen. Die sind ja bei den Windowsversionen unterschiedlich.
    • Beim resize "_WM_SIZE" wird nun die Aufteilung der Statuszeile mehr zugunsten der linken Seite berücksichtigt.
    • Die Funktion "_Confirm" wird nun auch beim neu erstellen der Datenbank benutzt.
  • Zufällig genau das was ich gerade brauche :-)


    Beim ändern der Fenstergröße (nach rechts größer machen) schwirren bei mir Linien von der linken oberen Ecke/Seite aus durch das Bild,
    sieht aus wie der Rahmen einer Group, habe aber auf Anhieb nichts gefunden was oben links bei 0,0 beginnt

  • sieht aus wie der Rahmen einer Group, habe aber auf Anhieb nichts gefunden was oben links bei 0,0 beginnt

    Ja, jetzt sehe ich den Fehler auch!
    Wobei das nach einem Neustart des Programms weg ist.
    Tatsächlich verursacht der Rahmen der Suchbegriff-Group diesen Fehler und noch kurioser ist, dass der Fehler nicht mehr auftritt, wenn man die Zeile GUICtrlCreateGroup('', -99, -99, 1, 1) auskommentiert.

  • Das Script ist eine richtig tolle Sache. Klasse kommentiert und nachvollziehbar. Vielen Dank für die arbeitsreiche Bereitstellung !

    Viele Grüße,
    -Bazii-

    Einmal editiert, zuletzt von bazii () aus folgendem Grund: Textinhalte überarbeitet

  • sieht aus wie der Rahmen einer Group

    Ist es auch... und es liegt am Resizing.


    Wenn du nach dem Schließen der Gruppe ("schließen" finde ich treffender) unter Zeile 105 noch ein GUICtrlSetResizing() einfügst, stimmt es mit der Optik wieder...

    Code
    1. GUICtrlCreateGroup('', -99, -99, 1, 1) ; die Gruppe beenden
    2. GUICtrlSetResizing(-1, $GUI_DOCKSIZE + $GUI_DOCKTOP + $GUI_DOCKLEFT)
  • @Oscar
    Auch ich möchte mich für das Skript und deine Mühe bedanken ! :thumbsup:


    Die ausführlichen Kommentare, aber auch die Einblicke in Struktur und Programmierstil, machen das Ganze fast schon zu einem Tutorial. Sowohl Anfänger als auch Fortgeschrittene werden davon sehr profitieren können.


    Danke auch für die großzügige Lizenzierung. Auf diese Weise kann jeder das Skript/Skriptteile problemlos in eigene Projekte integrieren.


    Gruß Musashi

    "Die Definition von Wahnsinn ist, immer wieder das Gleiche zu tun und andere Ergebnisse zu erwarten." - Albert Einstein

  • Hallo @Oscar, hallo Leute.
    Mich stört bei GUIs mit Listviews, die man in der Größe ändern kann das extreme Flackern beim Ändern der Größe. Ich habe das auch noch nicht mit irgendeinem Style wegbekommen. Wie macht ihr das?
    Weil ich es nicht verhindern kann, habe ich mich entschieden es etwas abzumildern. In der On Event-Funktion _WM_SIZE wird ein Timer gestartet, die Listview versteckt, und eine weitere Funktion registriert, in der die Timervariable ausgewertet wird. So lange _WM_SIZE bei der Größenänderung aufgerufen wird, wird der Timer immer neu gestartet und erreicht nie die Zeitschwelle nach der in der anderen Funktion die Listview wieder eingeblendet wird. Erst wenn man mit dem Verschieben fertig ist, wird die Listview wieder eingeblendet und die Funktionsaufrufe beendet.


    Das ganze sieht dann so aus:
    Globale Variable für den Timer:

    Code
    1. Global $g_hTimer ; Variable, die in WM_SIZE gesetzt und in _EndSize ausgewertet wird. Dient zur Auswertung, dass eine Größenänderung der GUI abgeschlossen ist.

    Geänderte _WM_SIZE Funktion:

    Code
    1. Func _WM_SIZE($hWnd, $iMsg, $wParam, $lParam) ; diese Funktion wird aufgerufen, wenn die Groesse des Hauptfensters geandert wurde
    2. #forceref $hWnd, $iMsg, $wParam, $lParam ; eine Anweisung an AutoIt, dass diese Variablen hier nicht verwendet werden
    3. _GUICtrlStatusBar_Resize($hStatus) ; die Statuszeile an die Groesse des Hauptfensters anpassen
    4. $g_hTimer = TimerInit() ; Bei Größenänderungen wird ein Timer gestartet, ..
    5. GUICtrlSetState($idListView, $GUI_HIDE) ; die Listview ausgeblendet, ..
    6. AdlibRegister("_EndSize", 30) ; und der zyklische Aufruf der Funktion _EndSize registriert.
    7. Return $GUI_RUNDEFMSG ; Anweisung an Windows, dass es mit der normalen Abarbeitung fortfahren kann
    8. EndFunc ;==>_WM_SIZE

    Funktion, in der geprüft wird, ob die Größenänderung abgeschlossen ist:

    Code
    1. Func _EndSize() ; Diese Funktion wird in _WM_SIZE aufgerufen. (Um das Flackern der Listview zu vermeiden, wird sie versteckt bis das Ändern der Größe beendet ist).
    2. Local $fDiff = TimerDiff($g_hTimer) ; So lange die Größe sich geändert, wird $g_hTimer = TimerInit() aufgerufen und $fDiff erreicht nicht 50.
    3. If $fDiff > 50 Then ; Wenn der 50 doch überschritten wird, wird ..
    4. AdlibUnRegister("_EndSize") ; der zyklische Aufruf der Funktion _EndSize beendet..
    5. GUICtrlSetState($idListView, $GUI_SHOW) ; und die Listview wieder eingeblendet.
    6. EndIf
    7. EndFunc ;==>_EndSize

    Ich weiß nicht, ob das gut ist. Für mich war es bisher aber ein gangbarer Weg, der die GUI deutlich ruhiger beim Ändern der Größe macht.


    Das wäre dann schon das geänderte Skript. Die _EndSize-Funktion habe ich einfach unter _WM_SIZE kopiert - auch wenn sie da eigentlich nicht wirklich hin gehört..

  • Hallo Oscar,
    ich weiß nicht ob ich der Beispiel-Script Schuldige bin aber


    DANKE


    es ist endlich mal wieder eine sql freie Variante und dennoch schnell.
    Ich ziehe den Hut und werde es mal austesten..


    Lieben Gruß

  • Hallo @flummi1988,

    es ist endlich mal wieder eine sql freie Variante und dennoch schnell.

    ich finde das Skript vor allem toll, weil hier sehr schön und extrem ausführlich kommentiert vorgestellt wird, wie man Daten in einer GUI verwalten/anzeigen kann. Es würde sich daher sehr gut in einem AutoIt Kurs anbieten*. Man sollte es aber richtig einordnen. Wenn es wirklich um die Daten an sich geht, kommt man (ab einem gewissen Punkt nicht mehr sinnvoll) an SQL nicht vorbei. Klar, hier wird aus jeder Spalte alles gefunden. Aber mach das selbe mal mit zwei, drei Bedingungen. Finde a wo b=x und c=y. Dann ist es vorbei mit der Performanz. Da sollte man sich nichts einreden.


    *(etwa als ein abschließendes Beispiel, nachdem man die einzelnen Komponenten in einzelnen Teilen vorgestellt hat).

    Grüße autoiter

    Einmal editiert, zuletzt von autoiter () aus folgendem Grund: Formulierung geändert

  • autoiter : Ein verstecken des Listviews während des Resizing finde ich nicht so gut. Ich habe jetzt aber mal das $LVS_EX_DOUBLEBUFFER hinzugefügt. Damit reduziert sich das flackern zumindest.


    flummi1988 : Ja, Du warst der Auslöser, dass ich das endlich mal in Angriff genommen habe. Ich wollte das Beispiel schon länger mal ändern, weil ich das so wie damals schon lange nicht mehr handhabe.



    Es gibt aber (schon wieder) ein paar kleine Änderungen am Script. Update auf v3.2 in Post#1.

  • Ja, das verstehe ich @Oscar. Wenn man etwa so groß ziehen möchte, bis ein Inhalt komplett sichtbar ist, ist es natürlich doof, wenn die Listview beim Großziehen nicht sichtbar ist. Beim Ausprobieren war ich nun aber überrascht, wie gut das klappt. Bei mir habe ich gar kein Flackern mehr beim Ziehen, sondern nur noch beim Wechsel Vollbild zu Fenster und zurück gesehen. Bei früheren eigenen Versuchen war ich nicht so überzeugt von dem Style. (Wahrscheinlich hatte ich etwas falsch gemacht ^^ ). Aber so ist das super. :thumbup:

  • Hallo Oscar.


    Dann werde ich wohl mal sehen, das ich meine Musikdatenbak mit 12 Spalten auf das neue von Dir "anpasse".
    In der großen Datenbank sind bereits gut 9.700 Titel mit jeweils 11 weiteren Spalten wie z. B. Erscheinungsjahr,
    Playlist, usw..


    Auch andere Sachen halte ich ja mit dem "ListView-Datenbank" fest. Ist echt super !!! DANKE !!!

    ...... Lieben Gruß, ........
    ...........
    Alina ............

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Ich habe die Deutsche Hilfe auf meinem PC und
    OrganizeIncludes ist beim Scripten mein bester
    Freund. Okay?

  • Hallo Osscar,
    das ist nicht nur ein Klasse Script, es ist auch echt Super um zu lernen


    Ein großes Lob und VIELEN DANK


    Aber noch eine Frage:
    Ich will in die Spalte 2 IP Adressen eintragen. Wie bekomm ich diese formatiert ?


    Danke
    Gruß
    Thomas

  • Ich weiß jetzt nicht genau, was Du mit Spalte 2 meinst. In dem Beispiel fängt das zählen bei Null an, somit wäre Spalte 2 die dritte Spalte.
    Ich habe Dir aber mal das Beispiel umgeschrieben, sodass in der zweiten Spalte (Spalte 1) die IP-Adresse eingetragen werden kann. Zum eingeben habe ich die "GuiIPAddress.au3"-UDF verwendet.
    Außerdem mussten einige Funktionen angepasst werden.
    Du findest das Beipielscript im Anhang.

  • Super Danke


    Ich hab wirklich schon unheimlich viel von deinem Beispiel gelernt
    Hab AutoIT zufällig "gefunden" , und da ich früher mal Basic, den guten alten Clipper und Pascal Programmieren konnte findet man sich schneller rein.


    Aber es ist natürlich Klasse das Leute wie du Ihre Freizeit opfern und den Neulingen zu helfen.


    Danke dafür !

  • Lach ............


    Da ist sicher der harmloseste Fehler der mir übers lange Testprogrammierwochenende mit AuoIt passiert ist ...........


    Aber wird es mir merken. Das Konzept von AutoIt ist jedenfalls klasse


    Schönen Abend

  • Hi Oscar,



    super Skript.
    Du hast nicht zufällig so ein Beispiel mit "echtem Datenbank-Unterbau (SQLite oder sowas) rumliegen?



    Gruß und vielen Dank fürs Teilen! :)


    nuts