Ich wünsche euch allen ein frohes Weihnachtsfest (Ja, schon zu spät ) und ein glückliches neues Jahr!
Dafür gibt es von mir ein, ausführlich kommentiertes, AutoIt-Script, damit AutoIt-Anfänger etwas lernen können.
Diese kleine UDF enthält 8 Funktionen (BitAND, BitOR, BitNOT, BitROL, BitROR, BitSHL, BitSHR, BitXOR) zum bearbeiten von Integerzahlen im 64-Bit-Format.
Das sind 8 Assembler-Funktionen, die da aufgerufen werden. Das AutoIt-Script muss aber im 64-Bit-Modus laufen (siehe Example).
Edit 26.12.2018: Neue Version
- Bei AND, OR und XOR können nun bis zu 8 Parameter direkt im Funktionsaufruf übergeben werden. Wer mehr Parameter benötigt, muss sie als Array in Parameter Eins übergeben.
- Es gibt jetzt noch zwei Hilfsfunktionen "_BitRotate64" und "_BitShift64" in Anlehnung an die originalen Funktionen. Allerdings einheitlich (im Gegensatz zu den originalen Funktionen): mit negativen Werten nach links und positiven Werten nach rechts.
Edit 27.12.2018: Neue Version
- OnAutoItExitRegister erst nach der Deklaration der globalen Variablen
- Die Anforderung des Speichers geschieht jetzt in einer Funktion: "__BitOp64OnStart"
- Fehler behoben bei "_BitRotate64" und "_BitShift64", wenn 0 für Rotate oder Shift übergeben wurde.
- Fehler behoben bei "_BitROx64" und "_BitSHx64". Der Parameter-Aufruf war falsch rum.
- Das Beispiel-Script komplett überarbeitet und aufgeräumt.
Eine Stoppuhr (Stunden:Minuten:Sekunden Millisekunden), deren Ziffern einzeln angesteuert werden, damit die Anzeige nicht flackert.
Und damit das Ganze etwas schöner aussieht habe ich einen 7-Segment-Font für die Anzeige verwendet. Screenshot:
Ich habe mal wieder ein kleines Spiel programmiert. Einen MasterMind-Clone.
Ich nenne es MasterCode. Falls das Spiel nicht bekannt ist, hier die
Spielregeln:
Bei Spielstart generiert das Programm einen 4stelligen Code aus 6 Farben (Doppelte sind erlaubt). Diese sind ganz oben zu sehen (natürlich erstmal verdeckt).
Der Spieler muss nun versuchen diesen Code zu erraten. Dazu kann er mit den Buttons am unteren Spielfeldrand einen Code eingeben.
Wenn man versehentlich eine "falsche" Farbe angeklickt hat, so gibt es den "Undo"-Button auf der rechten Seite, mit der man die letzte Eingabe zurücknehmen kann.
Sind die 4 Felder gefüllt, erscheint ein "Haken"-Button, den man zur Bestätigung des Code anklicken muss.
Nach der Bestätigung wertet das Programm die Spieler-Eingabe aus. Für jede richtige Farbe, die dazu am richtigen Platz steht, bekommt man einen schwarzen Pin. Für jede richtige Farbe, die aber am falschen Platz steht, bekommt man einen weißen Pin.
Kein Pin heißt, alle Farben sind falsch. Vier schwarze Pins markieren das Spielende (logischerweise), denn dann hat man den Code ja erraten.
Insgesamt hat man 12 Versuche. Wenn man den Code bis dahin nicht erraten hat, hat man das Spiel verloren.
Das Spiel passt sich automatisch in der Größe dem Monitor an, von dem es gestartet wird (Mausposition).
Ich habe das mit diversen Auflösungen getestet (von 640x480 bis 2560x1440). Es sollte aber auch mit noch höheren Auflösungen funktionieren. Bei den niedrigen Auflösungen sieht das Ganze nicht so schön aus, weil die Grafiken alle extrem runterskaliert werden müssen.
Aber ich denke, dass die meisten wohl über Monitore von 1024x768 und darüber verfügen werden.
Screenshot:
Im ZIP-Archiv (Anhang) findet ihr das Script, sowie alle benötigten Includes. Die Grafiken sind wieder BASE64-Codiert in "Ressources.au3".
Eine kleine UDF zum andocken eines (oder mehrerer) Fenster am Bildschirmrand (bzw. an der Taskleiste).
Das funktioniert auch mit mehreren Bildschirmen.
Version 1.1.0.0 (08.07.2018):
- Auswertung jetzt mit $WM_WINDOWPOSCHANGING statt $WM_WINDOWPOSCHANGED. Kein Flackern mehr! Danke Bitnugger!
- Wegen $WM_WINDOWPOSCHANGING funktioniert jetzt das "weiterziehen" mit der Maus nicht mehr, um auf einen anderen Bildschirm zu kommen.
Deswegen habe ich jetzt einen Hotkey: <CTRL> eingebaut. Wird die CTRL-Taste während des ziehens gedrückt gehalten, so kann man das Fenster auf den anderen Bildschirm ziehen.
- Es gibt jetzt einen "magnetischen Rahmen" (50 Pixel). Wird das Fenster in diesen Bereich bewegt, wird es an den Rand gezogen.
Version 1.2.0.0 (08.07.2018):
- Die UDF nochmal komplett umgestaltet (auf globales 2D-Array). Da waren ein paar blöde Bugs drin. Danke Bitnugger!
- Eine neue Funktion "_WindowDocking_SetMagneticBorder", mit der man den "MagneticBorder" auf eine beliebige Pixelzahl einstellen kann (siehe Example).
Version 1.3.0.0 (09.07.2018):
- Es gab noch einen Fehler, wenn man ein Fenster mit eingeschalteten Docking gelöscht hat (GuiDelete). Dabei wurde die WindowProc nicht wieder auf den alten Wert gesetzt und AutoIt stürzte ab. Behoben!
- Bei der Array-Verwaltung (globales 2D-Array) war noch ein Fehler drin (falsch dimensioniert). Behoben!
- Die "CTRL-Tasten-Methode" zum verschieben auf einen anderen Bildschirm habe ich jetzt doch standardmäßig auf die "Zwei-Maustasten-Methode" umgestellt. Das Fenster nur mit der Maus zu verschieben ist doch benutzerfreundlicher.
- In Version v3.3.14.5 von AutoIt gibt es die Konstanten $SM_CXSIZEFRAME und $SM_CYSIZEFRAME, deshalb ist die zusätzliche Definition überflüssig.
- Das Beispiel öffnet jetzt 3 Fenster und man kann jedes Fenster einzeln konfigurieren.
Version 1.4.0.0 (11.07.2018):
- Wenn man ein Docking-Fenster auf einen zweiten Bildschirm geschoben hat und das Fenster minimiert und dann wieder restored hat, dann wurde es auf dem Hauptbildschirm "festgehalten". Behoben!
- Es gibt eine neue Funktion "_WindowDocking_SetVisible" (damit wird das Fenster auf dem am naechsten liegenden Bildschirm zentriert, wenn sich das Fenster außerhalb des Desktopbereichs befindet).
- Die Abfrage der rechten Maustaste (zum vorübergehenden ausschalten des Dockings) übernimmt jetzt die Funktion "_RMBpressed()". Im Gegensatz zu "_isPressed" wird damit die virtuelle (statt der physikalischen) rechte Maustaste abgefragt.
- Das Beispielscript "WindowDocking_Example.au3" um ein Beispiel für die neue Funktion erweitert.
Mit dieser kleinen Funktion kann man einem PIC-Control (GuiCtrlCreatePic) oder einem Button (GuiCtrlCreateButton) ein beliebiges Bild zuweisen (alle von GDI+ unterstützten Grafikformate).
- Dabei werden Bilder, die größer als das PIC-Control sind, proportional auf die Größe des PIC-Controls herunterskaliert.
- Die Bilder werden immer horizontal/vertikal zentriert angezeigt.
- Die Grafikdatei kann entweder als GDI+ Bitmap, als Dateiname oder als Binärdaten übergeben werden. So kann man auch den File to Base64 String Code Generator von UEZ benutzen, um Bilder direkt ins Script einzubinden.
- Man kann mit der Funktion auch Buttons ein Bild oder ein Bild und Text zuweisen.
- Wenn dem Button nur ein Bild zugewiesen wird, dann wird es entsprechend der Höhe proportional skaliert zentriert auf den Button angezeigt.
- Wenn Bild und Text zugewiesen werden, kann man angeben, ob der Text links ($GCSIE_LEFT) oder rechts ($GCSIE_RIGHT) vom Bild angezeigt werden soll (siehe Example.au3).
In dem Beispiel-Script sind zwei Bilder als Binärdaten enthalten, die mit dem erwähnten Code-Generator erstellt wurden.
Ansonsten sollte das Beispiel und die Kommentare die Anwendungsmöglichkeiten verdeutlichen.
Für meine Digitaluhr habe ich ja die Alarmzeit per MouseWheel einstellbar gemacht.
Falls ihr so etwas auch machen wollt, hier mal ein kleines, kommentiertes Minimal-Beispiel:
Global $hGui = GUICreate('Zeit ändern per MouseWheel', 350, 200)
Global $aidClock[3]
For $i = 0 To 2
$aidClock[$i] = GUICtrlCreateLabel('00', 60 + $i * 80, 20, 50, 44)
GUICtrlSetFont(-1, 32, 800, 0, 'Courier New')
Next
GUICtrlCreateLabel(':', 112, 20, 26, 44)
GUICtrlSetFont(-1, 32, 400, 0, 'Courier New')
GUICtrlCreateLabel(':', 192, 20, 26, 44)
GUICtrlSetFont(-1, 32, 400, 0, 'Courier New')
GUISetState()
GUIRegisterMsg($WM_MOUSEWHEEL, '_WM_MOUSEWHEEL')
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
Func _WM_MOUSEWHEEL($hWnd, $iMsg, $wParam, $lParam)
Local Const $aMaxVal[3] = [23, 59, 59], $iWheelDelta = 120
Local $iWheel, $aGuiInfo, $iIndex, $iValue
$iWheel = _WinAPI_HiWord($wParam) / $iWheelDelta ; HiWord(wParam) / WheelDelta ergibt down = -1, up = 1
$aGuiInfo = GUIGetCursorInfo($hWnd) ; $aGuiInfo[4] enthaelt die Ctrl-ID vom Control unter dem Mauszeiger
$iIndex = $aGuiInfo[4] - $aidClock[0] ; minus der Ctrl-ID vom ersten Label ergibt 0...2 fuer die Clock-Labels
If $iIndex < 0 Or $iIndex > 2 Then Return $GUI_RUNDEFMSG ; wenn Mauszeiger ausserhalb, dann Funktion verlassen
$iValue = GUICtrlRead($aidClock[$iIndex]) + $iWheel ; Wert auslesen und Wheelwert (-1 oder 1) addieren
If $iValue > $aMaxVal[$iIndex] Then $iValue = 0 ; wenn neuer Wert groesser als Maximalwert, dann 0
If $iValue < 0 Then $iValue = $aMaxVal[$iIndex] ; wenn neuer Wert kleiner als 0, dann Maximalwert
_WinAPI_LockWindowUpdate($hWnd) ; WindowUpdate blockieren (verhindert das flackern beim aendern der Werte)
GUICtrlSetData($aidClock[$iIndex], StringFormat('%02i', $iValue)) ; neuen Wert setzen
_WinAPI_LockWindowUpdate(0) ; WindowUpdate wieder freigeben
Return $GUI_RUNDEFMSG
EndFunc ;==>_WM_MOUSEWHEEL
Diese vierte Version meiner Digitaluhr ist ziemlich speziell auf meine Anforderungen ausgerichtet, deswegen weiß ich gar nicht, ob ihr damit etwas anfangen könnt.
Das geht schon mit der Größe des Fensters los (400 x 743 Pixel plus Rahmen). Das mag manchem zu groß für eine Uhr sein, aber mein Programm ist ja auch nicht nur eine Uhr.
Vielleicht sollte ich erstmal aufzählen, was mein Programm alles anzeigt.
Liste der Anzeigen:
- Uhrzeit
- Datum
- Wochentag (ausgeschrieben)
- Wochennummer
- Die deutschen Feiertage (alle, auch wenn sie nicht das eigene Bundesland betreffen)
- Zwei Alarmzeiten (Anzeige umschaltbar)
- Vier Abfalltonnen (Altpapier, Gelber Sack, Restmüll, O-Tonne)
- Sommerzeit (Beginn und Ende)
- Sonnenaufgang und -untergang (Zeiten)
- Countdown bis zum nächsten Urlaub (in Tagen, Stunden und Minuten)
- Jahreszeitgrafik
- den Beginn der 4 Jahreszeiten (Datum und Uhrzeit)
- Monatskalender (aktueller Monat) mit Markierung von Geburts-, Hochzeits- und Jahrestagen
Abfalltonnen:
Das mit den Abfalltonnen habe ich aufgenommen, weil ich mir immer nicht merken kann, welche Tonnen am nächsten Freitag abgeholt werden. Aber gerade das ist vermutlich regional sehr verschieden. Hier bei uns ist das so, dass Altpapier und Gelber Sack jede Woche (Freitags) abgeholt werden, Restmüll alle 14 Tage und die O-Tonne alle 4 Wochen. Ich habe die Termine aber konfigurierbar gemacht (Konfigurationsfenster). Da kann man einstellen, wann die Tonne das letzte Mal abgeholt wurde und dann ob alle 1, 2 oder 4 Wochen.
Feiertage:
Wenn der heutige Tag auf einen Feiertag fällt, dann wird der entsprechende Feiertag oberhalb der Uhrzeit angezeigt. Außerdem sind die Feiertage im Kalender fett geschrieben und werden als Tooltip angezeigt.
Sonnenaufgang und -untergang:
Diese sind abhängig vom Ort, wo man sich gerade aufhält (Latitude und Longitude). Dafür habe ich eine Datenbank (Geonames) gefunden, in der die Postleitzahlen und die dazugehörigen Positionen abgespeichert sind. Man muss also im Konfigurationsfenster nur die eigene PLZ eintragen und das Programm sucht die dazugehörigen Positionen aus der Datenbank raus. Zur Überprüfung der Daten kann man sie sich bei OpenStreetMap anzeigen lassen (Lupen-Button neben den Positionen).
Die besonderen Tage (Geburts-, Hochzeits- und Jahrestage):
Dabei handelt es sich um Tage, die jedes Jahr wieder eine Bedeutung haben. Sie können im Konfigurationsfenster eingegeben/geändert/gelöscht werden. Sie sind dann im Kalender fett geschrieben und werden als Tooltip angezeigt (wobei die Anzahl der Jahre in Klammern dahinter steht).
Alarmtöne:
Im Konfigurationsfenster lasssen sich die MP3-Dateien für die beiden Alarmzeiten festlegen. Sind dort keine MP3s eingetragen, so wird ein interner Alarmton benutzt.
Tray-Icon:
Zentraler Anlaufpunkt ist das Icon der Digitaluhr im Tray-Bereich. Hier kann man das oben erwähnte Konfigurationsfenster aufrufen, das Programm in den Autostart packen, das Fenster nach vorne holen, die Programminformationen aufrufen und das Programm beenden.
Alarmzeiten:
Die beiden Alarmzeiten lassen sich einstellen, indem man links neben der Uhrzeit auf eine der beiden Uhrensymbole klickt. Es wird dann statt der Uhrzeit die jeweilige Alarmzeit angezeigt und nun kann man mit dem Mausrad die Stunden, Minuten oder Sekunden verstellen (je nachdem, worüber sich der Mauszeiger gerade befindet).
Links neben den Uhrensymbolen befindet sich noch jeweils eine Checkbox. Wenn die Checkbox angehakt ist, dann ist die entsprechende Alarmzeit aktiv.
Wenn eine der beiden Alarmzeiten erreicht wurde (und der Alarm aktiv ist), wird der dazugehörige Alarmton (MP3-Datei) abgespielt und es wird ein Alarmfenster (im Vordergrund) angezeigt.
Der Alarmton wird nur einmal abgespielt (keine Wiederholung) und er kann abgestellt werden, indem man das Alarmfenster schließt. Spätestens nach 10 Minuten wird das Alarmfenster aber auch automatisch geschlossen.
Countdown:
Das Datum und die Uhrzeit für den "Countdown bis zum nächsten Urlaub" kann man mit einem Klick auf das Kalendersymbol (mit dem Fragezeichen) einstellen. Wählt man einen Tag vor dem heutigen Datum, so wird kein Countdown angezeigt.
Zusätzliche Hinweise:
Im ZIP-Archiv (Anhang) befindet sich das Script und alle benötigten Includes. Die verwendeten Grafiken, Sounds und Fonts sind alle BASE64-codiert in "Ressource.au3" enthalten. Das heißt, eigentlich braucht man dann nur noch die Exe-Datei.
Die ganzen Einstellungen und Daten (Geburtstage etc.) werden in einem Unterordner von @AppDataDir gespeichert.
Danksagungen gibt es im Programminformationsfenster. An dieser Stelle aber ein zusätzliches Dankeschön an UEZ ("Base64 String"-Generator) und an BugFix (Feiertagsfunktion) aus dem AutoIt.de-Forum.
Update v4.1 (18.06.2018):
Ich habe vergessen die Wecker-Grafik als BASE64-String in Ressoure.au3 zu packen und im Programm war noch der Link auf den Gfx-Ordner eingetragen (der in der veröffentlichten Version gar nicht existiert).
Bei der Gelegenheit habe ich dann noch das "WNr." gegen "KW" ausgetauscht.
Update v4.2 (20.06.2018):
- Ein kleiner Bug hatte sich in der Konfiguration eingeschlichen. Die neuen Daten wurden zwar gespeichert, aber die Anzeige im Kalender nicht aktualisiert. Behoben!
- Die Alarmzeiten lassen sich nun auch mit den Cursortasten einstellen: <links> und <rechts> zum auswählen von Stunden, Minuten, Sekunden und <oben> und <unten> zum verändern der Werte. Der gerade aktive Wert ist grün unterstrichen. Danke autoBert !
- Die Tooltips zum einstellen der Alarmzeiten ergänzt. Danke autoBert !
- Es gibt jetzt einen Update-Button im Programminformationsfenster. Beim ersten Klick darauf, wird im Internet nachgesehen, ob es eine neue Version gibt. Wenn ja, muss man das eigentliche updaten nochmal bestätigen (kein Auto-Update!). Noch ein Hinweis zum Update:
Das Update ist nur im kompilierten Zustand möglich! Das heißt, es wird auch nur die kompilierte Exe gegen die neue Exe ausgetauscht! Das evtl vorhandene Script und die Includes bleiben die alten. Wer immer das neueste Script haben will, muss sich das hier im Forum holen.
Die Exe-Datei wird von meiner Homepage (technik-hobby.de) per HTTPS geladen und dann gegen die vorhandene Exe ausgetauscht. Der Austausch geschieht mit Hilfe einer temporär erstellten Batchdatei. Es ist also wichtig, dass das Programm Schreibrechte im Programmverzeichnis (@ScritpDir) hat.
Eine "Installation" der Digitaluhr im Programme-Verzeichnis von Windows ist nicht zu empfehlen, weil man dann Administratorrechte für das Update bräuchte. Das halte ich für überflüssig.
Update v4.2.1 (20.06.2018):
- Den Bug mit "_WinAPI_GetVersion()" beseitigt. Danke Bitnugger !
Update 4.3 (25.06.2018):
- Die Updatefunktion hat nun einen TimeOut dazubekommen. Sollte der Download der neuen Version (aus welchen Gründen auch immer) länger als 60 Sekunden dauern, so wird das entsprechend angezeigt.
- Die Progressbar befindet sich nun am unteren Rand vom Programminformationsfenster (kein ProgressOn/-Off mehr).
- Ich habe das komplette Script jetzt umfangreich kommentiert, für den Fall dass jemand irgendeine Funktion des Scripts gebrauchen kann.
- Beim kommentieren sind mir dann noch Code-Optimierungen aufgefallen, die ich gleich eingebaut habe. Somit hat sich am Script so einiges geändert. Am Aussehen aber nicht.
Update 4.3.1 (25.06.2018):
- Das Update war nur für einen internen Test.
Update 4.3.2 (26.06.2018):
- Ein Bug beim Update, wenn das Programm aus dem Autostart gestartet wurde. Dann stimmte das WorkingDir nicht mit dem ScriptDir überein und verursachte einen Fehler. Behoben!
Bei diesem Programm kann man die Zeit zwischen 1 und 99 Minuten einstellen und nach Klick auf [Start] zählt diie Zeit runter bis auf Null.
Die Zeit wird mit einem 7-Segment-Font dargestellt und es gibt eine Progressbar, die entsprechend geleert wird. Wenn Null erreicht wird, ertönt eine Glocke und es erscheint eine MsgBox.
Man kann die Zeit auf 3 verschiedene Arten verstellen:
1. mit den Pfeilen auf der rechten Seite
2. mit den Tasten [up] und [down]
3. mit dem Mausrad (hoch / runter), wenn sich der Mauszeiger über der Zeitanzeige befindet
Die Zeit lässt sich aber nur verändern, wenn der Timer gerade nicht läuft. Der [Reset]-Button setzt die Zeit wieder auf die Ausgangszeit zurück und hält den Timer an.
Die eingestellte Zeit wird in einer Inidatei gespeichert, sodass sie beim nächsten Start wieder zur Verfügung steht.
Screenshot:
Im ZIP-Archiv (Anhang) befindet sich das Script, die UDF, die Exe und das Icon.
Ach ja, schon wieder eine Progressbar.
Ich brauchte etwas Universelleres, als meine bisherigen Progressbars. Vielleicht könnt ihr die UDF ja auch gebrauchen...
Mit dieser UDF kann man:
- die Koordinaten auf der GUI frei wählen
- die Breite und Höhe der Progressbar frei wählen
- die Progressbar horizontal oder vertikal anzeigen lassen
- die Farbe der Progressbar frei wählen
- eine Prozentanzeige anzeigen lassen
- die Prozentanzeige horizontal oder vertikal anzeigen lassen