1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Code-Jack

Beiträge von Code-Jack

  • "Gegenstände" im bild zählen

    • Code-Jack
    • 14. Juni 2016 um 01:06

    Damit ist Deine eigene Frage ja beantwortet, Xorianator. Es ist wirklich komplex.

    Es wird deutlich einfacher, wenn die Körner garantiert nicht überlappend, sondern strikt vereinzelt und mit Lücke zueinander liegen. Aber schon diese scheinbar simple Vorbereitung, die Körner auszurichten, ist in der Praxis gar nicht so einfach, bei unregelmäßigen Körpern.
    Auch die Bilderkennung wäre wesentlich einfacher, wenn es stets einheitliche Gegenstände wären, wie SMD-Bauteile, frisch aus dem Gurt.

    Ein Bekannter von mir (hochgradig fähiger Informatiker und Elektroniker) hat schon allerlei Erfahrung mit Bilderkennung. Dennoch musste der schon bei seinem Bestückungsautomaten immer wieder an der Software feilen. Dabei sind SMDs nicht gerade Naturprodukte, mit variierenden Eigenschaften. Sondern SMDs haben eine sehr strikte Geometrie, mit einheitlicher Größe und Färbung.
    Aber schon da spucken Lichtreflexionen und Staubkörner und sonst was für Faktoren ziemlich in die Suppe.

    Natürlich lobt jeder seine eigene Lösung, aber ich würde das Zählen wirklich lieber auf die simple Tour erledigen, bei der nicht so viel schief gehen kann. Und wenn doch: was man nicht minutenschnell selbst beheben könnte.

    Bilderkennungs-Software halte ich da für ERHEBLICH aufwendiger.
    Hinzu kommt: Wenn man dauernd den Bauern, dem man die Lösung installiert hat, am Telefon hat, weil er mal wieder über die schlechte Zählung jammert, dann sind endlose (unbezahlte) Serviceeinsätze vorprogrammiert.
    Bei der Lösung mit Druckluft und Piezo hingegen, dürfte es meistens genügen, fernmündlich ein paar Tipps abzusondern ("Dreh mal am Druckregler / vergrößere den Abstand zur Glasplatte") und ihn dann selbst fixen zu lassen.

  • "Gegenstände" im bild zählen

    • Code-Jack
    • 13. Juni 2016 um 15:33

    Ja klar, aber da liegen sie mit Abstand zueinander.
    Deshalb ist es unbedeutend, wie viele man davon dicht an dicht auf eine Referenzfläche legen könnte (abhängig von deren Größe).

    Welchen Nutzen zieht man also aus der Zählung der Körner, mit denen man dicht gepackt einen Quadratmeter, oder ein Blatt DIN-A4 bedecken kann (wovon weiter oben die Rede war)?
    Diese Zählung würde nur dann Sinn machen, wenn die Körner auf dem Acker ebenfalls lückenlos dicht an dicht gesät werden sollen.

    Sinn der ganzen Aktion sollte ja sein, von Jahr zu Jahr auftretende Unterschiede der Größe und des Gewichtes der Körner auszugleichen, um die richtige Menge Saatgut zu bestellen. Aber die Zählung der Körner, lückenlos auf einer Referenzfläche führt da in die Irre!
    Angenommen, dieses Jahr sind die Körner klein wie Salzkörner. Dann bekommt man Millionen davon auf einen Quatratmeter.
    Auf dem Acker werden sie aber mit einem Abstand von 5cm oder so gesät. Das wäre auch dann so, wenn sie groß wie Haselnüsse sind, statt groß wie Salzkörner. In dem Fall vergrößert sich aber das Volumen der nötigen Bestellmenge, um auf die gleiche Anzahl Körner zu kommen.

    Wenn das Saatgut am Ende also per Volumeneinheit bestellt wird, dann muss man natürlich das Volumen des Schüttguts ermitteln. Da ist es eine reichlich gewagte Annahme, man könnte von der lückenlos bedeckten Fläche auf das Volumen schließen!


    Es ist natürlich anzunehmen, dass der Bauer das seit Jahrzehnten so macht, wie er es macht, weswegen ihm die pure Erfahrung lehrt, dass der Zusammenhang zwischen Fläche und Volumen für ihn brauchbar ist.
    Real ist der Zusammenhang nur dann gegeben, wenn sich die Form und Oberflächenbeschaffenheit der Körner nie ändert.
    Aber diese Annahme finde ich wiederum gewagt, wenn man doch davon ausgeht, dass sich Größe und Gewicht der Körner von Jahr zu Jahr so signifikant verändern, dass neu gezählt werden muss.
    Ich würde daher vorschlagen, es gleich richtig zu machen und das Volumen zu ermitteln.

    Also: Messbecher mit einem Liter Körner befüllen und diese Körner dann zählen.

  • "Gegenstände" im bild zählen

    • Code-Jack
    • 13. Juni 2016 um 12:33

    Den ersten ROFL-Smiley verstehe ich nicht.

    Hier jedenfalls eine Abwandlung meines letzgenannten Prinzips - mit einer PET-Flasche, statt oben aufgesetztem Trichter:

    https://www.youtube.com/watch?v=r_8wRpgvhyg

    Ich glaube allerdings, dass damit eine Vereinzelung nicht so zuverlässig klappt, wie mit dem handgefütterten Trichter.
    Und natürlich würde ich einen weit geringeren Druck empfehlen, so dass die Körner nur ca. drei Meter weit fliegen würden - wenn sie denn könnten, wäre da nicht die Glasplatte.

  • "Gegenstände" im bild zählen

    • Code-Jack
    • 13. Juni 2016 um 10:48

    Gut, du brauchst die Anzahl der Körner, die einem bestimmten Volumen (oder Gewicht) entsprechen.

    Bestellt wird am Ende entweder in der Einheit Gewicht, oder in der Einheit Volumen. Aber Du musst zuvor wissen, wie vielen Körner das entspricht. Also muss eine bestimmte Menge (Volumen, oder Gewicht) gezählt werden.

    Da finde ich den Ansatz, mit den Körnern dicht gepackt eine bestimmte Fläche zu bedecken, doch ziemlich hirnrissig, weil die resultierende Information absolut nichts aussagt, was für die nötige Bestellmenge relevant ist.

    Der korrekte Ansatz wäre daher, den Inhalt eines 1-Liter Messbechers zu zählen.
    Oder die Anzahl der Körner, die einem zuvor abgewogenen Kilogramm entspricht.

    Wir müssen also durchaus zählen, aber wir können das mit dem dicht bedeckten Quadratmeter vergessen.


    OK, nun also zum Thema "Zählen vereinzelter Körner":
    Bei Dir ist die Menge überschaubar, es lohnt sich also nicht, eine hochkomplexe und vollautomatische Maschine zu bauen, sondern wir lassen etwas Handarbeit zu. Trotzdem haben wir binnen ganz weniger Minuten das Ergebnis.

    1. Ansatz:
    Waagerechtes Metallrohr. Oben eine Öffnung, auf der ein Trichter sitzt.
    Laaangsam von Hand die Körner in den Trichter befördern.
    Druckluft ins Rohr leiten - die Körner schießen ziemlich gut vereinzelt aus dem anderen Rohrende, wie aus 'nem Maschinengewehr.
    Lasse sie nach so ca. 2 Metern Fluglänge gegen eine senkrecht hängende Metallplatte prasseln, an der ein Piezoscheibchen montiert ist.
    Wahrscheinlich reicht ein Schmitt-Trigger, mit nachgeschaltetem Pulszähler, zur Zählung.
    Ein Atmel AVR tut den Job und steuert am Ende ein Display an, oder sendet die Daten zum PC.

    Das ist alles mit Material aus der Bastelkiste schnell gebaut.
    Habe noch andere Ideen, aber die hier finde ich besonders gut.

    Man kann die Körner im Anschluss ja noch ein zweites, drittes Mal inden Trichter schmeißen, falls man dem ersten Zählergebnis nicht ganz traut.
    Sollten sich nennenswerte Abweichungen ergeben (womit ich nicht rechne), so wäre noch etwas Feintuning erforderlich, an der Auswertung. Denkbar wäre, dass eine Art "Tastenentprellung" notwendig ist, aber das geht rein in Software.
    Ein billiger Arduino mit Display hat alles, was an Elektronik erforderlich ist, bis auf den Piezo. Aber den kannst Du irgendwo ausbauen, oder für 30 Cent bestellen.

    Eine Schutzschaltung, die den Arduino-Eingang vor Überspannung durch den Piezo schützt, wird nicht erforderlich sein, dazu ist die Energie zu gering, die der Piezo liefert, unter diesen Bedingungen. Da reichen die sowieso im AVR verbauten Schutzdioden.

    Wichtig ist halt, dass nicht der volle Messbecher in einem kräftigen Rutsch in den Trichter gekippt wird, sondern dass man sie relativ langsam von Hand hinein rieseln lässt, damit die Vereinzelung gut klappt.
    Die Flugbahn von 2 Metern tut ihr übriges, um zu gewährleisten, dass keine zwei Körner exakt gleichzeitig aufprallen (falls mal zwei besonders kleine Körner nebeneinander ins Rohr passen).

    Etwas Druckluft wird oben aus dem Trichter strömen wollen. Das ist gut, denn das lockert die Körner schon beim Einwerfen auf und dient bereits der Vorvereinzelung. Aber es könnte erforderlich sein, auf den Trichter noch ein weites Rohr zu setzen (einfach aus Pappe gewickelt), damit nichts oben aus dem Trichter heraus geblasen werden kann. Mindestens beim ersten Test daher vorsichtshalber eine Schutzbrille tragen!

  • "Gegenstände" im bild zählen

    • Code-Jack
    • 13. Juni 2016 um 09:15

    Ah, die Körner müssen nicht unterschieden werden, sondern einfach nur gezählt; egal, ob geplatzt, oder nicht.
    Gut, das vereinfacht die Sache.

    Zitat von GerhardSchr

    Allerdings weiß ich noch nicht, wie die Vorrichtung funktionieren soll, dass immer nur ein Korn auf die Waage fällt....

    Das mit der Waage ist viel zu kompliziert und zu langsam.
    Mir fallen einige andere Wege ein, je nachdem, um welchen Durchsatz es geht. Erkläre ich auf Nachfrage gern.
    Aber mir dämmert gerade, dass das überhaupt alles Käse ist.
    Du willst von einem Quadratmeter hochrechnen. Warum willst Du dazu die Körner zählen?

    Breite die doch einfach nur einlagig auf einer Fläche von einem Quatratmeter aus und schütte sie anschließend in einen Messbecher.
    Dann hast Du das Volumen dieser Menge.
    Und wenn Du den Messbecher auf 'ne Waage stellst und das Tara abziehst, dann hast Du auch das Gewicht dieser Körnermenge.
    Das sind doch wohl beides die relevanten Parameter. Wozu also noch einzeln zählen?

  • AutoIt und Arduino

    • Code-Jack
    • 12. Juni 2016 um 22:59

    Diese speziellen Sprühreiniger von Kontakt Chemie (auch Konkurrenzprodukte) habe ich ja schon weitgehend durch (siehe Posting 83).
    Kontakt WL bringt es nicht.
    Kolophonium kriegt man damit einigermaßen weg, wenn es nicht gerade doll verbrutzelt ist. Aber diese resinhaltigen Flussmittel sind wirklich brutal hartnäckig.

    Die Flussmittelpaste FL22R ist so ein Kandidat. Zum Löten ist das Zeug großartig, aber die Reste kriegt man partout nicht weg.

    Ich kann es irgendwie nicht glauben, dass es dafür kein definitiv taugliches Mittel geben soll und nehme eher an, dass in all den Jahren irgend was an mir vorbei gegangen ist.
    Habe aber auch schon reichlich gegoogelt und erfolglos Foren gefilzt, inkl. dem Giganten Mikrocontroller.net

  • AutoIt und Arduino

    • Code-Jack
    • 12. Juni 2016 um 21:24

    [Fieser Scherz ON]
    Aceton ist immer ausverkauft. Da kommt dauernd so'n Typ mit Filzbart, der die ganzen Märkte leer kauft ...
    [Fieser Scherz OFF]
    (Bin gar nicht so, aber das war halt 'ne unwiderstehliche Steilvorlage) ;)

    Nee, im Ernst: Mit Aceton wollte ich da nicht bei.
    Es muss schon etwas sein, das man bedenkenlos auf ein Notebook-Mainboard loslassen kann.
    Das sind zum Bleistift diese filigranen FPC-Verbinder verbaut. Aber man denke auch an die Spulen der Schaltwandler, deren Lackumhüllung die Anwendung überstehen muss.

    Ein Mainboard mit Flüssigkeitsschaden behandle ich zunächst mit 'ner weichen Bürste, in 'nem Vollbad aus normalem Haushaltsreiniger. Manchmal auch noch kurz mit Zitronensäure (je nachdem, was da verkleckert wurde). Und nach einer ausgiebigen Wasserspülung ziehe ich die Feuchtigkeit mit reichlich Isopropanol wieder raus, vor der mehr als 24-stündigen Endtrocknung auf der Heizung.

    Nach dem Isopropanol sind leider alle Flussmittelreste weiß verfärbt und von Korrosion kaum zu unterscheiden.
    Ich hätte es gerne blitziblank, damit ich korrodierte Stellen rasch und einwandfrei erkennen kann.

    Gar zu aggressive Mittel, von denen möglicheweise doch noch Reste unter den BGAs, oder in den Ferritumhüllungen der Spulen verbleiben, jagen mir doch Angst ein.
    Aceton würde so ziemlich sicher Kurzschlüsse in den Spulen verursachen (ohne es je probiert zu haben).
    Und von den Felgenreinigern würde ich ähnliches erwarten. Es muss schon etwas sein, das sich bei Elektronikern bewährt hat.

  • "Gegenstände" im bild zählen

    • Code-Jack
    • 12. Juni 2016 um 19:44

    Oder auf 'ne Heizplatte schütten und mit 'ner Thermografiekamera arbeiten.
    Intakte Körner sollten sich in der Mitte langsamer erwärmen, als geplatze, weil sich die Wärme durch mehr Material hindurch wühlen muss.
    Demnach sollte in der Mitte geplatzer Körper relativ schnell ein Hotspot feststellbar sein, der intakten Körnern fehlt.

    Es wäre aber gut, mal mehr über das Projekt zu erfahren.
    Mir ist z. B. nicht klar, ob die Körner anschließend noch verwendet werden sollen - denn würde chips Vorschlag mit der Lebensmittelfarbe natürlich ausscheiden.

    Weiterhin ist mir unklar, um welche Mengen es geht. Wegen der Idee mit der Vereinzelung und der Feinwaage scheint es ja nur um geringe, stichprobenhafte Mengen zu gehen und nicht um derbe Massen, wie sie in einem Produktionsbetrieb anfallen.
    Es geht also anscheinend NICHT darum, ausnahmslos alle Körner zu untersuchen, bevor sie in eine Verpackung wandern?

    Zweite Idee:
    Bei relativ kleinen Stichproben, die anschließend getrost in die Tonne wandern können, wäre es denkbar die Körner auf ein vibrierendes Sieb zu schütten und von oben fluoreszierendes Pigment auf die Körner zu pudern.
    Wegen der Vibration fällt der meiste Puder oben von den Körnern ab und durch das Sieb. Aber in den Ritzen der geplatzen Körner sammelt sich besonders viel davon an.
    Dann mit UV-LEDs beleuchten.

    Dritte Idee:
    Druckluft durch ein enges Rohr blasen. Das Rohr hat oben eine Öffnung, durch die die Körner ins Rohr rieseln.
    Ich gehe davon aus, dass geplatze Körner ein anderes Flugverhalten haben, so dass sie sich automatisch von den intakten Körnern separieren.

    Vierte Idee:
    Die Körner eine Rille hinunter rutschen lassen. So, dass sie schön hintereinander kommen.
    Beleuchtung von der Seite (Die Rille könnte der Innenwinkel einer abgewinkelten Acrylglasplatte sein).
    Wegen der Beleuchtung von der Seite entsteht in geplatzen Körnern eine auswertbare Abschattung.

    Noch 'ne fünfte Idee:
    Man klebe einen geeigneten Teppich auf eine größere, schräge Fläche und lasse dort die Körner runter rutschen.

    Der Teppich soll so beschaffen sein, dass die intakten, äußerlich glatten Körner weitgehend ungehindert hinab rollen/gleiten, wohingegen die aufgeplatzten Körner in den Stoppeln hängen bleiben.

    Einfach mal mit 'ner Handvoll Körner in den Baumarkt latschen und dort verschiedene Teppiche direkt ausprobieren. Es muss vermutlich einer mit kurzen, offenendigen Stoppeln sein (wie 'ne Bürste).

    Vielleicht muss man noch etwas Vibration geeigneter Amplitude ins Spiel bringen, damit die glatten Körner wirklich hinab rutschen können, ohne das Brett gar zu steil stellen zu müssen. Denn bei zu steilen Brett würden sicherlich auch die geplatzten Körner zu leicht runter trudeln.
    Wenn alle Parameter stimmen, wären die Körner anschließend jedenfalls separiert und können bequem getrennt in der Menge erfasst werden, z. B. mit einer Zählwage.

    Btw. Waage: Ich habe nicht begriffen, warum in Posting 15 eine Feinwaage erwähnt wurde, zur Unterscheidung?
    Anscheinend wiegen die geplatzten Körner weniger. Warum ist das so?

    Gnaa, noch 'ne sechste Idee!
    Leider nur tauglich für Stichproben.

    Eventuell notwendige Vorbereitung:
    Mit einem Rakel etwas Vaseline dünn auf ein Bettlaken streichen. Dort die Körner drauf schütten und etwas verreiben, so dass sich die Außenseite mit Vaseline benetzt.
    Idee dabei: In die Öffnungen der glatten Körner kann die dünn auf das Tuch aufgetragene Vaseline nicht eindringen.

    Nun nehme man eine Platte aus diesem schaumstoffartigen Kunststoffzeug, mit dem manche Möbel, oder Fahrradsattel ausgestattet sind; das sich unter Druck einer Form temporär anpasst und bei Entlastung wieder die Ursprungsform annimmt (habe den Namen dieses Materials vergessen) und lege diese Platte oben druff, eventuell mit 'ner Glasplatte beschwert.
    Nach kurzer Zeit sollte das Zeug die Körner so halbwegs umhüllen und auch in die Öffnungen der geplatzen Körner eingedrungen sein.
    Nun die Platte abheben.

    Die glatten, zudem mit Vaseline umhüllten Körner, sollten fast unverzüglich wieder abfallen.
    Die geplatzen Körner hingegen, sollten wesentlich länger an der Platte haften bleiben.

    Eventuell muss nach jeder Anwendung die Spezialschaumstoff-Platte von der verbliebenen Vaseline gereinigt werden. Aber es sind diverse Abwandlungen dieses Prinzips denkbar und vielleicht geht es ja auch ohne Vaseline.

    Ist mir fast peinlich, aber ich habe eine siebte Idee:

    Davon ausgehend, dass die intakten Körner schwerer als Wasser sind:
    Die Körner in einer flachen Schale ausbreiten. Dann langsam Wasser einfüllen.
    Geplatzte Körner sollten nun wie kleine Schiffchen oben schwimmen.

    Falls das nicht ganz klappt:
    Schlagsahne über alle Körner und etwas durchmatschen. Die Sahne dringt in die offenen Körner ein und setzt sich dort fest. Nun schwimmen die geplatzten Körner ganz bestimmt und können leicht abgeschöpft werden.

    Die abschließende Quantifizierung muss dann (wie ursprüpnglich angedacht) per Kamera erfolgen, weil eine Zählwaage nun ausscheidet.

    Achte Idee (ööhh, hoffentlich nerve ich noch nicht):

    Man denke an eine Trillerpfeife: Kügelchen, Luftstrom, charakteristischer Sound.

    Leicht unregelmäßiges "Kügelchen" (intaktes Korn): Etwas unregelmäßigerer Sound, gegenüber einer echten Kugel, aber insgesamt doch relativ gleichmäßig "polternd".

    Sehr unregelmäßiges "Kügelchen" (geplatztes Korn): Extrem ungleichmäßiger, stellenweise immer wieder mal kurz stockender Sound.

    Auswertung per Mikrofon, bzw. an der "Pfreife" montierter Piezo-Sensor.
    Tiefpass (der nur das Poltern von wenigen Hz. durch lässt), Schmitt-Trigger, getorter Pulszähler.

    Nun bastele man sich eine Vorrichtung nach grob diesem Prinzip, wo die Körner im Idealfall vereinzelt hineinrutschen und nach einigem "Getriller" wieder heraus flutschen.


    Alternativ (fertigungstechnisch viel leichter zu machen):
    Die vereinzelten Körner einfach aus einiger Höhe auf 'ne Glasplatte plumpsen lassen, auf deren Unterseite ein Piezo montiert ist.
    Idee dabei: Intakte Körner purzeln ein gutes Stück länger herum, als geplatzte.

    Für das vorherige Vereinzeln der Körner habe ich eine gute Idee, die erkläre ich aber nur bei Bedarf.

  • AutoIt und Arduino

    • Code-Jack
    • 12. Juni 2016 um 15:21

    [Off Topic ON]
    Kennt einer der hier anwesenden Elektroniker ein Mittelchen, mit dem man gegenüber Alkohol resistente Flussmittelreste vollständig weg bekommt?

    Das Zeug scheint mit praktisch gar nichts komplett weg zu gehen. Es hilft kein:

    • Spiritus
    • Isopropanol
    • Nagellackentferner (acetonfrei)
    • Reinigungsbenzin
    • Petroleum
    • Orangenöl
    • Haushaltsputzmittel jedweder Art
    • Ultraschallreiniger mit heißer Lauge
    • ...

    Selbst mit diversen Mitteln zur Platinenreinigung aus Sprühdosen hatte ich bislang keinen wirklich befriedigenden Erfolg. Trotz stundenlangem Einwirken und ausgiebigem Bürsten.

    Fies ist der Effekt, dass nach der Anwendung von Isopropanol die noch verbliebenen Flussmittelreste weiß verfärbt erst so richtig dolle in Erscheinung treten.

    Manche nennen diese "No-clean"-Flussmittel mit zynischem Unterton genau deshalb so, weil man sie durch Reinigung partout NICHT entfernen kann ...
    Aber es muss doch irgend watt geben, auf dieser Welt!?!

    [Off Topic OFF]

  • "Gegenstände" im bild zählen

    • Code-Jack
    • 11. Juni 2016 um 17:38

    Leute die Bestückungsautomaten bauen (diese Dinger, die SMD-Bauteile auf 'ne Platine packen), beschäftigen sich mit solchen Problemstellungen.
    Ich kenne da jemanden, der sich erst kürzlich intensiv damit befasst hat, wilde Schüttungen von Bauteilen per Bilderkennung zu sortieren. Der Mann ist aber professionell unterwegs und programmiert außerdem in "C".

    Aber vielleicht hilft ja bereits das Stichwort "Bestückungsautomat" bei der Suche nach geeingeten Routinen.

  • Koordinaten einer InputBox auslesen

    • Code-Jack
    • 10. Juni 2016 um 19:11

    Ich hatte ja versprochen, meine Lösung hier einzustellen.
    Der Einfachheit halber poste ich kein kastriertes Beispiel, sondern den aktuellen Stand (V0.29) meines kompletten Programmes.
    Bei Gelegenheit muss ich die Variablen sinnvoller benennen, aber die Umgestaltung der GUI funktioniert richtig schön (man beachte die angehefteten Labels)!

    Derzeit ist die Umgestaltung noch auf das Verschieben von (den meisten) InputBoxen, sowie MemoBoxen und GroupBoxen beschränkt.

    Laden/Speichern der GUI-Parameter in eine (wählbare) Ini-Datei kommt dann als Nächstes ...

    AutoIt
    ; output.code.page=65001  ;Deutsche Umlaute ermöglichen. Klappt dennoch nur manchmal ...
    #Region Header #################################################################################################################\
    ; Erstellt mit AutoIt-Version v3.3.14.2
    
    
    Global Const $sProgrammname = "Reparaturverwaltung"
    Global Const $sVersion = "0.29"
    Global Const $sRevisionsdatum = "10.06.2016"
    Global Const $sAutor = "EDV-Dompteur, Stefan Denk"
    Global Const $sWebsite = "http://www.EDV-Dompteur.de"
    
    
    ; --- P r o g r a m m b e s c h r e i b u n g -----------------------------------------------------------------------------\
    Global Const $sAbout = "Programmname: " & $sProgrammname & @CRLF & "Version: " & $sVersion & @CRLF & "Autor: " & $sAutor & @CRLF & "Website: " & $sWebsite & @CRLF _
    & @CRLF & "P r o g r a m m b e s c h r e i b u n g" _
    & @CRLF & "---------------------------------------" _
    & @CRLF & "Die hier vorliegende Software ist Freeware, also zur kostenlosen Nutzung freigegeben!" _
    & @CRLF & "Das Programm dient kleinen Reparaturbetrieben dazu, den Überblick über ihre ausgeführten Arbeiten zu behalten." _
    & @CRLF & "Die Details einer jeden Reparatur werden in einem eigenen Datensatz einer SQLite-Datenbank gespeichert." _
    & @CRLF & "Eine Übersicht, in Form einer frei sortierbaren Liste, ermöglicht es rasch nach Datum, Kunde, Gerät etc. zu sortieren."
    ; --- P r o g r a m m b e s c h r e i b u n g -----------------------------------------------------------------------------/
    
    
    ; --- History -------------------------------------------------------------------------------------------------------------\
    Global Const $sHistory = "" _
    & @CRLF & "D a n k s a g u n g:" _
    & @CRLF & "----------------------" _
    & @CRLF & "Die Code-Vorlage, auf der dieses Programm aufbaut, stammt vom User ""RR04"", aus dem großartigen Forum www.AutoIt.de" _
    & @CRLF & "Hier der Foren-Thread mit der Ursprungsversion:" _
    & @CRLF & "https://autoit.de/index.php/Thread/83862-Alinas-SQLite-BuchVw/" _
    & @CRLF & "Vielen Dank an ""RR04"", für die tolle Vorarbeit, die mir sicherlich mehrere Tage Arbeit erspart hat!" _
    & @CRLF _
    & @CRLF & "Weiterhin enthält das Programm einzelne Routinen von ""BugFix"" (bugfix@autoit.de)" _
    & @CRLF & "Vielen Dank daher auch an ""BugFix""!" _
    & @CRLF & "" _
    & @CRLF & "Vielen Dank auch an ""autoBert"", für die gezielte Hilfe bei einer bestimmten Problemlösung!" _
    & @CRLF & "" _
    & @CRLF & "Ab hier beginnen nun die Änderngen und Erweiterungen durch Fa. EDV-Dompteur, Stefan Denk:" _
    & @CRLF _
    & @CRLF & "H i s t or y:" _
    & @CRLF & "-------------" _
    & @CRLF & "V0.01 vom 28.05.2016:" _
    & @CRLF & "- Programm umbenannt und erste Umgestaltungen der Quelltext-Vorlage von RR04." _
    & @CRLF & "- Programmbeschreibung und History im Quelltext-Header implementiert; derart, dass auch eine Ausgabe dieser Texte möglich wird." _
    & @CRLF & "- Die Tabelle wird nun bei Programmstart automatisch mit Datensätzen gefüllt (wenn DB noch nicht vorhanden, wird sie zuvor erzeugt)." _
    & @CRLF _
    & @CRLF & "V0.06 vom 29.05.2016:" _
    & @CRLF & "- Der ListView-Header ist nun eine Variable, zwecks späterer Möglichkeit zum Einlesen aus einer ini-Datei." _
    & @CRLF & "- Die Beispiel-Datensätze der usprünglichen Reparaturverwaltung umgestrickt auf die Belange einer Reparaturverwaltung." _
    & @CRLF & "- Die Feldbezeichner der SQL-Datenbank verallgemeinert, zwecks leichterer Modifizierbarkeit." _
    & @CRLF & "- Neue Datenfelder definiert: Projektordner, Gesprächsnotiz, Reparaturbericht." _
    & @CRLF & "- Bugfix: Nach dem letzten Quelltext-Umbau wurden Datensätze nicht mehr aktualisiert, nach entsprechender Button-Betätigung." _
    & @CRLF & "- Programmbeschreibung und History werden jetzt mit Zeilenumbrüchen formatiert ausgegeben." _
    & @CRLF & "- Bugfix: Datenfeld 20 wurde nicht mit aktualisiert, nach dem Editieren eines Datensatzes." _
    & @CRLF & "- Menüleiste hinzugefügt. Funktionen: Exit, Programminfo, History (der Menüzweig ""Einstellungen"" ist noch ohne Funktion)." _
    & @CRLF & "- Listview: Spaltenbreiten und Textausrichtung eingestellt. Erste Vorbereitung für späteres Laden der Werte aus ini-Datei." _
    & @CRLF _
    & @CRLF & "V0.20 vom 04.06.2016:" _
    & @CRLF & "- Harmloser Bugfix: Die Einstellmöglichkeit für die Breite von ListView-Spalte 20 fehlte im Quellcode." _
    & @CRLF & "- Anzahl der Datenfelder von 20 auf 30 erhöht. Dadurch GUI-Erscheinungsbild derzeit desolat" _
    & @CRLF & "- Momentan überflüssige Felder auskommentiert und Befehl zum Verstecken von ListView-Spalten implementiert." _
    & @CRLF & "- Vorbereitungen für späteres Laden der GUI-Parameter aus einer Datei." _
    & @CRLF & "- Elegantere Methode zur GUI-Gestaltung implementiert, für späteres Laden aus Datei." _
    & @CRLF & "- Alle InputBoxen sind nun bequem parametrierbar, voll vorbereitet für späteres Laden aus CSV-Datei." _
    & @CRLF & "- Zu jeder Inputbox gehört nun ein Label, deren Ausrichtung ebenfalls bequem einstellbar ist." _
    & @CRLF & "- Die Maus-Koordinaten werden jetzt erfasst und links in der Fußzeile angezeigt." _
    & @CRLF _
    & @CRLF & "V0.25 vom 07.06.2016:" _
    & @CRLF & "- Auch das Suchfeld kann nun einfach parametriert werden." _
    & @CRLF & "- Experimentell eine Groupbox hinzugefügt." _
    & @CRLF & "- Auch Groupboxen können nun einfach parametriert werden." _
    & @CRLF & "- Statusleiste am unteren Fensterrand debugt und erweitert. Jetzt perfekt." _
    & @CRLF & "- Inputboxen lassen sich jetzt erstmals anstazweise per Maus verschieben (noch reichlich buggy)." _
    & @CRLF & "- Fehler beseitigt bei den Koordinaten der Objekt-Label. Nun auch bei Editbox in Ordnung." _
    & @CRLF & "- Absturzfehler beseitigt (trat auf bei Klick außerhalb des Fensters): Mauspositionen werden nun durch MouseGetPos ermittelt, statt durch GUIGetCursorInfo." _
    & @CRLF & "- Hintergrundbild für das Hauptfenster implementiert." _
    & @CRLF & "- Der Modus zum Umgestalten des GUI kann nun per Menü aktiviert/deaktiviert werden." _
    & @CRLF & "- Bug bemerkt: Inputboxen und ListView nicht betretbar, wenn Hintergrundbild geladen." _
    & @CRLF _
    & @CRLF & "V0.26 vom 08.06.2016:" _
    & @CRLF & "- Die Bildschirmmaske kann nun weitgehend per Maus umgestaltet werden. Noch nicht perfekt, aber bereits brauchbar." _
    & @CRLF _
    & @CRLF & "V0.27 vom 08.06.2016:" _
    & @CRLF & "- Das Verschieben von GUI-Elementen klappt nun perfekt und schließt jetzt auch deren angeheftete Labels mit ein." _
    & @CRLF _
    & @CRLF & "V0.28 vom 08.06.2016:" _
    & @CRLF & "- Es wird jetzt eine Ini-Datei erzeugt, mit den GUI-Parametern. Noch Arbeitsbedarf, anschließendes Einlesen schlägt fehl!" _
    & @CRLF _
    & @CRLF & "V0.29 vom 10.06.2016:" _
    & @CRLF & "- Kosmetik an der Maske und am Quelltext."
    ; --- History -------------------------------------------------------------------------------------------------------------/
    
    
    ; --- Aktuelle Aufgaben ---------------------------------------------------------------------------------------------------\
    Global Const $sProgrammieraufgaben = "" _
    & @CRLF & "Folgende drei Darstellungsmodi implementieren: Kombi (Tabelle und Datensatz, wie gehabt), Tabelle (volle Größe), Datensatz (ohne Tabelle)" _
    & @CRLF & "Laden/Speichern der GUI-Parameter aus/in einer ini-Datei vervollständigen." _
    & @CRLF & "Bug: Inputboxen und ListView nicht betretbar, wenn Hintergrundbild geladen." _
    & @CRLF & "Suchfunktion derzeit nicht funktionstüchtig." _
    ; --- Aktuelle Aufgaben ---------------------------------------------------------------------------------------------------/
    
    
    #include <Array.au3>
    ;
    #include <ComboConstants.au3>
    ;
    #include <Date.au3>
    ;
    #include <EditConstants.au3>
    ;
    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    #include <GuiListView.au3>
    #include <GuiStatusBar.au3>
    ;
    #Include <Misc.au3>
    ;
    #include <StaticConstants.au3>   ;Erweiterte Einstellungen für Labels
    #include <String.au3>
    #include <SQLite.au3>
    #include <sqlite3101_dll.au3>
    ;
    #include <WindowsConstants.au3>
    #include <WinAPI.au3>
    
    
    ;--------------
    
    
    #include <ButtonConstants.au3>
    #include <StaticConstants.au3>
    #include <ListviewConstants.au3>
    #include <SliderConstants.au3>
    #include <File.au3>
    _GDIPlus_Startup()
    #EndRegion Header ##############################################################################################################/
    
    
    #Region Constanten & Variablen deklarieren und belegen #########################################################################\
    ; --- Globale Constanten deklarieren --------------------------------------------------------------------------------------\
    Global Const $asWDAYger[7] = ["Sonntag, ", "Montag, ", "Dienstag, ", "Mittwoch, ", "Donnerstag, ", "Freitag, ", "Samstag, "]
    ; --- Globale Constanten deklarieren --------------------------------------------------------------------------------------/
    
    
    ; --- Globale Variablen deklarieren ---------------------------------------------------------------------------------------\
    Opt("MustDeclareVars", 1) ;Zwingt den Programmierer, Variablen ordentlich zu deklarieren, vor der ersten Benutzung.
    Global $cboSerch, $iptSerch, $FormKombiansicht, $Label, $ListView, $ContextMenu, $MenuItem, $btnUpdate, $btnDelete, $iptSearch
    Global $cboSearch, $btnSearch, $btnDBladen, $btnClear, $lblBottomLine, $btnSave, $btnBackUp, $Result
    Global $sTmp, $sText, $i
    Global $sListViewHeader, $iDBFeldanzahl
    Global $hGUI, $hImage1, $hImage2, $aMousePos
    Global $sUserMessageOld, $sUserMessageNew
    Global $bGUIRedesign
    Global $iDoItOnlyOnce = 0
    Global $aiGUIElementXYWH
    Global $hActualGUIElement, $hActualLabel, $iActualGUINumber
    Global $iXOffsetGUIElementToMouse, $iYOffsetGUIElementToMouse
    Global $aiGUILabelXYWH
    
    
    Opt("MouseCoordMode", 0)
    Global $iPressed = 0, $iLastCtrlID = -1
    ; --- Globale Variablen deklarieren ---------------------------------------------------------------------------------------/
    
    
    ; ---Globale Variablen mit Werten belegen ---------------------------------------------------------------------------------\
    Global $sIniFilename = @ScriptDir & "\GUI.ini"
    Global $sDatenbankVollpfad = @ScriptDir & "\Reparaturverwaltung.rr04"
    $iDBFeldanzahl = 30  ;So viele Felder gibt es in der Datenbank
    ; ---Globale Variablen mit Werten belegen ---------------------------------------------------------------------------------/
    #EndRegion Constanten & Variablen deklarieren und belegen ######################################################################/
    
    
    #Region Bedienoberfläche zeichnen ##############################################################################################\
    ; --- Fenster & Menü erzeugen-----------------------------------------------------------\
    Global $FormKombiansicht = GUICreate($sProgrammname, 1200, 768, 10, 10)  ;Das Hauptfenster erzeugen.
    GUICtrlCreatePic(@ScriptDir & '\Example Images\background.jpg', 0, 0, 1200, 768)
    
    
    ; --- Menüzweig 1 ------------------------------------------------------------\
    Global $MenuA = GUICtrlCreateMenu("Datei")
    Global $MenuItemAExit = GUICtrlCreateMenuItem("Schließen", $MenuA)
    ; --- Menüzweig 1 ------------------------------------------------------------/
    
    
    ; --- Menüzweig 2 ------------------------------------------------------------\
    Global $MenuB = GUICtrlCreateMenu("Einstellungen")
    Global $MenuItemOptionen = GUICtrlCreateMenuItem("Maske umgestalten", $MenuB)
    ; --- Menüzweig 2 ------------------------------------------------------------/
    
    
    ; --- Menüzweig 3 ------------------------------------------------------------\
    Global $MenuC = GUICtrlCreateMenu("?")
    Global $MenuItemCProgramminfo = GUICtrlCreateMenuItem("Programminfo", $MenuC)
    Global $MenuItemCHistory = GUICtrlCreateMenuItem("History && Danksagung", $MenuC)
    ; --- Menüzweig 3 ------------------------------------------------------------/
    GUISetState(@SW_SHOW)   ;??? Was macht dieser Befehl?
    ; --- Fenster & Menü erzeugen-----------------------------------------------------------/
    
    
    ; --- Programmname darstellen ----------------------------------------------------------\
    ;$Label = GUICtrlCreateLabel("~ ~ ~ " & $sProgrammname & " Version: " & $sVersion & " ~ ~ ~", 0, 8, 1125, 28, 0x01) ; $SS_CENTER=0x01
    ;GUICtrlSetFont(-1, 16, 800, 0, "Arial")
    ;GUICtrlSetColor(-1, 0x0000FF)
    ; --- Programmname darstellen ----------------------------------------------------------/
    
    
    ; --- Liestview aufbauen --------------------------------------------------------------------------------------------------\
    ; ---- Headerzeile der ListView --------------------------------------------------------\
    $sListViewHeader= "" _
    & "ID" _
    & "|Annahme" _
    & "|Abholung" _
    & "|Gerät" _
    & "|Schadenskürzel" _
    & "|Firma" _
    & "|Vorname" _
    & "|Nachname" _
    & "|Endpreis" _
    & "|Re-Nr." _
    & "|Anzahl." _
    & "|Leihteile" _
    & "|Voranschlag" _
    & "|Rekla" _
    & "|Projektordner" _
    & "|Gesprächsnotiz" _
    & "|Reparaturbericht" _
    & "|17" _
    & "|18" _
    & "|19" _
    & "|20" _
    & "|21" _
    & "|22" _
    & "|23" _
    & "|24" _
    & "|25" _
    & "|26" _
    & "|27" _
    & "|28" _
    & "|29" _
    & "|30"
    ; ---- Headerzeile der ListView --------------------------------------------------------/
    
    
    ; --- Listwiew erzeugen ----------------------------------------------------------------\
    Global $aHeader = StringSplit($sListViewHeader, '|')
    $ListView = GUICtrlCreateListView($sListViewHeader, 0, 40, 1125, 260)
    GUICtrlSetBkColor(-1, 0xFFFFFF) ; Color weiß
    GUICtrlSetBkColor(-1, $GUI_BKCOLOR_LV_ALTERNATE)
    GUICtrlSetFont(-1, 10, 400, 0, "Arial")
    ; --- Listwiew erzeugen ----------------------------------------------------------------/
    
    
    ; --- Spaltenbreiten und Textausrichtung der Listview-Spalten festlegen ----------------\
    Global $GetHandleLV = GUICtrlGetHandle($ListView)
    _GUICtrlListView_SetColumn($GetHandleLV, 0, $aHeader[1], 40, 1)    ;ID
    _GUICtrlListView_SetColumn($GetHandleLV, 1, $aHeader[2], 80, 0)    ;Annahmedatum
    _GUICtrlListView_SetColumn($GetHandleLV, 2, $aHeader[3], 70, 0)    ;Abholdatum
    _GUICtrlListView_SetColumn($GetHandleLV, 3, $aHeader[4], 120, 0)   ;Gerät
    _GUICtrlListView_SetColumn($GetHandleLV, 4, $aHeader[5], 100, 0)   ;Schadenskürzel
    _GUICtrlListView_SetColumn($GetHandleLV, 5, $aHeader[6], 110, 0)   ;Firma
    _GUICtrlListView_SetColumn($GetHandleLV, 6, $aHeader[7], 110, 1)   ;Vorname
    _GUICtrlListView_SetColumn($GetHandleLV, 7, $aHeader[8], 110, 0)   ;Nachname
    _GUICtrlListView_SetColumn($GetHandleLV, 8, $aHeader[9], 60, 1)    ;Endpreis
    _GUICtrlListView_SetColumn($GetHandleLV, 9, $aHeader[10], 60, 1)   ;Rechnungsnummer
    _GUICtrlListView_SetColumn($GetHandleLV, 10, $aHeader[11], 60, 1)  ;Anzahlung
    _GUICtrlListView_SetColumn($GetHandleLV, 11, $aHeader[12], 150, 0) ;Leihteile
    _GUICtrlListView_SetColumn($GetHandleLV, 12, $aHeader[13], 60, 1)  ;Voranschlag
    _GUICtrlListView_SetColumn($GetHandleLV, 13, $aHeader[14], 70, 0)  ;Reklamation (Verknüpfung auf neuen Datensatz)
    _GUICtrlListView_SetColumn($GetHandleLV, 14, $aHeader[15], 100, 0) ;Projektordner
    _GUICtrlListView_SetColumn($GetHandleLV, 15, $aHeader[16], 100, 0) ;Gesprächsnotiz
    _GUICtrlListView_SetColumn($GetHandleLV, 16, $aHeader[17], 100, 0) ;Reparaturbericht
    _GUICtrlListView_SetColumn($GetHandleLV, 17, $aHeader[18], 40, 0)  ;Festnetz
    _GUICtrlListView_SetColumn($GetHandleLV, 18, $aHeader[19], 40, 0)  ;Mobil
    _GUICtrlListView_SetColumn($GetHandleLV, 19, $aHeader[20], 40, 0)  ;E-Mail
    _GUICtrlListView_SetColumn($GetHandleLV, 20, $aHeader[21], 80, 0)  ;Status (In Arbeit / Abholbereit / Abgeholt)
    _GUICtrlListView_SetColumn($GetHandleLV, 21, $aHeader[22], 40, 0)  ;
    _GUICtrlListView_SetColumn($GetHandleLV, 22, $aHeader[23], 40, 0)  ;
    _GUICtrlListView_SetColumn($GetHandleLV, 23, $aHeader[24], 40, 0)  ;
    _GUICtrlListView_SetColumn($GetHandleLV, 24, $aHeader[25], 40, 0)  ;
    _GUICtrlListView_SetColumn($GetHandleLV, 25, $aHeader[26], 40, 0)  ;
    _GUICtrlListView_SetColumn($GetHandleLV, 26, $aHeader[27], 40, 0)  ;
    _GUICtrlListView_SetColumn($GetHandleLV, 27, $aHeader[28], 40, 0)  ;
    _GUICtrlListView_SetColumn($GetHandleLV, 28, $aHeader[29], 40, 0)  ;
    _GUICtrlListView_SetColumn($GetHandleLV, 29, $aHeader[30], 40, 0)  ;
    _GUICtrlListView_SetColumn($GetHandleLV, 30, $aHeader[31], 40, 0)  ;
    ; --- Spaltenbreiten und Textausrichtung der Listview-Spalten festlegen ----------------/
    
    
    $ContextMenu = GUICtrlCreateContextMenu($ListView)
    $MenuItem = GUICtrlCreateMenuItem("Datensatz bearbeiten", $ContextMenu)
    ; --- Liestview aufbauen --------------------------------------------------------------------------------------------------/
    
    
    ; --- Main Area -----------------------------------------------------------------------------------------------------------\
    ; --- Buttons, Labels und Inputfelder erzeugen -----------------------------------------------------------------------\
    Global $iAnzahlGUIElemente = 24  ;Später ändern, wenn aus Datei eingelesen!!!
    Global $aCtrlLabel[$iDBFeldanzahl + 1], $aHandleGUIElement[$iDBFeldanzahl + 1]
    Global $asGUI_Element[$iAnzahlGUIElemente]     ;Array mit Anzahl GUI-Elementen erzeugen.
    Global $iYSchrittweite = 35
    
    
    
    
    ReadIniFile()
    
    
    
    
    
    
    
    
    ; --- Information
    ;$aHandleGUIElement[$iDBFeldanzahl] = GUICtrlCreateEdit("Gesprächsnotiz", 895, 400, 217, 160)
    ;$aCtrlLabel[$iDBFeldanzahl] = GUICtrlCreateLabel($aHeader[$iDBFeldanzahl + 1], 895, 372, 100, 22)
    
    
    ; --- Button "Datensatz Update"
    $btnUpdate = GUICtrlCreateButton("DS Update", 895, 583, 105, 28)
    GUICtrlSetFont(-1, 12, 400, 0, "Arial")
    
    
    ; --- Button "Datensatz löschen"
    $btnDelete = GUICtrlCreateButton("DS Löschen", 1010, 583, 105, 28)
    GUICtrlSetFont(-1, 12, 400, 0, "Arial")
    
    
    ; --- Suche
    $cboSearch = GUICtrlCreateCombo("Suche im Feld:", 50, 8, 150, 25, BitOR($GUI_SS_DEFAULT_COMBO, $CBS_DROPDOWNLIST))
    GUICtrlSetData(-1, $sListViewHeader)
    GUICtrlSetFont(-1, 12, 400, 0, "Arial")
    
    
    $btnSearch = GUICtrlCreateButton("Suche starten", 570, 8, 110, 25)
    GUICtrlSetFont(-1, 12, 400, 0, "Arial")
    
    
    ; --- Button "Datenbank laden"
    $btnDBladen = GUICtrlCreateButton("Suche beenden", 700, 8, 130, 25)
    GUICtrlSetFont(-1, 12, 400, 0, "Arial")
    
    
    ; --- Button "Eingabefelder leeren"
    $btnClear = GUICtrlCreateButton("Eingabefelder leeren", 620, 583, 241, 28)
    GUICtrlSetFont(-1, 12, 400, 0, "Arial")
    ; --- Buttons, Labels und Inputfelder erzeugen -----------------------------------------------------------------------/
    ; --- Main Area -----------------------------------------------------------------------------------------------------------/
    
    
    ; --- Horizontale, gestrichelte Linie erzeugen -------------------------------\
    Const $trR = _StringRepeat("-", 368)
    $lblBottomLine = GUICtrlCreateLabel($trR, 10, 615, 1110, 8)
    ; --- Horizontale, gestrichelte Linie erzeugen -------------------------------/
    
    
    ; --- Bottom Area ---------------------------------------------------------------------------------------------------------\
    ; --- Untere Inputfelder erzeugen --------------------------------------------\
    Global $aCtrllbl[3], $aCtrlipt[3], $aLblTxt[3] = ["Auftragsanzahl:", "Ges. Seitenzahl:", "Ges. Buch NP:"]
    For $l = 0 To 2
      $aCtrllbl[$l] = GUICtrlCreateLabel($aLblTxt[$l], 10 + ($l) * 260, 640, 120, 22)
      GUICtrlSetFont(-1, 12, 400, 0, "Arial")
      $aCtrlipt[$l] = GUICtrlCreateInput($l, 140 + ($l) * 260, 638, 120, 26, 0x0002) ; $ES_RIGHT=0x0002
      GUICtrlSetFont(-1, 12, 400, 0, "Arial")
     Next
    ; --- Untere Inputfelder erzeugen --------------------------------------------/
    
    
    ; --- Button "Neuer Datensatz" erzeugen -----------------------------------\
    $btnSave = GUICtrlCreateButton("Neuer Datens.", 1010, 635, 105, 28)
    GUICtrlSetFont(-1, 12, 400, 0, "Arial")
    ; --- Button "Datensatz kopieren" erzeugen -----------------------------------/
    
    
    ; --- Button "Datenbank-Backup" erzeugen -------------------------------------\
    $btnBackUp = GUICtrlCreateButton("DB BackUp", 895, 635, 105, 28)
    GUICtrlSetFont(-1, 12, 400, 0, "Arial")
    ; --- Button "Datenbank-Backup" erzeugen -------------------------------------/
    ; --- Bottom Area ---------------------------------------------------------------------------------------------------------/
    
    
    #EndRegion Bedienoberfläche zeichnen ###########################################################################################/
    
    
    
    
    #Region SQL starten & Datenbank in Listview laden (DB gegebenenfalls zuerst erzeugen) ##########################################\
    _SQLite_Startup(@ScriptDir & "\sqlite3.dll", False, 1) ; BugFix Idee, da DLL ja nicht mehr mitgeliefert wird
    If @error Then
       $sTmp = "SQLite.dll konnte nicht geladen werden!"
        MsgBox($MB_SYSTEMMODAL, "SQLite Error", $sTmp)
        Exit -1
    EndIf
    
    
    Local $bTabelleErzeugen = 0
    If Not FileExists($sDatenbankVollpfad) Then
       $bTabelleErzeugen = True
    EndIf
    
    
    Global $g_db_Database = _SQLite_Open($sDatenbankVollpfad)  ;Datenbank öffnen. Falls noch nicht vorhanden, dann erzeugen & öffnen.
    If @error Then
       $sTmp = "Die Datenbank:" & @CRLF & $sDatenbankVollpfad & @CRLF & "konnte nicht geöffnet werden!"
        MsgBox($MB_SYSTEMMODAL, "SQLite Error", $sTmp)
        Exit -1
    EndIf
    
    
    If $bTabelleErzeugen = True Then
      ; --- Datenbank-Tabelle erzeugen-----------------------------------------------------------------------------------------\
      Global $sDBHeader = "CREATE TABLE IF NOT EXISTS Reparaturverwaltung(ID INTEGER PRIMARY KEY AUTOINCREMENT," _
      & "F01," _ ;Annahme
      & "F02," _ ;Abholung
      & "F03," _ ;Gerät
      & "F04," _ ;Schadenskürzel
      & "F05," _ ;Firma
      & "F06," _ ;Vorname
      & "F07," _ ;Nachname
      & "F08," _ ;Endpreis
      & "F09," _ ;Rechnungsnummer
      & "F10," _ ;Anzahlung
      & "F11," _ ;Leihteile
      & "F12," _ ;Voranschlag
      & "F13," _ ;Reklamationsdatum
      & "F14," _ ;Projektordner
      & "F15," _ ;Gesprächsnotiz
      & "F16," _ ;Reparaturbericht
      & "F17," _
      & "F18," _
      & "F19," _
      & "F20," _
      & "F21," _
      & "F22," _
      & "F23," _
      & "F24," _
      & "F25," _
      & "F26," _
      & "F27," _
      & "F28," _
      & "F29," _
      & "F30);"
      ; --- Datenbank-Tabelle erzeugen ----------------------------------------------------------------------------------------/
    
    
      ; --- Mehrere Beispiel-Datensätze erzeugen ------------------------------------------------------------------------------\
      _SQLite_Exec($g_db_Database, $sDBHeader)
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-03-22 11','16-03-22 18','Medion Akoya 731','Buchse defekt','','Herbert','Mustermann','100,00','576','20.00','USB-HDD-Gehäuse','100.00','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-03-21 12','16-03-22 11','HP dv7','Buchse defekt','RA Rechtsverdreh','Ede','Knastmann','100,00','1039','','','100.00','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-03-27 16','16-03-28 11','Lenovo 730','Scharnier lose','','Cornelia','Turteltaub','120,00','1038','100.00','','100.00','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-04-22 09','16-04-27 11','Lenovo 1100','Einschaltproblem','','Waltrude','von der Weide','80,00','1040','10.00','','100.00','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-06-22 15','16-06-29 11','Toshiba Satellite 50','Stabilitätsproblem','Schokofabrik ABC','Ali','Bahbah','47,50','413','10.00','Leihgerät 4','-','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-07-22 13','16-07-22 17','Sony Vaio MG3000','Grafikfehler','','','Megenstadter','22,50','-','22.50','','-','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-03-22 11','16-03-28 15','Lenovo AS200','Sturzschaden','Druckerei Müller','Willybald','Mustermann','100,00','-','','','100.00','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-01-22 12','16-03-23 15','Toshiba Satellite X20','Flüssigkeitsschaden','','Fridolin','Kaiserschmarrn','90,00','1041','','','100.00','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'15-03-22 11','15-04-01 12','MSI XC70S','Buchse defekt','???','','Maienbaum','0,00','-','','','0.00','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-03-22 16','16-03-23 10','HP HDX18','Flüssigkeitsschaden','Werbeagentur DeLuxe','Veronika','Glitterstrass','1050,79','1042','500.00','','1000.00','','','','','','','','','','','','','','','','','','');")
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL,'16-05-27 16','','Asus X738','Einschaltproblem','Druckerei Müller','Willybald','Mustermann','','','','','100,00','','','','','','','','','','','','','','','','','','');")
     ; --- Mehrere Beispiel-Datensätze erzeugen ------------------------------------------------------------------------------/
    EndIf
    
    
    _SQLite_CountRows('Reparaturverwaltung')
    #EndRegion SQL starten & Datenbank in Listview laden (DB gegebenenfalls zuerst erzeugen) #######################################/
    
    
    ; --- Statusbar am untersten Fensterrand ----------------------------------------------------------------------------------\
    Global $idStatusbar = _GUICtrlStatusBar_Create($FormKombiansicht)
    
    
    GUISetState(@SW_SHOW)
    ;_timeStatus() ; Funktion aufrufen sofortige einmalige Ausführung nach Programmstart
    AdlibRegister('_timeStatus', 1000) ; Start alle 1000 milisec.
    
    
    Global $idStatusbar_PartsWidth[4]
    $idStatusbar_PartsWidth[0]=700
    $idStatusbar_PartsWidth[1]=$idStatusbar_PartsWidth[0]+180
    $idStatusbar_PartsWidth[2]=$idStatusbar_PartsWidth[1]+150
    $idStatusbar_PartsWidth[3]=-1 ;$idStatusbar_PartsWidth[2]+200
    
    
    _GUICtrlStatusBar_SetParts($idStatusbar, $idStatusbar_PartsWidth) ;200, 400, 700, -1) ;$idStatusbar_PartsWidth)
    Global $sMausXY
    _GUICtrlStatusBar_SetText($idStatusbar, $sMausXY, 0)
    _GUICtrlStatusBar_SetText($idStatusbar, " _SQLite_LibVersion = " & _SQLite_LibVersion(), 1)
    
    
    _GUICtrlStatusBar_SetMinHeight($idStatusbar, 20)  ;!!!
    ; --- Statusbar am untersten Fensterrand ----------------------------------------------------------------------------------/
    #Region Listview Füllen und Darstellungs-Einstellungen vornehmen ###############################################################\
    _ListViewFill()  ;Listview füllen, mit den Datensätzen der (nun garantiert vorhandenen und geöffneten) Datenbank-Datei.
    
    
    _GUICtrlListView_HideColumn($Listview, 17)
    _GUICtrlListView_HideColumn($Listview, 18)
    _GUICtrlListView_HideColumn($Listview, 19)
    _GUICtrlListView_HideColumn($Listview, 20)
    _GUICtrlListView_HideColumn($Listview, 21)
    _GUICtrlListView_HideColumn($Listview, 22)
    _GUICtrlListView_HideColumn($Listview, 23)
    _GUICtrlListView_HideColumn($Listview, 24)
    _GUICtrlListView_HideColumn($Listview, 25)
    _GUICtrlListView_HideColumn($Listview, 26)
    _GUICtrlListView_HideColumn($Listview, 27)
    _GUICtrlListView_HideColumn($Listview, 28)
    _GUICtrlListView_HideColumn($Listview, 29)
    _GUICtrlListView_HideColumn($Listview, 30)
    #EndRegion Listview Füllen und Darstellungs-Einstellungen vornehmen ############################################################/
    
    
    #Region Hauptschleife ##########################################################################################################\
    $hGUI = $FormKombiansicht ;GUICreate('Drag & Drop Images Example', 541, 340, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_CLIPCHILDREN))
    Global Const $SC_DRAGMOVE = 0xF012
    Global $iMouseButtonLeft
    Global $aRect[4]
    AutoItSetOption ("MouseCoordMode", 2 )  ;Mauskoordinaten sollen sich auf den Bereich unterhalb der Menüleiste beziehen.
    
    
    ;do
    While True
    
    
      ; --- Mauskoordinaten erfassen und darstellen -------------------------------------\
      $sMausXY=MouseGetPos()   ;GUIGetCursorInfo()  ;Die Verwendung von MouseGetPos, statt GUIGetCursorInfo vermeidet Absturz wenn außerhalb des Fensters geklickt wird.
      _GUICtrlStatusBar_SetText($idStatusbar, $sMausXY[0] & " / " & $sMausXY[1], 0)                 ;!!!!!!!! Verursacht Absturz wenn Fenster Fokus verliert !!!!!!!
      ;_GUICtrlStatusBar_SetText($idStatusbar, "lala", 0) ;$sMausXY[0] & " / " & $sMausXY[1], 0)    ;!!!!!!!! Verursacht den obigen Absturz nicht !!!!!!!
      ; --- Mauskoordinaten erfassen und darstellen -------------------------------------/
    
    
      Switch GUIGetMsg()
    
    
      Case -3
        _Exit()
    
    
      Case $ListView
       _GUICtrlListView_RegisterSortCallBack($ListView, false)
        _GUICtrlListView_SortItems($ListView, GUICtrlGetState($ListView))
    
    
      Case $btnSave
        _DsInsert()
        _ListViewFill()
        _iptClear()
        _SQLite_CountRows('Reparaturverwaltung')
    
    
      Case $btnDelete
        _DsDelete()
        _ListViewFill()
        _SQLite_CountRows('Reparaturverwaltung')
    
    
      Case $btnUpdate
        _DsUpdate()
        _ListViewFill()
    
    
      Case $btnSearch
        _ListViewFill("SELECT ROWID,* From Reparaturverwaltung WHERE " & GUICtrlRead($cboSearch) & " LIKE '" & GUICtrlRead($iptSearch) & "';")
      ; --- Obiges funktioniert derzeit nicht mehr, weil: -------------------------------\
      ; --> Query:    SELECT ROWID,* From Reparaturverwaltung WHERE Annahme LIKE '0';
        ; --> Error:    no such column: Annahme
      ; Problem sind die inzwischen abweichenden Namen der ListView Rows von den Datensatzfeldern
      ; --- Obiges funktioniert derzeit nicht mehr, weil: -------------------------------/
    
    
      Case $btnDBladen
        _ListViewFill()
    
    
      Case $btnClear
        _iptClear()
    
    
      Case $btnBackUp
        _DB_BackUp()
    
    
      Case $MenuItem
        _iptClear()
        _ListView2ipt()
    
    
      Case $MenuItemAExit
        _Exit()
    
    
      Case $MenuItemCProgramminfo
        msgbox(0, "", $sAbout)
    
    
      Case $MenuItemCHistory
        msgbox(0, "", $sHistory)
    
    
      Case $MenuItemOptionen
        Optionen()
    
    
      Case $GUI_EVENT_PRIMARYDOWN                                      ;Test
        ;_SendMessage($aHandleGUIElement[4], $WM_SYSCOMMAND, $SC_DRAGMOVE, 0)  ;Test
        ConsoleWrite("Linker Mausbutton gedrückt" & @CRLF)
        $iMouseButtonLeft = 1
    
    
      Case $GUI_EVENT_PRIMARYUP                                      ;Test
        ;_SendMessage($aHandleGUIElement[4], $WM_SYSCOMMAND, $SC_DRAGMOVE, 0)  ;Test
        ConsoleWrite("Linker Mausbutton losgel." & @CRLF)
        $iMouseButtonLeft = 0
    
    
      Case $GUI_EVENT_SECONDARYDOWN                                      ;Test
        ;_SendMessage($aHandleGUIElement[4], $WM_SYSCOMMAND, $SC_DRAGMOVE, 0)  ;Test
        ConsoleWrite("Rechtsklick" & @CRLF)
    
    
      EndSwitch
    
    
      ; --- Verhindern, dass sich während des Verschiebens ein anderes GUI-Element angesprochen fühlt -----\
      #cs
      if $iMouseButtonLeft then  ;$sMausXY[2] = 1 then
        $iDoItOnlyOnce += 1
        if $iDoItOnlyOnce > 2 Then  ;Integer-Überlauf verhindern.
          $iDoItOnlyOnce =2
        EndIf
      Else
        $iDoItOnlyOnce = 0
      EndIf
      #ce
      ; --- Verhindern, dass sich während des Verschiebens ein anderes GUI-Element angesprochen fühlt -----/
    
    
      if $bGUIRedesign=1 then   ;Im Menü wurde der Eintrag zum Umgestalten des GUI aktiviert.
        GUI_Redesign()
      EndIf
    
    
    
    
    
    
    
    
    WEnd
    #EndRegion Hauptschleife #######################################################################################################/
    
    
    ; ### Functions ################################################################################################################\
    Func _timeStatus()
      Local $zeit = _DateTimeFormat(_NowCalc(), 5)
      _GUICtrlStatusBar_SetText($idStatusbar, " " & $asWDAYger[@WDAY - 1] & _DateTimeFormat(_NowCalc(), 2), 2)
      _GUICtrlStatusBar_SetText($idStatusbar, " Uhrzeit: " & $zeit, 3)
    EndFunc   ;==>_timeStatus
    ; #############################################################################
    Func _ListViewFill($QLite = "SELECT ROWID,* FROM Reparaturverwaltung;")
      Local $hQuery, $aRow
      _GUICtrlListView_DeleteAllItems($ListView)
    ;~ 	_SQLite_Query(-1, "SELECT ROWID,* FROM Reparaturverwaltung;", $hQuery)
      _SQLite_Query(-1, $QLite, $hQuery)
      While _SQLite_FetchData($hQuery, $aRow, False, False) = $SQLITE_OK ; Read Out the next Row
        GUICtrlCreateListViewItem(_ArrayToString($aRow, '|', 1, 21), $ListView)
        GUICtrlSetBkColor(-1, 0xF0E68C) ; (0xF9F9F9) helles Grau (0xB9D1EA) helles blau (0xF0E68C)
      WEnd
      _SQLite_QueryFinalize($hQuery)
      _GUICtrlListView_RegisterSortCallBack($ListView) ; CallBack registrieren zum sortieren
    EndFunc   ;==>_ListViewFill
    ; #############################################################################
    Func _DsDelete()  ;Datensatz löschen.
      _SQLite_Exec(-1, "DELETE From Reparaturverwaltung WHERE ID = " & GUICtrlRead($aHandleGUIElement[0]) & ";")
    EndFunc   ;==>_DsDelete
    ; #############################################################################
    Func _DsUpdate()  ;Datensatz updaten
      _SQLite_Exec(-1, "UPDATE Reparaturverwaltung SET " _
      & "F01 = '" & GUICtrlRead($aHandleGUIElement[1]) & "'," _
      & "F02 = '" & GUICtrlRead($aHandleGUIElement[2]) & "'," _
      & "F03 = '" & GUICtrlRead($aHandleGUIElement[3]) & "'," _
      & "F04 = '" & GUICtrlRead($aHandleGUIElement[4]) & "'," _
      & "F05 = '" & GUICtrlRead($aHandleGUIElement[5]) & "'," _
      & "F06 = '" & GUICtrlRead($aHandleGUIElement[6]) & "'," _
      & "F07 = '" & GUICtrlRead($aHandleGUIElement[7]) & "'," _
      & "F08 = '" & GUICtrlRead($aHandleGUIElement[8]) & "'," _
      & "F09 = '" & GUICtrlRead($aHandleGUIElement[9]) & "'," _
      & "F10 = '" & GUICtrlRead($aHandleGUIElement[10]) & "'," _
      & "F11 = '" & GUICtrlRead($aHandleGUIElement[11]) & "'," _
      & "F12 = '" & GUICtrlRead($aHandleGUIElement[12]) & "'," _
      & "F13 = '" & GUICtrlRead($aHandleGUIElement[13]) & "'," _
      & "F15 = '" & GUICtrlRead($aHandleGUIElement[14]) & "'," _
      & "F15 = '" & GUICtrlRead($aHandleGUIElement[15]) & "'," _
      & "F16 = '" & GUICtrlRead($aHandleGUIElement[16]) & "'," _
      & "F17 = '" & GUICtrlRead($aHandleGUIElement[17]) & "'," _
      & "F18 = '" & GUICtrlRead($aHandleGUIElement[18]) & "'," _
      & "F19 = '" & GUICtrlRead($aHandleGUIElement[19]) & "'," _
      & "F20 = '" & GUICtrlRead($aHandleGUIElement[20]) & "'," _
      & "F21 = '" & GUICtrlRead($aHandleGUIElement[21]) & "'," _
      & "F22 = '" & GUICtrlRead($aHandleGUIElement[22]) & "'," _
      & "F23 = '" & GUICtrlRead($aHandleGUIElement[23]) & "'," _
      & "F24 = '" & GUICtrlRead($aHandleGUIElement[24]) & "'," _
      & "F25 = '" & GUICtrlRead($aHandleGUIElement[25]) & "'," _
      & "F26 = '" & GUICtrlRead($aHandleGUIElement[26]) & "'," _
      & "F27 = '" & GUICtrlRead($aHandleGUIElement[27]) & "'," _
      & "F28 = '" & GUICtrlRead($aHandleGUIElement[28]) & "'," _
      & "F29 = '" & GUICtrlRead($aHandleGUIElement[29]) & "'," _
      & "F30 = '" & GUICtrlRead($aHandleGUIElement[30]) & "'" _
      & "WHERE ID = " & GUICtrlRead($aHandleGUIElement[0]) & ";")
    EndFunc   ;==>_DsUpdate
    ; #############################################################################
    Func _DsInsert()  ;Neuen Datensatz hinzufügen.
      _SQLite_Exec(-1, "INSERT INTO Reparaturverwaltung VALUES(NULL, '" _
      & GUICtrlRead($aHandleGUIElement[1]) & "','" _
      & GUICtrlRead($aHandleGUIElement[2]) & "','" _
      & GUICtrlRead($aHandleGUIElement[3]) & "','" _
      & GUICtrlRead($aHandleGUIElement[4]) & "','" _
      & GUICtrlRead($aHandleGUIElement[5]) & "','" _
      & GUICtrlRead($aHandleGUIElement[6]) & "','" _
      & GUICtrlRead($aHandleGUIElement[7]) & "','" _
      & GUICtrlRead($aHandleGUIElement[8]) & "','" _
      & GUICtrlRead($aHandleGUIElement[9]) & "','" _
      & GUICtrlRead($aHandleGUIElement[10]) & "','" _
      & GUICtrlRead($aHandleGUIElement[11]) & "','" _
      & GUICtrlRead($aHandleGUIElement[12]) & "','" _
      & GUICtrlRead($aHandleGUIElement[13]) & "','" _
      & GUICtrlRead($aHandleGUIElement[14]) & "','" _
      & GUICtrlRead($aHandleGUIElement[15]) & "','" _
      & GUICtrlRead($aHandleGUIElement[16]) & "','" _
      & GUICtrlRead($aHandleGUIElement[17]) & "','" _
      & GUICtrlRead($aHandleGUIElement[18]) & "','" _
      & GUICtrlRead($aHandleGUIElement[19]) & "','" _
      & GUICtrlRead($aHandleGUIElement[20]) & "','" _
      & GUICtrlRead($aHandleGUIElement[21]) & "','" _
      & GUICtrlRead($aHandleGUIElement[22]) & "','" _
      & GUICtrlRead($aHandleGUIElement[23]) & "','" _
      & GUICtrlRead($aHandleGUIElement[24]) & "','" _
      & GUICtrlRead($aHandleGUIElement[25]) & "','" _
      & GUICtrlRead($aHandleGUIElement[26]) & "','" _
      & GUICtrlRead($aHandleGUIElement[27]) & "','" _
      & GUICtrlRead($aHandleGUIElement[28]) & "','" _
      & GUICtrlRead($aHandleGUIElement[29]) & "','" _
      & GUICtrlRead($aHandleGUIElement[30]) & "');")
    EndFunc   ;==>_DsInsert
    ; #############################################################################
    Func _ListView2ipt()
    ;~ 	MsgBox(0, "Information", "Selected Mark: " & _GUICtrlListView_GetSelectionMark($ListView))
      Local $electionMark = _GUICtrlListView_GetSelectionMark($ListView)
      If $electionMark > -1 Then
        Local $aLVitem = _GUICtrlListView_GetItemTextArray($ListView, $electionMark)
        For $i = 1 To $aLVitem[0]
    ;~ 			MsgBox(0, "Information", "ItemTextArray: " & $aIpt[$i-1] & "  " & $aLVitem[$i])
          GUICtrlSetData($aHandleGUIElement[$i - 1], $aLVitem[$i])
        Next
      EndIf
    EndFunc   ;==>_ListView2ipt
    ; #############################################################################
    Func _iptClear()
      For $i = 0 To 30
        GUICtrlSetData($aHandleGUIElement[$i], "")
      Next
    EndFunc   ;==>_iptClear
    ; #############################################################################
    ;==========================================================================
    ; Function Name....: _SQLite_CountRows
    ; Description......: Ermittelt die Anzahl von Datensätzen für eine Tabelle
    ; Parameter(s).....: $_sTable  Tabellenname
    ; Requirement(s)...: Eine mit _SQLite_Open() geöffnete DB
    ; .................: #include <SQLite.au3>
    ; Return Value(s)..: Erfolg:   Anzahl der Datensätze
    ; .................: Fehler:   -1   @error = 1,  @extended = SQLite-@error
    ; Author(s)........: BugFix (bugfix@autoit.de)
    ;==========================================================================
    Func _SQLite_CountRows($_sTable)
      Local $hQuery, $aQuery, $iRet = 0, $iErr
      If $SQLITE_OK <> _SQLite_Query(-1, "SELECT count(*) FROM " & $_sTable & ";", $hQuery) Then
        $iErr = _SQLite_ErrCode()
        _SQLite_QueryFinalize($hQuery)
        Return SetError(1, $iErr, -1)
      EndIf
      While _SQLite_FetchData($hQuery, $aQuery) = $SQLITE_OK
        $iRet = $aQuery[0]
      WEnd
      _SQLite_QueryFinalize($hQuery)
      ;MsgBox(0, "", $iRet)
    ;~ 	Return $iRet
      GUICtrlSetData($aCtrlipt[0], $iRet)
    EndFunc   ;==>_SQLite_CountRows
    ; #############################################################################
    Func _DB_BackUp()
      Local $BackUpFolder = @ScriptDir & "\_BackUps"
      If Not FileExists($BackUpFolder) Then DirCreate($BackUpFolder)
      Local $hFileOpen = FileOpen($BackUpFolder & "\" & @YEAR & "-" & @MON & "-" & @MDAY & "_BuchVw.db.txt", 2)
      If $hFileOpen = -1 Then Exit MsgBox(0, "Fehler", "Die Datei konnte nicht geöffnet werden.")
    
    
      Local $aResult, $iRows, $iColumns
      Local $iRval = _SQLite_GetTable2d(-1, "SELECT * FROM Reparaturverwaltung;", $aResult, $iRows, $iColumns)  ;Variablen doppelt deklariert (siehe Vorzeile).
    
    
      FileWriteLine($hFileOpen, $sListViewHeader)
    
    
      For $iR = 1 To $iRows
        $sText = ""
        For $iC = 0 To $iColumns - 1
          $sText &= $aResult[$iR][$iC]
          If $iC < $iColumns - 1 Then $sText &= "|"
        Next
        FileWriteLine($hFileOpen, $sText)
      Next
      FileClose($hFileOpen)
      MsgBox(64, "Info", "DB BackUp ist fertig !", 3)
    EndFunc   ;==>_DB_BackUp
    ; #############################################################################
    Func Stringbreite($sT_Lbl)
    ; Ermittelt die Breite des Strings in Pixeln.
    ; Basiert auf folgender Quelle:
    ; https://autoit.de/index.php/Thread/13627-TextMeter/?postID=105795#post105795&page=Thread&postID=105795
    ; Dank an den User "BugFix"!
      Local $nText = $sT_Lbl
      Local $aFont[8] = [8,0,'Courier New',10,400,0,0,0]
      Local $gui
    
    
      If $nText = '' Then Return
        ;_GDIPlus_Startup()
        Local $hFormat = _GDIPlus_StringFormatCreate(0)
        Local $hFamily = _GDIPlus_FontFamilyCreate($aFont[2])
        Local $hFont = _GDIPlus_FontCreate($hFamily, $aFont[3], $aFont[1], 3)
        Local $tLayout = _GDIPlus_RectFCreate(15, 171, 0, 0)
        Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND($gui)
        Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, $nText, $hFont, $tLayout, $hFormat)
        Local $iWidth = Ceiling(DllStructGetData($aInfo[0], "Width"))
        ;Local $iHeight = Ceiling(DllStructGetData($aInfo[0], "Height"))
        ;_GDIPlus_StringFormatDispose($hFormat)
        ;_GDIPlus_FontDispose($hFont)
        ;_GDIPlus_FontFamilyDispose($hFamily)
        ;_GDIPlus_GraphicsDispose($hGraphic)
        ;_GDIPlus_ShutDown()
        ;GUICtrlSetData($inHeight, $iHeight)
        ;GUICtrlSetData($inWidth, $iWidth)
      Return $iWidth
    ;MsgBox(0, "", $iWidth)
    EndFunc
    ; #############################################################################
    Func ReadIniFile()
      Local $aCtrls[1]
      Local $Section_GUI_Parameter
      Local $aSplit
    
    
      ;If Not FileExists($sIniFilename) Then
        ; --- GUI-Parameter der Input-Boxen und deren Labels ------------------------------------------------------------\
        ;                       1   2   3  4 5      6 7        8 9   10 11  12  1314     1516 17
        $asGUI_Element[0]  = "Inputbox000=| 15|320|100| 22|L|0x0000|0|Zeile 0    |U|   0| 0|110| 22|L|0x0000|0|Datensatz-ID"
        $asGUI_Element[1]  = "Inputbox001=|150|375|100| 22|L|0x0000|0|Zeile 1    |L|  -5| 0|110| 22|L|0x0000|0|Annahmedatum"
        $asGUI_Element[2]  = "Inputbox002=|150|400|100| 22|L|0x0000|0|Zeile 2    |L|  -5| 0|110| 22|R|0x0000|0|Abholdatum"
        $asGUI_Element[3]  = "Inputbox003=|390|375|200| 22|L|0x0000|0|Zeile 3    |O|  -5| 0|110| 22|R|0x0000|0|Gerät"
        $asGUI_Element[4]  = "Inputbox004=|390|400|200| 22|L|0x0000|0|Zeile 4    |U|   0| 0|110| 22|R|0x0000|0|Schadenskürzel"
        $asGUI_Element[5]  = "Inputbox005=|150|495|100| 22|L|0x0000|0|Zeile 5    |L|  -5| 0|110| 22|R|0x0000|0|Firma"
        $asGUI_Element[6]  = "Inputbox006=|150|520|100| 22|L|0x0000|0|Zeile 6    |L|  -5| 0|110| 22|R|0x0000|0|Vorname"
        $asGUI_Element[7]  = "Inputbox007=|150|545|100| 22|L|0x0000|0|Zeile 7    |L|  -5| 0|110| 22|R|0x0000|0|Nachname"
        $asGUI_Element[8]  = "Inputbox008=|450|550|100| 22|R|0x0000|0|Zeile 8    |L|  -5| 0|110| 22|R|0x0000|0|Endpreis"
        $asGUI_Element[9]  = "Inputbox009=|450|575|100| 22|R|0x0000|0|Zeile 9    |L|  -5| 0|110| 22|R|0x0000|0|Re-Nr."
        $asGUI_Element[10] = "Inputbox010=|450|450|100| 22|R|0x0000|0|Zeile 10   |L|  -5| 0|110| 22|R|0x0000|0|Anzahlung"
        $asGUI_Element[11] = "Inputbox011=|450|475|100| 22|L|0x0000|0|Zeile 11   |L|  -5| 0|110| 22|R|0x0000|0|Leihteile"
        $asGUI_Element[12] = "Inputbox012=|450|500|100| 22|R|0x0000|0|Zeile 12   |L|  -5| 0|110| 22|R|0x0000|0|Voranschlag"
        $asGUI_Element[13] = "Inputbox013=|140|320|100| 22|L|0x0000|0|Zeile 13   |U|   0| 0| 85| 22|L|0x0000|0|Rekla"
        $asGUI_Element[14] = "Inputbox014=|270|320|500| 22|L|0x0000|0|Zeile 14   |U|   0| 0|130| 22|L|0x0000|0|Projektordner"
        $asGUI_Element[15] = "Inputbox015=|750|475|100| 22|L|0x0000|0|Zeile 15   |L|  -5| 0|110| 22|R|0x0000|0|Gesprächsnotiz"
        $asGUI_Element[16] = "Inputbox016=|750|350|100| 22|L|0x0000|0|Zeile 16   |L|  -5| 0|120| 22|R|0x0000|0|Reparaturbericht"
        $asGUI_Element[17] = "Inputbox017=|750|375|100| 22|L|0x0000|0|Zeile 17   |L|  -5| 0|110| 22|R|0x0000|0|Festnetz"
        $asGUI_Element[18] = "Inputbox018=|750|400|100| 22|L|0x0000|0|Zeile 18   |L|  -5| 0|110| 22|R|0x0000|0|Mobil-Nr."
        $asGUI_Element[19] = "Inputbox019=|750|425|100| 22|L|0x0000|0|Zeile 19   |L|  -5| 0|110| 22|R|0x0000|0|E-Mail"
        $asGUI_Element[20] = "Inputbox020=|750|450|100| 22|L|0x0000|0|Zeile 20   |L|  -5| 0|110| 22|R|0x0000|0|Status"
        $asGUI_Element[21] = "Inputbox021=|270| 10|250| 22|L|0x0000|0|Zeile 21   |L|   0| 0| 70| 22|R|0x0000|0|Suche:"
        $asGUI_Element[22] = "Groupbox001=| 64|475|200|100|L|0x0000|0|Adressdaten|R|   0| 0| 70| 22|L|0x0000|0|"
        $asGUI_Element[23] = "Editbox001= |895|400|217|160|L|0x0000|0|Memo       |U|  -5| 0| 70| 22|L|0x0000|0|Gesprächsnotiz"
        ; --- GUI-Parameter der Input-Boxen und deren Labels ------------------------------------------------------------/
    
    
        For $iGUI_ElementNr = Ubound($asGUI_Element)-1 to 0 Step -1
          IniWriteSection($sIniFilename, "GUI-Parameter", $asGUI_Element[$iGUI_ElementNr])
        Next
       ;EndIf
    
    
    $aCtrls = IniReadSection($sIniFilename, "GUI-Parameter")
    
    
    
    
    
    
    #cs
    ;$aCtrls = IniReadSection($sIni, "Moveable")
    If $aCtrls[0][0] > 0 Then
    	_ArrayColInsert($aCtrls, 2)
    	_ArrayColInsert($aCtrls, 2)
    	_ArrayColInsert($aCtrls, 2)
    	_ArrayColInsert($aCtrls, 2)
    	_ArrayColInsert($aCtrls, 2)
    	_ArrayColInsert($aCtrls, 2)
    	For $iCtrl = 1 To $aCtrls[0][0]
    		$aSplit = StringSplit($aCtrls[$iCtrl][1], '|')
    		For $iCol = 1 To $aSplit[0]
    			$aCtrls[$iCtrl][$iCol] = $aSplit[$iCol]
    		Next
    	Next
    EndIf
    $aCtrls[0][1] = "Text"
    $aCtrls[0][2] = "left"
    $aCtrls[0][3] = "Top"
    $aCtrls[0][4] = "width"
    $aCtrls[0][5] = "height"
    $aCtrls[0][6] = "Style"
    $aCtrls[0][7] = "ID"
    
    
    _ArrayDisplay($aCtrls)
    #ce
    
    
    
    
    
    
    
    
    
    
    
    
    ;_ArrayDisplay($asGUI_Element, "Array-Inhalt") ; Debugausgabe (besserer Ersatz für MsgBox, um ein ganzes Array auf einen Schlag anzeigen zu lassen).
    
    
    ; --- Input-Boxen (und Labels) für Datenbankfelder --------------------------------------------------------------\
    Global $avGUI_Parameter[19]  ;Anzahl der Parameter eines Parametersatzes.
    Global $sF_Obj
    Global $iX_Obj, $iY_Obj, $iW_Obj, $iH_Obj, $hE_Obj, $sT_Obj
    Global $sA_Lbl, $sA_LblTxt
    Global $iX_Lbl, $iY_Lbl, $iW_Lbl, $iH_Lbl, $hE_Lbl, $sT_Lbl
    Global $iStrgW
    Global $iXOffsetLabelToElement[$iAnzahlGUIElemente], $iYOffsetLabelToElement[$iAnzahlGUIElemente]  ;Zwei Arrays, die den Offset zwischen Obekt und Label speichern.
    
    
    For $iGUI_ElementNr = 0 to Ubound($asGUI_Element)-1  ;30 Zeilen
      ; --- Pro Schleifendurchlauf die Parameter je eines GUI-Elements auslesen --------------------------------\
      $avGUI_Parameter=Stringsplit($asGUI_Element[$iGUI_ElementNr], "|")    ;Aufgesplittete Parameter
      ;MsgBox(0,"",$avGUI_Parametersatz[2])
    
    
      $sF_Obj = StringStripWS ($avGUI_Parameter[1], 3)    ;Funktion des Objektes (von Leerzeichen links und Rechts befreit)
    
    
      $iX_Obj = $avGUI_Parameter[2]            ;X-Position des Objektes
      $iY_Obj = $avGUI_Parameter[3]            ;Y-Position des Objektes
      $iW_Obj = $avGUI_Parameter[4]            ;Weite des Objektes
      $iH_Obj = $avGUI_Parameter[5]            ;Höhe des Objektes
      $hE_Obj = $avGUI_Parameter[6]            ;Erweiterte Parameter, siehe AutoIt Help: GUICtrlCreateLabel, bzw. GUI Control Styles
      $sT_Obj = $avGUI_Parameter[9]            ;Textvorbelegung (wenn Inputbox)
    
    
      $sA_Lbl = $avGUI_Parameter[10]           ;Positionsangabe, bezogen auf das Objekt: "L"=Links / "U"=Unten / "R"=Rechts / "O"=Oben.
    
    
      $iX_Lbl = $avGUI_Parameter[11] ; + $iX_Obj  ;X-Position des Labels
      $iY_Lbl = $avGUI_Parameter[12] ;+ $iY_Obj  ;Y-Position des Labels
      $iW_Lbl = $avGUI_Parameter[13]           ;Weite des Labels
      $iH_Lbl = $avGUI_Parameter[14]           ;Höhe des Labels
      $sA_LblTxt= $avGUI_Parameter[15]         ;Ausrichtung des Labeltextes (linksbündig/rechtsbündig)
      $hE_Lbl = $avGUI_Parameter[16]           ;Erweiterte Parameter, siehe AutoIt Help: GUICtrlCreateLabel, bzw. GUI Control Styles
      $sT_Lbl = $avGUI_Parameter[18]           ;Text des Labels
    
    
      $iStrgW=Stringbreite($sT_Lbl)            ;Breite des vordefinierten Label-Strings in Pixeln.
      ; --- Pro Schleifendurchlauf die Parameter je eines GUI-Elements auslesen --------------------------------/
    
    
      ; --- Positionen der Labels (in Bezug auf deren Inputboxen), sowie deren Textausrichtung festlegen -------\
      Select   ;Label-Position (L/U/R/O) und Textausrichtung (L/R) des Labels
      Case $sA_Lbl="L" and $sA_LblTxt="L"     ;LL - Labelposition (L)inks, Textausrichtung (L)inksbündig
        $iX_Lbl = $iX_Obj + $iX_Lbl - $iW_Lbl
        $iY_Lbl = $iY_Obj + $iY_Lbl
    
    
      Case $sA_Lbl="L" and $sA_LblTxt="R"     ;LR - Labelposition (L)inks, Textausrichtung (R)echtsbündig
        $iX_Lbl = $iX_Obj + $iX_Lbl - $iW_Lbl ; + $iStrgW
        $hE_Lbl=BitOR($hE_Lbl, 0x0002)
        $iY_Lbl = $iY_Obj + $iY_Lbl
    
    
      Case $sA_Lbl="U" and $sA_LblTxt="L"     ;UL - Labelposition (U)nten, Textausrichtung (L)inksbündig
        $iX_Lbl = $iX_Obj + $iX_Lbl
        $iY_Lbl = $iY_Obj + $iY_Lbl + $iH_Obj
    
    
      Case $sA_Lbl="U" and $sA_LblTxt="R"     ;UR - Labelposition (U)nten, Textausrichtung (R)echtsbündig
        $iX_Lbl = $iX_Obj + $iX_Lbl + $iW_Obj - $iW_Lbl
        $hE_Lbl=BitOR($hE_Lbl, 0x0002)
        $iY_Lbl = $iY_Obj + $iY_Lbl + $iH_Lbl
    
    
      Case $sA_Lbl="R" and $sA_LblTxt="L"     ;RL - Labelposition (R)echts, Textausrichtung (L)inksbündig
        $iX_Lbl = $iX_Obj + $iX_Lbl + $iW_Obj
        $iY_Lbl = $iY_Obj + $iY_Lbl
    
    
      Case $sA_Lbl="R" and $sA_LblTxt="R"     ;RR - Labelposition (R)echts, Textausrichtung (R)echtsbündig
        $iX_Lbl = $iX_Obj + $iX_Lbl + $iW_Obj ;- $iW_Lbl
        $hE_Lbl=BitOR($hE_Lbl, 0x0002)
        $iY_Lbl = $iY_Obj + $iY_Lbl
    
    
      Case $sA_Lbl="O" and $sA_LblTxt="L"     ;OL - Labelposition (O)ben, Textausrichtung (L)inksbündig
        $iX_Lbl = $iX_Obj + $iX_Lbl
        $iY_Lbl = $iY_Obj + $iY_Lbl - $iH_Lbl
    
    
      Case $sA_Lbl="O" and $sA_LblTxt="R"     ;OR - Labelposition (O)ben, Textausrichtung (R)echtsbündig
        $iX_Lbl = $iX_Obj + $iX_Lbl ;+ $iW_Lbl
        $hE_Lbl=BitOR($hE_Lbl, 0x0002)
        $iY_Lbl = $iY_Obj + $iY_Lbl - $iH_Obj
    
    
      EndSelect
      ; --- Positionen der Labels (in Bezug auf deren Inputboxen), sowie deren Textausrichtung festlegen -------/
    
    
      if StringLeft($sF_Obj, 8)="Inputbox" then
      ;if $GUIElement_Nr=1 Then  ;Die erste Inputbox enthält die ID des Datensatzes. Daher auf nicht editierbar schalten.
         ;BitXOR $ES_READONLY
        ;EndIf
        $aHandleGUIElement[$iGUI_ElementNr] = GUICtrlCreateInput($sT_Obj, $iX_Obj, $iY_Obj, $iW_Obj, $iH_Obj, $hE_Obj, 0)   ;Inputbox
      EndIf
    
    
      if StringLeft($sF_Obj, 8)="Groupbox" then
        $aHandleGUIElement[$iGUI_ElementNr] = GUICtrlCreateGroup($sT_Obj, $iX_Obj, $iY_Obj, $iW_Obj, $iH_Obj)
      EndIf
    
    
      if StringLeft($sF_Obj, 7)="Editbox" then
        $aHandleGUIElement[$iGUI_ElementNr] = GUICtrlCreateEdit($sT_Obj, $iX_Obj, $iY_Obj, $iW_Obj, $iH_Obj)
      EndIf
    
    
    ; --- Label erzeugen -----------------------------------------------------------------------------\
      $aCtrlLabel[$iGUI_ElementNr] = GUICtrlCreateLabel($sT_Lbl, $iX_Lbl, $iY_Lbl, $iW_Lbl, $iH_Lbl, $hE_Lbl, 0)   ;Label, zugehörig zu obiger Inputbox.
      GUICtrlSetFont($aCtrlLabel[$iGUI_ElementNr], 12, 400, 0, "Arial")
      GUICtrlSetFont($aHandleGUIElement[$iGUI_ElementNr], 12, 400, 0, "Arial")
    ; --- Label erzeugen -----------------------------------------------------------------------------/
    
    
      $iXOffsetLabelToElement[$iGUI_ElementNr] = $iX_Obj - $iX_Lbl
      $iYOffsetLabelToElement[$iGUI_ElementNr] = $iY_Obj - $iY_Lbl
    
    
    Next
    ; --- Input-Boxen (und Labels) für Datenbankfelder --------------------------------------------------------------/
    GUICtrlSetFont(-1, 12, 400, 0, "Arial")
    
    
    EndFunc  ;==> IniRead
    ; #############################################################################
    Func Optionen()
      ;MsgBox(0, "Optionen", "Hallo")
      ;$aHandleGUIElement[$iGUI_ElementNr]
      $bGUIRedesign = BitXOR($bGUIRedesign, 0x1)  ;Binärwert von $bGUIRedesign toggeln.
      if $bGUIRedesign=1 then   ;Im Menü wurde der Eintrag zum Umgestalten des GUI aktiviert.
        MsgBox(0, "", "" _
        & "Sie können nun einzelne Bedienelemente" _
        & @CRLF & "mit der Maus verschieben." _
        & @CRLF & "Zum Beenden diesen Menüeintrag erneut anwählen!")
      EndIf
    EndFunc
    ; #############################################################################
    FUNC GUI_Redesign()
      Local $iNewX, $iNewY
      $sUserMessageNew=""
    
    
      ; --- Ermitteln, über welchem GUI-Element der Hauszeiger hoovert. ------------------------------------------------------------\
      if $iDoItOnlyOnce = 0 then   ;Null, wenn gerade kein GUI-Element mit der Maus angewählt ist. Andernfalls Eins.
        For $iGUI_ElementNr = 0 to Ubound($asGUI_Element)-1   ;Alle GUI-Elemente im Array durchlaufen.
          ;ConsoleWrite("Nr.: " & $iGUI_ElementNr & @CRLF)
          $aiGUIElementXYWH = ControlGetPos($FormKombiansicht, "", $aHandleGUIElement[$iGUI_ElementNr])  ;Pro Durchlauf die X/Y-Position eines GUI-Elements ermitteln
          if not @error and $sMausXY[0] > $aiGUIElementXYWH[0] and $sMausXY[0] < ($aiGUIElementXYWH[0]+$aiGUIElementXYWH[2])  and  $sMausXY[1] > $aiGUIElementXYWH[1] and $sMausXY[1] < ($aiGUIElementXYWH[1]+$aiGUIElementXYWH[3])then
            ; --- Das GUI-Element unter dem Mauszeiger wurde gefunden! --------------------------------------------------------\
    		$sUserMessageNew="Feld-Nr. " & $iGUI_ElementNr
    		$hActualGUIElement = $aHandleGUIElement[$iGUI_ElementNr]         ;Das Handle des GUI-Elements unter dem Mauszeiger.
    		$hActualLabel = $aCtrlLabel[$iGUI_ElementNr]                     ;Das Handle des an das GUI-Element angeheftete Label.
    		$iActualGUINumber = $iGUI_ElementNr                              ;Die Nummer des GUI-Elements im Array aller GUI-Elemente.
    		$iXOffsetGUIElementToMouse = $sMausXY[0] - $aiGUIElementXYWH[0]  ;Der X-Offset des GUI-Elemnts zur Maus, im Moment des Linksklicks.
    		$iYOffsetGUIElementToMouse = $sMausXY[1] - $aiGUIElementXYWH[1]  ;Der Y-Offset des GUI-Elemnts zur Maus, im Moment des Linksklicks.
    		$iDoItOnlyOnce = 1   ;Verhindert erneuten Schleifenaufruf, so lange die linke Maustaste gedrückt bleibt (nachdem das GUI-Element nun ja gefunden wurde).
            ExitLoop
            ; --- Das GUI-Element unter dem Mauszeiger wurde gefunden! --------------------------------------------------------/
          EndIf
        Next
      EndIf
      ; --- Ermitteln, über welchem GUI-Element der Hauszeiger hoovert. ------------------------------------------------------------/
    
    
      if $sUserMessageNew <> $sUserMessageOld then
        _GUICtrlStatusBar_SetText($idStatusbar, $sUserMessageNew, 1)
        $sUserMessageOld=$sUserMessageNew
      EndIf
    
    
      ; --- So lange die linke Maustaste gedrückt ist, folgen das gewählte GUI-Element und dessen Label dem Mauszeiger ---\
      if $iMouseButtonLeft then
        $iNewX = $sMausXY[0] - $iXOffsetGUIElementToMouse   ;Die neue X-Position des GUI-Elements.
    	$iNewY = $sMausXY[1] - $iYOffsetGUIElementToMouse   ;Die neue Y-Position des GUI-Elements.
        GUICtrlSetPos($hActualGUIElement, $iNewX, $iNewY)   ;GUI-Element an die neue Position verschieben.
    	GUICtrlSetPos($hActualLabel, $iNewX - $iXOffsetLabelToElement[$iActualGUINumber], $iNewY - $iYOffsetLabelToElement[$iActualGUINumber])    ;Angeheftetes Label ebenfalls mit verschieben.
      Else
    	$iDoItOnlyOnce = 0   ;Maustaste wurde losgelassen - Vorbereitung für das Verschieben des nächsten Elements (obige For-Schleife kann wieder betreten werden).
      EndIf
      ; --- So lange die linke Maustaste gedrückt ist, folgen das gewählte GUI-Element und dessen Label dem Mauszeiger ---/
    EndFunc
    ; #############################################################################
    Func _Exit() ;Datenbank schließen und Programmende.
      _GUICtrlListView_UnRegisterSortCallBack($ListView)
      _SQLite_Close($g_db_Database)
      _SQLite_Shutdown()
      _GDIPlus_ShutDown()
      Exit
    EndFunc   ;==>_Exit
    ; ### Functions ################################################################################################################/
    
    
    ; --- Codeschnippsel-Ablage ---
    ;$maus_x = -(MouseGetPos(0) - $center)
    ;$maus_y = (MouseGetPos(1) - $center)
    ;_GDIPlus_GraphicsDrawLine($hGraphic, $center + $x1, $center + $y1, $center + $x2, $center + $y2, $hPen) ;quadrat
    ; Local $mpos = GUIGetCursorInfo()   ;Mauskoordinaten relativ zum Fenster.
    Alles anzeigen
  • Hilfe beim Ordner durchsuchen und löschen der Dateien

    • Code-Jack
    • 10. Juni 2016 um 14:12

    Vielleicht überhaupt der Hinweis auf den Befehl _FileListToArrayRec.
    In der AutoIt Help findet sich zu diesem Befehl ein leicht verständliches, kompaktes und direkt lauffähiges Example, wo die jeweiligen Resultate ratzfatz in einer Tabelle dargestellt werden, mittels _ArrayDisplay().

    Keine Angst, da wird nichts gelöscht, sondern nur die Liste angezeigt, entsprechend der jeweiligen Parameter.

    Etwas damit herumspielen, bis alle Einstellungen stimmen, so dass die Ergebnisliste korrekt das zeigt, was man löschen möchte. Dann erst den Befehl zum Löschen einbauen, wie GerhardSchr es demonstriert.
    So kann nichts in die Hose gehen, durch eventuell falsch gesetzte Parameter.


    Edit: Oh, autoBert hat weiter oben ja bereits darauf hingewiesen ...

  • Bestimmte Werte durch andere ebenfalls bestimmte Werte ersetzen

    • Code-Jack
    • 8. Juni 2016 um 23:19

    Oohhh, das verlinkte Tutorial sieht ja auf den ersten Blick wirklich großartig aus!
    Vielen Dank für den Hinweis; da hat SEuBo aber heftig Arbeit reingesteckt, Respekt!!! :thumbup:

    Und Dir, Xorinator: Herzlichen Glückwunsch zum 2000sten Beitrag! :thumbup:


    Edit: wobei es wahrscheinlich schon längst mehr als 2000 sind. Ich habe ja angeblich erst 20 ...

  • Bestimmte Werte durch andere ebenfalls bestimmte Werte ersetzen

    • Code-Jack
    • 8. Juni 2016 um 22:38

    Zweifellos wird der Code dadurch kompakter. Meinetwegen auch "eleganter". Aber einfacher???
    Ich persönlich finde RegEx ja reichlich "advanced".
    Also bis man da durchsteigt ...

    Ich staune immer wieder, was damit alles geht, in verblüffend kompakter Form. Nur kann ich solchen Code nicht mal lesen. Meine eigenen Experimente damit waren schon immer ein frustrierendes, extrem fehlerträchtiges Herumprobieren, ohne den Hauch eines Durchblicks, was da passiert.

    Aber danke für den Einwurf; für fortgeschrittenere Programmierer ist das ein guter Hinweis, um die eigenen Fähigkeiten zu erweitern.

  • Bestimmte Werte durch andere ebenfalls bestimmte Werte ersetzen

    • Code-Jack
    • 8. Juni 2016 um 20:26

    Datei laden und jede Zeile mit StringSplit zerlegen (siehe AutoIt Help).
    Resultat ist ein Array mit so vielen Einträgen, wie du Spalten hast.

    Für weitgehend mundfertige Beispiele suche im Forum mal nach "Ini-Datei" und "CSV". Da findest Du Beispiele, wie man Dateien lädt, zerlegt und wieder speichert.

    Dann müssen nur noch, in einer Schleife, die Werte ausgetauscht werden, was wohl keine Probleme bereiten sollte, wenn Du schon mal mit Arrays gearbeitet hast.

  • Koordinaten einer InputBox auslesen

    • Code-Jack
    • 8. Juni 2016 um 18:03

    Vielen Dank, autoBert!

    ControlGetPos war der entscheidende Hinweis, der mir fehlte.
    Trotz viieel RTFM war mir der entgangen, habe immer woanders gesucht.

    Ich habe diesen einen Befehl in meinen Code eingeflochten und kann nun wunderbar sämtliche Controls (nicht nur 9) mit der Maus verschieben.
    Es gibt nur noch etwas Optimierungsbedarf bezüglich der Geschwindigkeit, aber das bekomme ich selbst hin.

    Wenn ich den Code etwas aufgeräumt (und um 'n Biserle Schnickschnack ergänzt) habe, stelle ich meine Lösung hier ein.

    Nochmals vielen Dank!

  • Forum Problemsammlung

    • Code-Jack
    • 8. Juni 2016 um 06:19

    OK, jetzt verstanden, was mit "</> Button" gemeint war. Genau der, den ich auch verwendet hatte (der also Code-Tags einfügt).

    Ich sollte dazu sagen, dass die Bildschirmdarstellung dieses Forums bei mir völlig im Dutt ist (siehe Anhang), weswegen ich mich im Editor rein an den (leider nur manchmal) eingeblendeten Tooltips orientiere, wenn ich mit der Maus über die Bedienelemente fahre.

    Gut, zukünftig dann in Code-Tags, mit der Syntax-Hervorhebung "AutoIt".
    Zwischenablage.jpg

  • Best Practise: Dokumente als Ausgabe generieren

    • Code-Jack
    • 8. Juni 2016 um 06:02

    Und weil es bei chesstigers Fragestellung ja nicht ausschließlich um Rechnungen ging, will ich noch eine weitere (wenn auch leicht beknackte) Idee zumindest mal in den Raum werfen:

    Man programmiere in AutoIt - zusätzlich zu der Maske, in der die Daten eingepflegt werden - noch eine weitere GUI, in die am Ende die Daten WYSIWYG-mäßig einfließen.
    Und von der wird dann automatisch ein Screenshot erstellt!

    Die GUI für die Datenausgabe sollte möglich größer sein, als der eigene Bildschirm. Folglich muss der Screenshot mit raffinierteren Methoden erfolgen, als als dem "Abfotografieren" des sichtbaren Bereichs, denn die GUI ist ja größer.
    Warum größer?
    - Na, damit man später mit guter Qualität ins Bild zoomen kann.

    Damit ist der fette Nachteil bereits erwähnt: Die so erzeugten Dateien werden groß.
    Aber insbesondere wenn es vorrangig um die Erzeugung von Papierdokumenten geht, wäre dieser Weg absolut brauchbar. Das erzeugte Bild wird dabei nur temporär erzeugt, um es direkt auszudrucken. Danach wird es automatisch gelöscht; es kann bei Bedarf ja per Knopfdruck jederzeit neu erzeugt werden.

    Vorteil dieser etwas schrägen Methode: Die Erzeugung des Dokuments ist besonders einfach. Man muss sich nicht mit HTML/CSS, oder PDF, oder sonstigen Dateiformaten herumplagen; sondern man wendet nix als AutoIt an!
    Das erzeugte Datenformat sieht auch in elektronischer Form (also nicht nur auf Papier) garantiert überall gleich aus; was mit anderen Formaten (insbesondere HTML/CSS) doch eher schwierig zu gewährleisten ist.
    Außerdem müssen keine Fremdprodukte installiert werden, wie der von Peter S. Taler erwähnte, virtuelle PDF-Druckerteiber.

    Im Grunde tut Windows beim Drucken nicht viel anderes. In der guten, alten Zeit wurde noch simples ASCII zum Drucker geschickt. Doch heutzutage erzeugt praktisch jeder Druckertreiber sogar für Textdokumente eine Grafik, die dann zum Drucker gespoolt wird.


    Fazit:

    • Für Rechnungen dürfte ZugFeRD wirklich das Mittel der Wahl sein.
    • Und die simple HTML-Ausgabe hat heutzutage natürlich ebenfalls ihren unbestreitbaren Nutzen.
    • Aber für Papierdokumente, oder echtes WYSIWYG (bei jedem Endbetrachter), kommt die wie beschrieben programmierte Grafik ins Spiel.
  • Best Practise: Dokumente als Ausgabe generieren

    • Code-Jack
    • 8. Juni 2016 um 02:49

    Habe inzwischen mal nach geeigneten HTML/CSS-Vorlagen für die Rechnungserstellung recherchiert und stieß dabei auf "ZugFeRD".

    Fazit: DAS ist es.
    Hier ein paar Links zum Einlesen:

    http://www.golem.de/news/pdf-und-x…406-107463.html

    http://www.flowmanager.eu/aus-der-praxis…earbeitung.html

    https://de.wikipedia.org/wiki/ZUGFeRD

    Bei dem Wiki-Artikel beachte man den ersten Link in den Einzelnachweisen. Das ausführliche PDF erklärt auf 132 Seiten neben dem Datenformat noch allerlei weitere Aspekte, die bei der Anwendung zu beachten sind.

  • Koordinaten einer InputBox auslesen

    • Code-Jack
    • 8. Juni 2016 um 00:26

    Obiges Posting bearbeitet, nun außschließlich in Code-Tags.

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™