Bei dieser UDF handelt es sich um einen Kalender, den man auf der eigenen GUI anzeigen lassen kann. Die Abmessungen des Kalenders sind (Breite x Hoehe = 460 x 380 px).
Man kann auch mehrere Kalender auf der GUI erstellen lassen. Im Beispiel-Script habe ich zwei Kalender benutzt.
Die Samstage und Sonntage haben standardmäßig bereits eine andere Farbe als die anderen Wochentage.
Außerdem kann man einzelne Tage im Kalender markieren (fett, kursiv, unterstrichen, durchgestrichen, Vorder- und Hintergrundfarbe aendern), um Geburtstage, Urlaub, Feiertage, etc. besonders darzustellen.
Das Programm zeigt die Überschriften des Newstickers von Heise Online als Laufschrift in einem Fenster an. Beim Klick auf eine dieser Überschriften wird die Webseite von Heise Online mit dieser Nachricht aufgerufen.
Zusätzlich wird die Uhrzeit als Digitaluhr angezeigt.
Screenshot:
Bei der UDF "GUICtrlClock" handelt es sich um eine Digitaluhr, die man in einer "fast" beliebigen Größe auf der eigenen GUI erstellen kann.
Die Größe, die man übergibt bestimmt die Fontgröße. Außerdem kann man die X- und Y-Position auf der GUI angeben und die Farbe der Ziffern bestimmen.
Man kann auch unterschiedliche Uhrzeiten anzeigen lassen und Größe, Position und Farbe auch noch nach dem erstellen verändern.
Screenshot:
Die UDF und ein Beispiel-Script findet ihr im ZIP-Archiv im Anhang.
ChipHunter Bei ChipHunter geht es darum, umherfliegende Chips abzuschießen.
Vor dem Start kann man einen von drei Schwierigkeitsgraden auswählen:
"Ansitzjäger", "Treibjäger" oder "Jagdhund" (in aufsteigender Reihenfolge).
Dieser Schwierigkeitsgrad bestimmt, wie schnell sich die Chips bewegen, wie weit sie sich "pro Zug" über den Bildschirm bewegen und in welcher Zeit, man alle drei abgeschossen haben muss, bevor ein Spezial-Chips erscheint (2sek., 1.75sek. 1.5sek.).
Bei Spielstart bekommt man 100 Schuss Munition. Davon befinden sich 10 Schuss im Magazin. Hat man das Magazin leergeschossen, so muss man nachladen (mit der rechten Maustaste). Wenn man die gesamte Munition verschossen hat, ist das Spiel vorbei (die Restzeit wird auf Null gesetzt).
Nach dem Start des Spiels erscheinen drei Chips, die unterschiedliche Werte (1, 10, 25, 50, 100, Zusatzmunition, Magnet, Teufel oder Zauberhut) aufweisen können und die Chips bewegen sich zufallsgesteuert über den Bildschirm.
Wenn man die Chips abschießt (mit der linken Maustaste anklicken), erhält man die Punkte bzw. die Munition gutgeschrieben. Der Magnet-Chip hat eine besondere Bedeutung. Hat man ihn abgeschossen, wird das Fadenkreuz magnetisch und zieht die anderen Chips an. Die Wirkung hält 10 Sekunden lang an. Während dieser Zeit verändert sich das Ausssehen des Fadenkreuzes.
Ab und zu erscheint ein Teufel- oder ein Zauberhut-Chip. Diese beiden Chips verschwinden nach 10 Sekunden von alleine wieder, wenn man sie nicht vorher abschießt.
Den Zauberhut-Chip sollte man allerdings nicht abschießen, denn der verwandelt alle Chips in Gold-Chips.
Den Teufel-Chip hingegen sollte man so schnell wie möglich abschießen, weil der alle Chips in Einer-Chips verwandelt.
Schafft man es, alle drei Chips innerhalb einer vorgegebenen Zeit abzuschießen, so erscheint ein Spezial-Chip, der per Zufall ausgewählt wird.
In 75% der Fälle handelt es sich bei dem Spezial-Chip um einen Gold-Chip, der bei Abschuss 250 Punkte wert ist. In den übrigen 25% der Fälle erscheint ein anderer Spezial-Chip und davon gibt es fünf verschiedene: "+5sek.", "+10sek.", "+5%", "+10%" und die "freundliche Bombe", wobei die Sekunden zur Restzeit addiert werden und die Prozente zur Trefferquote.
Beim Abschuss der "freundlichen Bombe" werden auch alle anderen Chips zerstört, die sich momentan auf dem Bildschirm befinden, und man bekommt deren Punkte, sowie 100 Punkte für die Bombe und, als zusätzlicher Bonus, kommt als nächstes ein Gold-Chip.
Die Trefferquote entscheidet, wie viele der abgeschossenen Punkte man tatsächlich erhält. Wenn man also beispielsweise 100 mal mit der Maus geklickt hat und dabei nur 50 Chips getroffen hat, dann ergibt das eine Trefferquote von 50%. Hat man dabei Chips im Wert von 2000 Punkten abgeschossen, so erhält man davon nur diese 50%, also 1000 Punkte.
Die "Jagdzeit" pro Spiel beträgt regulär 90 Sekunden. Durch das Abschießen der Sekunden-Spezial-Chips verlängert sich diese Zeit aber entsprechend.
Die Lautstärke der Sounds kann man oben rechts einstellen. Entweder indem man mit der linken Maustaste in das Feld klickt (nicht während eines Spiels, damit man nicht versehentlich hineinklickt) oder indem man das Mausrad (falls vorhanden) rauf oder runter dreht (das funktioniert auch während des Spiels).
Das Spiel kann man mit einem Mausklick auf das "X" oben rechts beenden (nicht während eines Spiels, damit man nicht versehentlich darauf klickt) oder indem man die "ESC"-Taste auf der Tastatur drückt (das funktioniert auch während des Spiels). Achtung, es erfolgt keine weitere Nachfrage! Das Spiel wird dann sofort beendet!
Zusätzlich gibt es noch ein Kontextmenü (zu erreichen mit der rechten Maustaste). In diesem Kontextmenü gibt es fünf Menüpunkte, die man mit der linken Maustaste auswählen kann.
Als ersten Menüpunkt gibt es dort den Eintrag "Programm-Informationen". Beim Klick darauf erscheint ein Fenster, wo Informationen zu dem Programm angezeigt werden. Unter anderem auch eine Statistik.
Der zweite Menüpunkt heißt "Spielanleitung & Spielregeln". Beim Klick darauf wird diese Spielanleitung aufgerufen.
Der dritte Menüpunkt heißt "Hintergrundbild ändern". Beim Klick darauf kann man eine Bilddatei (jpg, bmp, png) auswählen, die als Hintergrundbild angezeigt werden soll. Wenn wieder das interne Hintergrundbild angezeigt werden soll, einfach bei der Auswahl auf "Abbrechen" klicken.
Der vierte Menüpunkt heißt "Bestenliste importieren". Beim Klick darauf kann man eine Datei auswählen, die die Bestenliste eines anderen Spielers enthält. Diese Bestenliste wird dann mit der eigenen Bestenliste abgeglichen/importiert.
Der fünfte Menüpunkt heißt "Bestenliste exportieren". Beim Klick darauf muss man eine Datei angeben, in der dann die eigene Bestenliste gespeichert/exportiert wird. Ein anderer Spieler kann diese Datei dann bei sich importieren.
Zusätzlich habe ich noch eine "Boss-Taste" eingebaut. Es handelt sich dabei um die Tastenkombination: {STRG} & {b}
Wenn man diese Tastenkombination drückt, wird das ChipHunter-Fenster minimiert und es tarnt sich in der Taskleiste als Taschenrechner (Titel und Icon).
Viel Spaß beim Abschießen der Chips!
Rechtliches:
Das Spiel steht unter der "CC BY-NC-ND 4.0"-Lizenz (freie Weitergabe mit Namensnennung, nicht kommerziell, keine Bearbeitung).
Screenshot:
Das komplette Spiel (Exe, Script, Resourcen, Icon und BASS.dll) befindet sich im ZIP-Archiv im Anhang.
Installation: einfach das ZIP-Archiv irgendwohin entpacken.[/b]
Früher (mit weniger Erfahrung) hielt ich es für eine gute Idee, eine Datenbank ausschließlich mit einem Listview zu verwalten.
Also die Daten direkt in das Listview eintragen, dort sortieren und dort suchen. Von dort aus speichern und auch dahin von der Festplatte laden.
Mit wenigen Datensätzen ist das machbar und auch schnell genug, deshalb ist mir das erst nicht bewusst geworden.
Erst als ich so eine "Datenbank" im praktischen Einsatz hatte und die Datensätze immer mehr wurden, wurde mir klar, dass das keine so gute Idee war.
Lange Rede, kurzer Sinn! Ich handhabe das mittlerweile anders: alle Daten werden in ein Array geladen, eingegeben, sortiert, dort gesucht und von dort gespeichert.
Das Listview dient im Wesentlichen nur der Anzeige. Auf diese Weise ist das Ganze sehr viel schneller und man kann auch umfangreichere Datensätze verwalten.
Ich wurde nach einem Beispiel-Script gefragt und so habe ich mich mal hingesetzt und solch ein Beispiel-Script geschrieben.
Das Script ist ganz schön umfangreich geworden (ca. 47kB), aber rund die Hälfte davon sind Kommentare.
Dabei habe ich auch an die AutoIt-Anfänger gedacht und jede Zeile kommentiert, mit der Hoffnung, dass das damit verständlich wird.
Das Script ist nicht nur einfach ein Datenbank-Beispiel geworden. Ich habe auch andere Erfahrungen, speziell mit der GUI-Verwaltung, mit einfliessen lassen:
Für AutoIt-Anfänger ist wohl der OnEvent-Modus ein Beispiel dafür.
Andere haben mit Arrays so ihre Probleme.
Ein größenveränderbares Hauptfenster wird hier ebenso benutzt, wie das abspeichern der Größe und Position des Fensters in einer Inidatei.
Auch das abwechselnde benutzen des OnEvent- wie auch des MessageLoop-Modus (z.B. für das Infofenster) wird in dem Beispiel gezeigt.
Verwenden einer Menüleiste und einer Statuszeile.
Doppelkliick-Auswertung auf ein Listview
usw.
Screenshot:
Bedienung des Programms:
Es gibt sieben Buttons auf dem Hauptfenster:
Neue Datenbank erstellen -> Wenn bereits eine Datenbank geladen ist, wird vorher nachgefragt, ob das wirklich passieren soll.
Datenbank laden -> Es öffnet sich ein Dialogfenster, indem man eine Datenbankdatei auswählen kann, die dann geladen wird.
Datenbank speichern -> Es öffnet sich ein Dialogfenster, indem man eine Datei angeben kann, unter der die Datenbank gespeichert wird (".lvdb" wird hinzugefügt).
Neuen Eintrag erstellen -> öffnet ein Fenster, zur Eingabe eines neuen Datensatzes.
Eintrag bearbeiten -> öffnet ein Fenster, in dem man den ersten markierten (bzw. den mit Doppelklick ausgewählten) Eintrag bearbeiten kann.
Markierte Einträge löschen -> alle markierten Einträge werden, nach Rückfrage, aus der Datenbank gelöscht.
Programm-Informationen -> öffnet ein Fenster mit den Programm-Informationen.
Außerdem gibt es die Suche, mit dem Suchbegriff-Eingabefeld und dem Lupen-Button.
Wobei es zwei Arten der Suche gibt:
Einmal die "Einzelsuche" (Aufruf ohne gedrückte Shift-Taste), hier wird der Suchbegriff im Listview einzeln angesteuert und der Suchtreffer markiert.
Und zum Anderen die "Treffersuche" (Aufruf mit gedrückter Shift-Taste), hier wird ein extra Suche-Listview angezeigt, indem alle Suchtreffer aufgelistet sind (und nur diese).
Zurück zum normalen Daten-Listview kommt man, wenn man die Suche mit leerem Eingabefeld startet.
Im ZIP-Archiv (Anhang) findet ihr das komplette Script, sowie eine Beispiel-Datenbankdatei mit über 16.000 Datensätzen (die habe ich mit Zufallsdaten erstellt).
Die Datenbankdateien bekommen von dem Programm die Endung ".lvdb". Es handelt sich aber um reine Textdateien. Man kann sie also auch mit einem Editor öffnen.
Lizenz:
Freeware! Das heißt, ich stelle euch das Script zur freien Verfügung. Ihr dürft es verwenden und verändern, wie ihr wollt. Auch das Infofenster dürft ihr beliebig anpassen.
Ein Hinweis auf mich als Autor der Vorlage wäre zwar schön, ist aber keine Bedingung.
Update 31.05.2017 Version3.1:
Fehler beim schliessen der Gruppe behoben.
Beim aendern der Spaltenbreite des Listview wurde die neue Spaltenbreite erst beim beenden des Programms gespeichert.
Beim beenden des Programms wurde für die Nachfrage noch eine MsgBox benutzt. Ich habe nun die Funktion "_ConfirmDelete" in "_Confirm" umbenannt und verwende sie für beide Nachfragen.
Einige Kommentare hizugefügt/korrigiert.
Update 01.06.2017 Version3.2:
Beim Listview $LVS_EX_DOUBLEBUFFER hinzugefügt. Damit reduziert sich das flackern beim Resizing.
Bei dem Eingabefenster ist das erste Element nun ein Date-Control, so braucht man das eingegebene Datum nicht auf Gültigkeit überprüfen und es erleichert die Eingabe.
Das zweite und dritte Input-Control habe ich mit $ES_NUMBER erweitert, weil man dort ja nur Zahlen eingeben soll.
Beim begrenzen des Fensters auf ein Minimum werden nun die Systemwerte für den Fensterrahmen ausgelesen. Die sind ja bei den Windowsversionen unterschiedlich.
Beim resize "_WM_SIZE" wird nun die Aufteilung der Statuszeile mehr zugunsten der linken Seite berücksichtigt.
Die Funktion "_Confirm" wird nun auch beim neu erstellen der Datenbank benutzt.
Um die Wochennummer zu berechnen, sind einige Funktionen nötig.
Im Internet findet man zahlreiche Berechnungen, aber viele von denen liefern fehlerhafte Daten zurück und/oder berücksichtigen nicht die deutschen/europäischen Regeln zur Berechnung.
Ich habe mal eine Berechnung auf Grundlage der ISO 8601 erstellt:
Show ContentArduino-Quellcode:
/* Daten mit Grenzwerten zum testen der Funktionen:
* 29.12.2014 = ist ein Montag und faellt bereits in die 1. Woche des naechsten Jahres
* 31.12.2015 = in dem Jahr gab es eine 53. Woche
* 31.12.2016 = Tag des Jahres wird mit 366 korrekt berechnet (Schaltjahr)
* 01.01.2017 = ist ein Sonntag und faellt noch in die 52. Woche des Vorjahres
*/
uint16_t year = 2014;
uint8_t month = 12;
uint8_t day = 29;
const char WeekDays[][3] = {"Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"}; // Abkuerzungen der Wochentage
void setup() {
Serial.begin(115200);
Serial.println(F("Berechnung nach ISO 8601"));
bool LeapYear = IsLeapYear(year); // berechnen, ob das Jahr ein Schaltjahr ist
Serial.print(F("Schaltjahr: "));
Serial.println(LeapYear ? F("Ja") : F("Nein"));
}
void loop() {
}
/***** Den Wochentag nach ISO 8601 (1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So) berechnen *****/
uint8_t GetWeekday(uint16_t y, uint8_t m, uint8_t d) {
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3;
uint8_t wd = (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;
return (wd == 0 ? 7 : wd);
}
/***** Die Wochennummer nach ISO 8601 berechnen *****/
uint8_t GetWeekNumber(uint16_t y, uint8_t m, uint8_t d) {
bool LeapYear;
uint16_t doy = GetDayOfYear(y, m, d); // Anzahl der Tage im Jahr ermitteln
uint8_t wd = GetWeekday(y, m, d); // Wochentag ermitteln
uint8_t wnr = (doy - wd + 7) / 7; // die Wochennummer berechnen
switch (wnr) {
case 0: // wenn die Wochennummer Null ergibt, dann liegt der Tag am Anfang des Jahres (1. Sonderfall)
wd = GetWeekday(y - 1, 12, 31); // den letzten Wochentag aus dem Vorjahr ermitteln
LeapYear = IsLeapYear(y - 1); // ermitteln, ob es sich beim Vorjahr um ein Schaltjahr handelt
break; // und nach dem Switch weitermachen...
case 52: // wenn die Wochennummer 52 ergibt, dann liegt der Tag am Ende des Jahres (2. Sonderfall)
wd = GetWeekday(y, 12, 31); // den letzten Wochentag aus diesem Jahr ermitteln
LeapYear = IsLeapYear(y); // ermitteln, ob es sich bei diesem Jahr um ein Schaltjahr handelt
break; // und nach dem Switch weitermachen...
default: // in den anderen Faellen kann die Funktion
return wnr; // hier verlassen und die Wochennummer zurueckgegeben werden
}
if (wd < 4) { // wenn der 31.12. vor dem Donnerstag liegt, dann...
wnr = 1; // ist das die erste Woche des Jahres
} else { // anderenfalls muss ermittelt werden, ob es eine 53. Woche gibt (3. Sonderfall)
/* wenn der letzte Wochentag auf einen Donnerstag oder, */
/* in einem Schaltjahr, auf einen Donnerstag oder Freitag fällt, */
/* dann ist das die 53. Woche, ansonsten die 52. Woche. */
wnr = ((wd == 4) || (LeapYear && wd == 5)) ? 53 : 52;
}
return wnr;
}
/***** die Anzahl der Tage (Tag des Jahres) berechnen *****/
uint16_t GetDayOfYear(uint16_t y, uint8_t m, uint8_t d) {
static const uint16_t mdays[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
return d + mdays[m - 1] + (m >= 2 && IsLeapYear(y));
}
/***** Testen, ob das Jahr ein Schaltjahr ist *****/
bool IsLeapYear(uint16_t y) {
return !(y % 4) && ((y % 100) || !(y % 400)); // Schaltjahrberechnung (true = Schaltjahr, false = kein Schaltjahr)
}
So funktioniert das auf dem Arduino problemlos.
Ich habe das Programm umfangreich kommentiert, sodass die Funktionen verständlich sind.
Noch ein kleines Arduino-Projekt.
Ein Passwort über eine Matrix-Tastatur einzugeben war mir zu einfach, deshalb habe ich mir gedacht, das geht auch mit einem Dreh-Enkoder (mit Buttonklick).
Das hat dann was von einem Tresorschloss, wo man die Zahlen "drehen" muss. Ich hatte hier noch eine 8stellige LED-Anzeige (mit MAX7219 IC). Das benötigt nur 5 Kabel zur Ansteuerung, also wurde das die Anzeige für das eingegebene Passwort. Dazu noch ein Arduino-Nano und ein Piezosummer.
Als Fritzing-Steckplatine sieht das dann so aus:
Die Bedienung ist recht simpel:
Mit dem Dreh-Enkoder dreht man nach links oder rechts, um die Zahl an der Eingabeposition von 0...9 einzustellen.
Mit einem Buttonklick (Dreh-Enkoder drücken) kommt man eine Stelle weiter.
Wenn man den Button längere Zeit gedrückt hält, dann wird die Eingabe zurückgesetzt (wenn man einen Fehler bei der Eingabe gemacht hat).
Sind alle 8 Ziffern eingegeben, so wird die Eingabe mit dem gespeicherten Passwort verglichen und es gibt eine Ausgabe (Passwort richtig/falsch).
Es werden zwei zusätzliche Libraries benötigt: #include "LedControl.h" -> https://github.com/wayoda/LedControl/releases
#include <ClickEncoder.h> -> https://github.com/0xPIT/encoder/tree/arduino
Das Programm für den Arduino findet ihr im Anhang.
Es ist blockierungfrei (ohne delays) geschrieben, sodass auch Erweiterungen problemlos möglich sind.
Selbst die Pieptoene blockieren den Ablauf nicht, sondern werden in einer Interrupt-Funktion ein-/ausgeschaltet.
Bei vielen Hobby-Projekten sucht man nach einer Möglichkeit die Temperatur zu messen.
Mein Favorit, zumindest im Temperaturbereich zwischen -55 und +125 Grad Celsius, ist der "DS18B20" Temperatursensor von "Maxim/Dallas Semiconductor".
Diesen Sensor gibt es einmal in einem TO-92 Gehäuse (gut für die Temperaturmessung in einem Gehäuse):
oder eingegossen in ein Edelstahlröhrchen (für die Messung draußen bzw. außerhalb des Gehäuses):
Die Unterstützung für den Arduino sieht auch sehr gut aus. Es gibt eine Library, die man einfach in sein Projekt integrieren kann.
Und alles was man an zusätzlicher Hardware benötigt, ist ein 4.7 kOhm Widerstand, den man zwischen dem Datenpin und VCC anschließt (PullUp).
Die A/D-Wandlung geschieht bereits im Sensor und die Übertragung zum MikroController erfolgt dann digital.
Die Genauigkeit liegt bei +/- 0.5 Grad Celsius (im Bereich von -10 bis +85 Grad Celsius) und bei +/- 2 Grad Celsuis (im Bereich von -55 bis +125 Grad Celsius).
Die Versorgungsspannung darf zwischen 3.0 und 5.5 Volt liegen.
Und das Beste ist eigentlich, dass dieser Sensor so preiswert ist. Im TO-92 Gehäuse ca. 1.70 € (Einzelpreis) und im externen Edelstahlgehäuse ca. 6,- € (Einzelpreis).
Die Preise sind Momentaufnahmen und liegen weitaus niedriger, wenn man gleich mehrere kauft.
Das alles zusammen macht diesen Sensor zu meinen Favoriten, den ich auch schon mehrfach eingesetzt habe und von dem ich auch mehrere auf Vorrat habe.
Das Datenblatt zum DS18B20 befindet sich im Anhang.
Es gibt zwar schon einige UDFs, die sich mit der seriellen Schnittstelle befassen, aber ich wollte eine kleine und vor allem einfache UDF für den Datenaustausch (AutoIt <-> Arduino).
Man kommt da schon mit wenigen Befehlen aus (Open, Close, Send, Receive). Da sind die anderen UDFs schon viel zu "overkill".
Im Anhang befindet sich die UDF, die man lediglich in sein Script includen muss.
Das Spiel "Galgenraten" kennt wohl jeder, aber trotzdem kurz eine Erklärung:
In diesem Fall ist es ein Spiel gegen den Computer.
Das Programm gibt ein Wort vor, von dem es die einzelnen Buchstaben als Striche darstellt. Nun muss man das Wort erraten, indem man einzelne Buchstaben rät. Kommt der geratene Buchstabe in dem Wort vor, so werden die Buchstaben angezeigt. Kommt der Buchstabe nicht vor, so wird der Galgen aufgebaut.
Das Programm ist komplett in AutoIt geschrieben. Der Quellcode inkl. der verwendeten Grafiken, des Fonts und der Icons befinden sich im ZIP-Archiv im Anhang.
Wenn man das Script "Galgenraten.au3" compiliert, werden alle Resourcen mit eingebunden, sodass man zum spielen nur noch die Exe-Datei benötigt.
Wichtig:Es muss ein Monitor mit FullHD-Auflösung (1920 x 1080) vorhanden sein, sonst startet das Programm nicht!
Screenshot:
Rechtliches:
Dieses Programm darf, zeitlich unbegrenzt, kostenlos genutzt werden!
Eine evtl. Weitergabe muss kostenlos, vollständig und unverändert erfolgen!
Änderungen am Programm dürfen nur durch den Autor vorgenommen werden!