Beispiele
Funktionierende Skripts zur Syntax und zu den Bereichen der integrierten Funktionen. Filtern Sie nach
Thema, oder durchsuchen Sie ihren Code und Text. Skripts, die Context*-Funktionen verwenden,
brauchen eine Geste oder einen Hotkey als Auslöser. In der Diagnosekonsole geben diese Funktionen
ihre leeren Standardwerte zurück.
Hallo, Konsole
Das kleinste Skript. UtilityPrint schreibt in die Diagnosekonsole oder, wenn das Skript nicht aus
der Konsole ausgeführt wurde, in das Ausgabeprotokoll.
UtilityPrint("Hello from Input.Observer");
Die fünf Werttypen
Eine Variable jedes Typs, ausgegeben über StringFormat, den einzigen Weg, einen Wert, der kein Text
ist, in Text umzuwandeln.
count = 3; // Integer
ratio = 0.75; // Real
name = "Notepad"; // Text
enabled = true; // Bool
w = WindowGetActive(); // Window
UtilityPrint(StringFormat("count={0} ratio={1}", count, ratio)); // count=3 ratio=0.750000
UtilityPrint(StringFormat("name={0} enabled={1}", name, enabled)); // name=Notepad enabled=true
UtilityPrint(StringFormat("window handle={0}", w, ""));
Wahrheitswert jedes Typs
Was if für jeden Typ als wahr ansieht: Zahlen ungleich null, nicht leerer Text, Handles ungleich
null.
if (0) UtilityPrint("never");
if (-1) UtilityPrint("-1 is true");
if (0.0) UtilityPrint("never");
if ("") UtilityPrint("never");
if (" ") UtilityPrint("a single space is true");
if ("false") UtilityPrint("the text \"false\" is true -- it's not empty");
if (!WindowFindByTitle("no window has this title zzz")) UtilityPrint("null handle is false");
else-if-Kette
Ordnet die waagerechte Position des Mauszeigers einem Drittel des Monitors darunter zu.
x = MouseGetCursorX();
y = MouseGetCursorY();
left = DisplayMonitorGetRectXFromPoint(x, y, false);
width = DisplayMonitorGetRectWidthFromPoint(x, y, false);
offset = x - left;
if (offset < width / 3) {
zone = "left";
} else if (offset < width * 2 / 3) {
zone = "center";
} else {
zone = "right";
}
UtilityPrint("Cursor is in the " + zone + " third");
Zählschleifen: aufwärts, abwärts und in Schritten
Alle drei Teile von for sind Zuweisungen oder Ausdrücke Ihrer Wahl.
sum = 0;
for (i = 1; i <= 100; i = i + 1) sum = sum + i;
UtilityPrint(StringFormat("1..100 = {0}", sum, "")); // 5050
for (i = 5; i > 0; i = i - 1) UtilityPrint(StringFormat("{0}...", i, ""));
for (p = 1; p <= 1024; p = p * 2) UtilityPrint(StringFormat("{0}", p, "")); // powers of two
Verschachtelte Schleifen: ein Einmaleins
Verschachtelte for-Schleifen, die pro Zeile der Tabelle eine Textzeile aufbauen.
for (r = 1; r <= 5; r = r + 1) {
line = "";
for (c = 1; c <= 5; c = c + 1) {
line = line + StringFormat("{0}\t", r * c, "");
}
UtilityPrint(line);
}
while-Schleife: mit Zeitlimit auf ein Fenster warten
Die Bedingung übernimmt die Arbeit des „while“, und der Zähler begrenzt sie auf 5 Sekunden.
ShellRun("notepad.exe");
w = WindowFindByTitle("Notepad");
for (tries = 0; !w && tries < 50; tries = tries + 1) {
UtilityWait(100);
w = WindowFindByTitle("Notepad");
}
if (w) {
WindowCenterToScreen(w);
} else {
UtilityPrint("Notepad didn't appear within 5 seconds");
}
while (true) mit einem Ende-Flag
Ein sich selbst zuweisender Schritt (go = go) ergibt eine Schleife, die erst endet, wenn ihr Rumpf
das Flag löscht. Der Hotkey zum Beenden aller Aktionen beendet sie ebenfalls immer.
rolls = 0;
for (go = true; go; go = go) {
rolls = rolls + 1;
if (MathRandom(1, 6) == 6) go = false;
}
UtilityPrint(StringFormat("Rolled a six after {0} tries", rolls, ""));
break und continue
Setzen Sie den Zähler über die Grenze hinaus, um abzubrechen. Setzen Sie den Rest des Rumpfs in ein
if, um fortzufahren.
n = StringSplit("keep,,skip-me,keep too,STOP,never reached", ",");
for (i = 0; i < n; i = i + 1) {
part = StringGetSplitPartAt(i);
if (part == "STOP") {
i = n; // break
} else if (part && !StringStartsWith(part, "skip")) { // continue for empty / skip-*
UtilityPrint(part);
}
}
Überraschungen bei der Rangfolge
Zwei Rangfolgefallen aus C und die expliziten Klammern, die sie beheben.
flags = 6;
a = flags & 4 == 4; // flags & (4 == 4) -> 6 & true -> 0 (Bool operand)
b = (flags & 4) == 4; // true
x = 5;
c = 0 < x < 10; // (0 < x) < 10 -> true < 10 -> false (Bool vs Integer)
d = x > 0 && x < 10; // true
UtilityPrint(StringFormat("a={0} b={1}", a, b));
UtilityPrint(StringFormat("c={0} d={1}", c, d));
&& und || werten beide Seiten aus
Beide Operanden werden immer ausgeführt; das ist wichtig, wenn die rechte Seite eine Wirkung hat oder fehlschlagen kann.
StorageSetValue("calls", 0);
// Both sides run even though the left is false; the right side's
// StorageSetValue still happens.
if (false && StorageSetValue("calls", 1)) { }
UtilityPrint(StringFormat("calls = {0}", StorageGetValue("calls"), "")); // calls = 1
// Guard a call that could fail with a nested if, not &&:
text = "no colon here";
idx = StringGetIndexOf(text, ":");
if (idx >= 0) {
UtilityPrint(StringGetSubstring(text, idx + 1, 100));
}
Gleichheit über Typen hinweg
Integer und Real werden numerisch verglichen. Jedes andere Paar verschiedener Typen ist einfach ungleich.
UtilityPrint(StringFormat("5 == 5.0 -> {0}", 5 == 5.0, "")); // true
UtilityPrint(StringFormat("1 == true -> {0}", 1 == true, "")); // false
UtilityPrint(StringFormat("\"5\" == 5 -> {0}", "5" == 5, "")); // false
UtilityPrint(StringFormat("\"a\" == \"A\" -> {0}", "a" == "A", "")); // false (case-sensitive)
w = WindowFindByTitle("zzz no such window");
UtilityPrint(StringFormat("w == 0 -> {0}, !w -> {1}", w == 0, !w)); // false, true
Arithmetik mit gemischten Typen ergibt 0
Kombinationen, die ein Operator nicht versteht, ergeben ohne Fehler Integer 0. Geben Sie einen Wert aus, wenn ein Ergebnis falsch aussieht.
a = "Total: " + 5; // 0 -- not "Total: 5"
b = true + 1; // 0
c = -"text"; // 0
d = 2.5 & 1; // 0 -- bitwise needs Integers
e = "Total: " + StringFormat("{0}", 5, ""); // "Total: 5"
UtilityPrint(StringFormat("{0} {1}", a, b) + StringFormat(" {0} {1} ", c, d) + e);
Kommentare, leere Anweisungen und Blöcke
Zeilen- und Blockkommentare, ein überzähliges Semikolon und ein Block auf oberster Ebene (der keinen Gültigkeitsbereich erzeugt).
// line comment
/* block comment
spanning lines */
x = 1;; // the extra ';' is an empty statement
{
y = x + 1; /* blocks group statements... */
}
UtilityPrint(StringFormat("y = {0}", y, "")); // ...but y is still visible here
Integer- und Real-Division sowie Division durch null
Ganzzahldivision schneidet Richtung null ab, ein Real-Operand ergibt ein Real-Ergebnis, und Division durch null ergibt 0.
a = 7 / 2; // 3
b = 7 / 2.0; // 3.5
c = 7 * 1.0 / 2; // 3.5 -- convert first, then divide
d = -7 / 2; // -3 (toward zero)
e = 5 / 0; // 0, no error
UtilityPrint(StringFormat("{0} {1}", a, b) + StringFormat(" {0} {1}", c, d) + StringFormat(" {0}", e, ""));
Rest ohne %
n - (n / d) * d entspricht % in C. Bei einem Divisor, der eine Zweierpotenz ist, leistet eine
Maske für nicht negative Zahlen dasselbe.
n = 17;
d = 5;
rem = n - (n / d) * d; // 2
isEven = (n & 1) == 0; // false
low3 = n & 7; // 17 % 8 == 1
UtilityPrint(StringFormat("17 % 5 = {0}, even = {1}", rem, isEven));
UtilityPrint(StringFormat("17 % 8 = {0}", low3, ""));
Runden und Real-Math-Funktionen
Ein Integer, der übergeben wird, wo eine integrierte Funktion Real deklariert, wird zum Real. Beim Runden werden Hälften von null weg gerundet.
n = 16;
root = MathSqrt(n); // 4.0 -- n is widened to 16.0
UtilityPrint(StringFormat("round 2.5 -> {0}", MathRound(2.5), "")); // 3
UtilityPrint(StringFormat("round -2.5 -> {0}", MathRound(-2.5), "")); // -3
UtilityPrint(StringFormat("floor -1.5 -> {0}", MathFloor(-1.5), "")); // -2
UtilityPrint(StringFormat("ceil 1.01 -> {0}", MathCeil(1.01), "")); // 2
UtilityPrint(StringFormat("sqrt 16 -> {0}", MathRound(root), "")); // 4
Einen Wert auf einen Bereich begrenzen
MathClamp (wie MathMin/MathMax) nimmt beide Zahlentypen an und gibt den ausschlaggebenden Wert
unverändert zurück.
v = 300;
v = MathClamp(v, 0, 255); // 255
dist = MathAbs(-42); // 42 (Integer stays Integer)
UtilityPrint(StringFormat("clamped={0} abs={1}", v, dist));
Zufallszahlen und ein Münzwurf
MathRandom schließt beide Enden des Bereichs ein.
die = MathRandom(1, 6);
if (MathRandom(0, 1) == 1) side = "heads"; else side = "tails";
UtilityPrint(StringFormat("die={0}, coin={1}", die, side));
Länge eines Gestenstrichs
Addiert die geradlinigen Abstände zwischen aufeinanderfolgenden Punkten der Geste. Die Integer-Summe
der Quadrate wird auf dem Weg in MathSqrt zum Real.
n = ContextGetPointCount();
total = 0.0;
for (i = 1; i < n; i = i + 1) {
dx = ContextGetPointX(i) - ContextGetPointX(i - 1);
dy = ContextGetPointY(i) - ContextGetPointY(i - 1);
total = total + MathSqrt(dx * dx + dy * dy);
}
UtilityPrint(StringFormat("{0} points, {1} px long", n, MathRound(total)));
Die Maus im Kreis bewegen
Grad in Bogenmaß, Trigonometrie mit Reals und MathRound zurück zu ganzzahligen Pixelkoordinaten.
cx = MouseGetCursorX();
cy = MouseGetCursorY();
radius = 80.0;
for (deg = 0; deg <= 360; deg = deg + 10) {
rad = deg * MathGetPi() / 180;
MouseMoveTo(cx + MathRound(radius * MathCos(rad)), cy + MathRound(radius * MathSin(rad)));
UtilityWait(15);
}
MouseMoveTo(cx, cy);
Einen Real ohne sechs Nachkommastellen formatieren
Skalieren und runden, um einen Prozentwert zu erhalten oder einen Wert für zwei Nachkommastellen in Ganzes und Hundertstel aufzuteilen. Funktioniert für nicht negative Werte.
ratio = 2.0 / 3.0;
pct = MathRound(ratio * 100); // 67
value = 3.14159;
cents = MathRound(value * 100); // 314
whole = cents / 100; // 3
frac = cents - whole * 100; // 14
if (frac < 10) fracText = StringFormat("0{0}", frac, ""); else fracText = StringFormat("{0}", frac, "");
UtilityPrint(StringFormat("{0}% and {1}", pct, StringFormat("{0}.", whole, "") + fracText)); // 67% and 3.14
Flag-Masken: setzen, löschen, umschalten, prüfen
Die vier üblichen Maskenoperationen auf eigenen Flag-Werten.
BOLD = 0x1;
ITALIC = 0x2;
UNDERLINE = 0x4;
style = BOLD | UNDERLINE; // 0b101 = 5
style = style | ITALIC; // set -> 7
style = style & ~BOLD; // clear -> 6
style = style ^ UNDERLINE; // toggle -> 2
if ((style & ITALIC) != 0) UtilityPrint("italic is on");
if ((style & BOLD) == 0) UtilityPrint("bold is off");
UtilityPrint(StringFormat("style = {0}", style, ""));
Die Pixelfarbe unter dem Mauszeiger lesen
Den Integer 0xRRGGBB mit Verschiebungen und Masken zerlegen.
c = DisplayGetPixelColorFromPoint(MouseGetCursorX(), MouseGetCursorY());
if (c < 0) {
UtilityPrint("The cursor isn't over any monitor");
} else {
r = (c >> 16) & 0xFF;
g = (c >> 8) & 0xFF;
b = c & 0xFF;
UtilityPrint(StringFormat("R={0} G={1}", r, g) + StringFormat(" B={0}", b, ""));
if (r > 200 && g < 80 && b < 80) UtilityPrint("That's red");
}
Integer in Hex-Text
Keine integrierte Funktion formatiert hexadezimal; lösen Sie daher jeweils vier Bits ab, und schlagen Sie jede Ziffer in einem Text nach.
digits = "0123456789ABCDEF";
value = 48879;
hex = "";
for (v = value; v > 0; v = v >> 4) {
hex = StringGetSubstring(digits, v & 0xF, 1) + hex;
}
if (!hex) hex = "0";
UtilityPrint("0x" + hex); // 0xBEEF
Die gesetzten Bits zählen
Durch alle 64 Bits verschieben und jedes unterste Bit addieren.
v = 0xB6; // 1011 0110
bits = 0;
for (i = 0; i < 64; i = i + 1) {
bits = bits + ((v >> i) & 1);
}
UtilityPrint(StringFormat("0xB6 has {0} bits set", bits, "")); // 5
Grenzfälle beim Verschieben
>> behält das Vorzeichen, und eine Verschiebungsweite außerhalb von 0–63 ergibt 0.
UtilityPrint(StringFormat("1 << 10 = {0}", 1 << 10, "")); // 1024
UtilityPrint(StringFormat("-16 >> 2 = {0}", -16 >> 2, "")); // -4
UtilityPrint(StringFormat("1 << 64 = {0}", 1 << 64, "")); // 0
UtilityPrint(StringFormat("~0 = {0}", ~0, "")); // -1
Zwei Integer vertauschen
Der übliche Weg braucht eine Hilfsvariable. XOR vertauscht ohne.
a = 12; b = 34;
t = a; a = b; b = t; // with a temporary
a = a ^ b; b = a ^ b; a = a ^ b; // XOR swap back
UtilityPrint(StringFormat("a={0} b={1}", a, b)); // a=12 b=34
Bits des Tastenzustands
KeyboardGetKeyState gibt den unveränderten Win32-Wert zurück: Das oberste Bit bedeutet, dass die
Taste gedrückt ist, das unterste, dass sie umgeschaltet ist. Die Is*-Funktionen nehmen Ihnen diese
Prüfung ab.
caps = KeyboardGetKeyState(VirtualKey.CapsLock);
shift = KeyboardGetKeyState(VirtualKey.ShiftKey);
UtilityPrint(StringFormat("Caps Lock on: {0}, Shift held: {1}", (caps & 1) != 0, (shift & 0x8000) != 0));
UtilityPrint(StringFormat("same via builtins: {0}, {1}",
KeyboardIsKeyToggled(VirtualKey.CapsLock), KeyboardIsKeyDown(VirtualKey.ShiftKey)));
Escapesequenzen und Windows-Pfade
Verdoppeln Sie jeden umgekehrten Schrägstrich in einem Pfad. \t, \n und \r sind Escapesequenzen,
und jeder andere umgekehrte Schrägstrich entfällt.
good = "C:\\Temp\\report.txt"; // C:\Temp\report.txt
bad = "C:\Temp\new.txt"; // C:<no backslash>Temp<line break>ew.txt
quote = "He said \"stop\"";
tabs = "Name\tValue";
cont = "one logical line, \
written on two";
UtilityPrint(good);
UtilityPrint(bad);
UtilityPrint(quote);
UtilityPrint(tabs);
UtilityPrint(cont);
Mehr als zwei Werte formatieren
StringFormat füllt nur {0} und {1}. Verschachteln Sie einen Aufruf, oder verbinden Sie mehrere
mit +.
w = WindowGetActive();
x = WindowGetX(w); y = WindowGetY(w);
width = WindowGetWidth(w); height = WindowGetHeight(w);
// nest: the inner call leaves "{0},{1}" for the outer call to fill
a = StringFormat(StringFormat("{0}x{1} at ", width, height) + "{0},{1}", x, y);
// concatenate: each call formats its own piece
b = StringFormat("pos {0},{1}", x, y) + StringFormat(" size {0}x{1}", width, height);
UtilityPrint(a);
UtilityPrint(b);
Aufteilen und durchlaufen
StringSplit gibt die Anzahl zurück, und StringGetSplitPartAt liest jeden Teil. Teile zwischen
zwei benachbarten Trennzeichen sind leer.
n = StringSplit("red,green,,blue", ",");
for (i = 0; i < n; i = i + 1) {
UtilityPrint(StringFormat("{0}: [{1}]", i, StringGetSplitPartAt(i)));
}
// 0: [red] 1: [green] 2: [] 3: [blue]
Verschachteltes Aufteilen: Schlüssel=Wert-Paare
Die innere Aufteilung ersetzt die Teile der äußeren; teilen Sie die äußere Liste daher zu Beginn jedes Durchlaufs erneut auf.
config = "width=800;height=600;title=Main";
n = StringSplit(config, ";");
for (i = 0; i < n; i = i + 1) {
StringSplit(config, ";"); // restore the outer parts...
pair = StringGetSplitPartAt(i); // ...and copy this one out
StringSplit(pair, "="); // now the cache holds key, value
UtilityPrint(StringFormat("{0} -> {1}", StringGetSplitPartAt(0), StringGetSplitPartAt(1)));
}
Letzter Index: eine Dateierweiterung
Es gibt kein LastIndexOf; prüfen Sie daher jede Position, und behalten Sie den letzten Treffer.
file = "report.final.v2.pdf";
last = -1;
len = StringGetLength(file);
for (i = 0; i < len; i = i + 1) {
if (StringGetSubstring(file, i, 1) == ".") last = i;
}
if (last >= 0) {
ext = StringGetSubstring(file, last + 1, len - last - 1);
base = StringGetSubstring(file, 0, last);
UtilityPrint(StringFormat("base={0} ext={1}", base, ext)); // base=report.final.v2 ext=pdf
}
Eine eingegebene Zahl lesen
false liest sie im regionalen Format des Benutzers (ein deutscher Benutzer tippt 1.234,5).
Zifferngruppen müssen dann diesem Format folgen: Für einen Benutzer mit Deutsch (Deutschland) ist
1.234,5 eine Zahl, 1.5 aber nicht. StringIsNumber erkennt Text, der keine Zahl ist und den StringToNumber allein zu 0 machen würde.
text = UIShowInputBox("Width in pixels:", "Resize", "800");
if (!StringIsNumber(text, false)) {
UIShowMessageBox("Not a number: " + text, "Resize", "OK", "Warning");
} else {
width = StringToNumber(text, false); // Integer 800, or a Real if they typed a fraction
shown = StringFromNumber(width * 1.5, 1, false); // "1,200.0" in en-US, "1.200,0" in de-DE
UtilityPrint("one and a half times that: " + shown);
}
Ein Programm starten, auf sein Fenster warten, darauf reagieren
WindowWaitFor fragt bis zum Zeitlimit (höchstens 60 Sekunden) ab und liefert ein Null-Window, wenn
nichts gepasst hat. Das Muster ist ein regulärer Ausdruck über den Titel ohne Beachtung der
Groß-/Kleinschreibung; der Titel eines Programms folgt der Anzeigesprache von Windows, prüfen Sie
daher auf den Teil, der sich nicht ändert.
ShellRun("notepad.exe");
w = WindowWaitFor("notepad$", 10000);
if (w) {
WindowSetActive(w);
KeyboardTypeText("Notes for today:\n");
WindowWaitClose(w, 60000); // carries on once the user closes it, or after a minute
UtilityPrint("Notepad is gone");
} else {
UtilityPrint("Notepad didn't open in 10 seconds");
}
Mit einem regulären Ausdruck einen Wert aus kopiertem Text holen
PCRE2-Syntax, mit Beachtung der Groß-/Kleinschreibung, sofern das Muster nicht mit (?i) beginnt,
und Unicode-fähig (\w passt auf Buchstaben mit diakritischen Zeichen). Gruppe 0 ist der gesamte
Treffer; ein umgekehrter Schrägstrich im Muster wird in einer Skriptzeichenfolge als \\
geschrieben. $1 in einer Ersetzung ist Gruppe 1. Die Window*Regex/Shell*Regex-Funktionen
verwenden dieselbe Engine, immer ohne Beachtung der Groß-/Kleinschreibung.
text = ClipboardGetText();
if (StringRegexMatch(text, "(?i)order\\s*#?(\\d+)")) {
UtilityPrint("order number: " + StringRegexGetGroupAt(1));
} else {
UtilityPrint("no order number on the clipboard");
}
// every run of spaces, tabs and line breaks becomes one space; "#1234" becomes "order 1234"
text = StringRegexReplace(text, "\\s+", " ");
ClipboardSetText(StringRegexReplace(text, "#(\\d+)", "order $1"));
Eine Zahl mit Nullen auffüllen
Zeichen voranstellen, bis der Text lang genug ist.
n = 7;
s = StringFormat("{0}", n, "");
for (s = s; StringGetLength(s) < 3; s = s) {
s = "0" + s;
}
UtilityPrint(s); // 007
Text umkehren
Den Text rückwärts, jeweils eine UTF-16-Einheit, durchlaufen. Zeichen außerhalb der Basic Multilingual Plane (die meisten Emojis) bestehen aus zwei Einheiten und würden zerteilt.
text = "Input.Observer";
rev = "";
for (i = StringGetLength(text) - 1; i >= 0; i = i - 1) {
rev = rev + StringGetSubstring(text, i, 1);
}
UtilityPrint(rev); // revresbO.tupnI
Wörter in der Zwischenablage zählen
Tabulatoren und Zeilenumbrüche in Leerzeichen umwandeln, an Leerzeichen aufteilen und die nicht leeren Teile zählen.
text = ClipboardGetText();
text = StringReplace(text, "\n", " ");
text = StringReplace(text, "\t", " ");
n = StringSplit(text, " ");
words = 0;
for (i = 0; i < n; i = i + 1) {
if (StringTrim(StringGetSplitPartAt(i))) words = words + 1;
}
UtilityPrint(StringFormat("{0} words", words, ""));
Vergleiche ohne Beachtung der Groß-/Kleinschreibung
Beide Seiten in Kleinbuchstaben umwandeln, denn jeder Textoperator und jede Textfunktion beachtet die Groß-/Kleinschreibung.
title = WindowGetTitle(WindowGetActive());
if (StringContains(StringToLower(title), "visual studio")) {
UtilityPrint("In Visual Studio");
}
exe = WindowGetExecutableName(WindowGetActive());
if (StringToLower(exe) == "notepad.exe") UtilityPrint("In Notepad");
Textreihenfolge ist ordinal
< vergleicht UTF-16-Codeeinheiten: Jeder ASCII-Großbuchstabe wird vor jedem Kleinbuchstaben
einsortiert.
UtilityPrint(StringFormat("\"apple\" < \"banana\" : {0}", "apple" < "banana", "")); // true
UtilityPrint(StringFormat("\"Zebra\" < \"apple\" : {0}", "Zebra" < "apple", "")); // true
UtilityPrint(StringFormat("\"apple\" < \"Banana\" : {0}", "apple" < "Banana", "")); // false
a = "apple"; b = "Banana";
UtilityPrint(StringFormat("case-folded : {0}", StringToLower(a) < StringToLower(b), "")); // true
Eine Vorlage füllen und einfügen
StringReplace füllt %NAME%-Platzhalter. Die Zwischenablage wird vor dem Einfügen gesichert und
danach wiederhergestellt.
template = "Hi %NAME%,\n\nThanks for the report on %APP%.\n";
text = StringReplace(template, "%NAME%", "Sam");
text = StringReplace(text, "%APP%", ContextGetApplicationName());
ClipboardSave();
ClipboardPasteReplacementText(text);
UtilityWait(150); // let the target app read the clipboard first
ClipboardRestore();
Zeilen der Zwischenablage zu einer Zeile verbinden
An \n aufteilen. StringTrim entfernt auch das \r von Windows-Zeilenenden, daher funktioniert
dies unabhängig davon, ob die Zeilen mit \r\n oder nur mit \n enden.
n = StringSplit(ClipboardGetText(), "\n");
out = "";
for (i = 0; i < n; i = i + 1) {
part = StringTrim(StringGetSplitPartAt(i));
if (part) {
if (out) out = out + " ";
out = out + part;
}
}
ClipboardSetText(out);
Im Web nach dem markierten Text suchen
ClipboardCopySelection wartet, bis die Kopie angekommen ist, statt zu raten. StringUrlEncode
verhindert, dass &, #, Leerzeichen und Buchstaben mit diakritischen Zeichen die Adresse
zerstören. Codieren Sie nur den Suchbegriff, nie die ganze URL.
ClipboardSave();
term = StringTrim(ClipboardCopySelection(1000));
ClipboardRestore();
if (term) ShellRun("https://www.bing.com/search?q=" + StringUrlEncode(term));
Eine Geste, mehrere Möglichkeiten
UIShowMenu nimmt einen Eintrag pro Zeile an (- allein ist ein Trennstrich) und gibt den Index des
gewählten Eintrags zurück, ab 0 gezählt und ohne Trennstriche, oder -1, wenn das Menü geschlossen
wurde. UIShowInputBox gibt bei „Abbrechen“ "" zurück.
choice = UIShowMenu("Maximize\nMinimize\n-\nRename window...");
w = ContextGetWindow();
if (choice == 0) WindowMaximize(w);
else if (choice == 1) WindowMinimize(w);
else if (choice == 2) {
title = UIShowInputBox("New title for this window:", "Rename", WindowGetTitle(w));
if (title) WindowSetTitle(w, title);
}
Das heutige Datum und ein Dateiname mit Zeitstempel
DateTimeGetNow gibt Text im Format ISO 8601 zurück. DateTimeFormat schreibt ihn so, wie der
Benutzer es gewohnt ist, oder als FileStamp, der sich nach Zeit sortieren lässt und in einem
Dateinamen sicher ist.
now = DateTimeGetNow();
KeyboardTypeText(DateTimeFormat(now, DateTimeStyle.LongDate));
path = ShellExpandEnvironmentVariables("%USERPROFILE%\\Desktop\\note-") + DateTimeFormat(now, DateTimeStyle.FileStamp) + ".txt";
FileCreate(path, ClipboardGetText());
if (DateTimeGetPart(now, DateTimePart.Hour) >= 17) UtilityPrint("after hours");
Benannte Konstanten statt bloßer Zahlen
Eine Konstante wird zu ihrer Zahl kompiliert, daher sind diese Aufrufe identisch. Die Hexadezimalform entspricht der Win32-Dokumentation.
KeyboardPressKey(VirtualKey.VolumeMute);
KeyboardPressKey(0xAD); // the same key, as a hex VK code
KeyboardPressKey(173); // and in decimal
UtilityPrint(StringFormat("VirtualKey.A = {0}, MouseButton.Right = {1}", VirtualKey.A, MouseButton.Right));
Maximieren des Fensters der Geste umschalten
Die häufigste Gestenaktion. ContextGetWindow ist das Fenster, über dem die Geste begonnen hat.
w = ContextGetWindow();
if (WindowIsMaximized(w)) WindowRestore(w); else WindowMaximize(w);
Ein Fenster im Vordergrund fixieren
WindowSetTopmost legt „Immer im Vordergrund“ ausdrücklich fest, und WindowToggleTopmost schaltet
es um. Eine Fenstereigenschaft merkt sich, welchen Zustand dieses Skript gewählt hat.
w = ContextGetWindow();
pinned = WindowGetPropertyInteger(w, "io.pinned") == 1;
WindowSetTopmost(w, !pinned);
if (pinned) {
WindowRemoveProp(w, "io.pinned");
} else {
WindowSetPropertyInteger(w, "io.pinned", 1);
ShellShowToast("Pinned on top", WindowGetTitle(w));
}
Fenstertransparenz durchschalten
Verringert die Deckkraft schrittweise von 255 auf 105 und kehrt dann zu 255 zurück. Ein Fenster, das kein Layered Window ist, meldet 255.
w = ContextGetWindow();
a = WindowGetAlpha(w) - 50;
if (a < 100) a = 255;
WindowSetAlpha(w, a);
Das aktive Fenster an der linken Hälfte seines Monitors ausrichten
Verwendet den Arbeitsbereich (true), damit das Fenster die Taskleiste nicht verdeckt.
w = WindowGetActive();
cx = WindowGetX(w) + WindowGetWidth(w) / 2;
cy = WindowGetY(w) + WindowGetHeight(w) / 2;
x = DisplayMonitorGetRectXFromPoint(cx, cy, true);
y = DisplayMonitorGetRectYFromPoint(cx, cy, true);
width = DisplayMonitorGetRectWidthFromPoint(cx, cy, true);
height = DisplayMonitorGetRectHeightFromPoint(cx, cy, true);
WindowRestore(w);
WindowMoveTo(w, x, y);
WindowResizeTo(w, width / 2, height);
Ein Fenster in eine Zelle eines 3×2-Rasters unter dem Mauszeiger einpassen
Region*-Funktionen teilen ein Rechteck in Zellen, finden die Zelle, die einen Punkt enthält, und
liefern ihre Grenzen.
mx = MouseGetCursorX();
my = MouseGetCursorY();
x = DisplayMonitorGetRectXFromPoint(mx, my, true);
y = DisplayMonitorGetRectYFromPoint(mx, my, true);
w = DisplayMonitorGetRectWidthFromPoint(mx, my, true);
h = DisplayMonitorGetRectHeightFromPoint(mx, my, true);
cell = RegionGetCellIndexAt(x, y, w, h, 3, 2, mx, my);
win = ContextGetWindow();
if (cell >= 0 && win) {
WindowRestore(win);
WindowMoveTo(win, RegionGetX(x, y, w, h, 3, 2, cell), RegionGetY(x, y, w, h, 3, 2, cell));
WindowResizeTo(win, RegionGetWidth(x, y, w, h, 3, 2, cell), RegionGetHeight(x, y, w, h, 3, 2, cell));
}
Ein Fenster auf den nächsten Monitor werfen
Das zweite Argument bewegt die Maus mit dem Fenster mit.
WindowSendToNextScreen(ContextGetWindow(), true);
Sichtbare Fenster der obersten Ebene auflisten
Erst aufzählen, dann indizieren, wobei ausgeblendete, verhüllte (cloaked) und titellose Fenster übersprungen werden.
n = WindowGetAllTopLevel();
shown = 0;
for (i = 0; i < n; i = i + 1) {
w = WindowGetEnumeratedAt(i);
if (WindowGetVisible(w)) {
if (!WindowIsCloaked(w)) {
title = WindowGetTitle(w);
if (title) {
UtilityPrint(StringFormat("{0} [{1}]", title, WindowGetExecutableName(w)));
shown = shown + 1;
}
}
}
}
UtilityPrint(StringFormat("{0} of {1} windows", shown, n));
Alle Fenster einer App minimieren
Prüft die ausführbare Datei mit einem regulären Ausdruck ohne Beachtung der Groß-/Kleinschreibung.
Beachten Sie das \\.: ein \. des regulären Ausdrucks, in einer Skriptzeichenfolge geschrieben.
n = WindowFindAllByModuleRegex("notepad\\.exe$");
for (i = 0; i < n; i = i + 1) {
WindowMinimize(WindowGetEnumeratedAt(i));
}
UtilityPrint(StringFormat("Minimized {0} Notepad windows", n, ""));
Fenster nach Titelmuster schließen, nach Bestätigung
Ein regulärer Ausdruck über die Titel, eine Anzahl in der Meldung und eine Prüfung, welche Schaltfläche geklickt wurde.
n = WindowFindAllByTitleRegex("^Untitled - ");
if (n > 0) {
answer = UIShowMessageBox(StringFormat("Close {0} untitled window(s)?", n, ""),
"Tidy up", "YesNo", "Question");
if (answer == "Yes") {
for (i = 0; i < n; i = i + 1) WindowClose(WindowGetEnumeratedAt(i));
}
}
Die Position eines Fensters merken und wiederherstellen
Fenstereigenschaften speichern Integer am Fenster selbst, über Ausführungen hinweg, bis es geschlossen wird. Eine nie gesetzte Eigenschaft liest sich als 0.
w = ContextGetWindow();
if (WindowGetPropertyInteger(w, "io.saved") == 1) {
WindowMoveTo(w, WindowGetPropertyInteger(w, "io.x"), WindowGetPropertyInteger(w, "io.y"));
WindowRemoveProp(w, "io.saved");
WindowRemoveProp(w, "io.x");
WindowRemoveProp(w, "io.y");
} else {
WindowSetPropertyInteger(w, "io.x", WindowGetX(w));
WindowSetPropertyInteger(w, "io.y", WindowGetY(w));
WindowSetPropertyInteger(w, "io.saved", 1);
WindowCenterToScreen(w);
}
Die untergeordneten Steuerelemente eines Fensters untersuchen
Untergeordnete Fenster verwenden denselben Fenstercache wie die Aufzählung der obersten Ebene.
w = ContextGetWindow();
n = WindowGetAllChildren(w, true);
for (i = 0; i < n; i = i + 1) {
c = WindowGetEnumeratedAt(i);
UtilityPrint(StringFormat("{0}: {1}", WindowGetClassName(c), WindowGetTitle(c)));
}
Vom Prozess zum Fenster
Prozess-IDs nach Name der ausführbaren Datei aufzählen und dann das Fenster jedes Prozesses finden.
n = ShellEnumerateProcessIdsByExeRegex("^explorer\\.exe$");
for (i = 0; i < n; i = i + 1) {
pid = ShellGetEnumeratedProcessIdAt(i);
w = WindowFromProcessId(pid);
UtilityPrint(StringFormat("pid {0}: {1}", pid, WindowGetTitle(w)));
}
Beschreiben, was sich unter dem Mauszeiger befindet
Das Steuerelement unter einem Punkt, sein Fenster der obersten Ebene und der in Clientkoordinaten umgerechnete Punkt.
x = MouseGetCursorX();
y = MouseGetCursorY();
control = WindowControlFromPoint(x, y);
top = WindowGetRoot(control);
UtilityPrint(StringFormat("control class: {0}; window: {1}", WindowGetClassName(control), WindowGetTitle(top)));
UtilityPrint(StringFormat("client point: {0},{1}",
WindowMapScreenPointToClientX(top, x, y), WindowMapScreenPointToClientY(top, x, y)));
Ein Fenster im Infobereich verstecken
In den Infobereich minimieren. TrayRestoreAllWindows() holt alle zurück.
TrayMinimizeWindow(ContextGetWindow());
Alles, was der Auslöserkontext weiß
Hängen Sie das an eine Geste an, um zu sehen, was ihr Skript lesen kann.
UtilityPrint(StringFormat("action={0} gesture={1}", ContextGetActionName(), ContextGetGestureName()));
UtilityPrint(StringFormat("app={0} window={1}", ContextGetApplicationName(), WindowGetTitle(ContextGetWindow())));
UtilityPrint(StringFormat("box x={0} y={1}", ContextGetBoundingBoxX(), ContextGetBoundingBoxY())
+ StringFormat(" w={0} h={1}", ContextGetBoundingBoxWidth(), ContextGetBoundingBoxHeight()));
UtilityPrint(StringFormat("points={0} button={1}", ContextGetPointCount(), ContextGetStrokeButton()));
In welche Richtung ging der Strich?
Ersten und letzten Punkt vergleichen und die vorherrschende Achse wählen.
n = ContextGetPointCount();
if (n > 1) {
dx = ContextGetPointX(n - 1) - ContextGetPointX(0);
dy = ContextGetPointY(n - 1) - ContextGetPointY(0);
if (MathAbs(dx) > MathAbs(dy)) {
if (dx > 0) dir = "right"; else dir = "left";
} else {
if (dy > 0) dir = "down"; else dir = "up";
}
UtilityPrint("The stroke went " + dir);
}
Nach der Maustaste des Strichs verzweigen
ContextGetStrokeButton gibt einen MouseButton.*-Wert zurück oder -1 außerhalb eines
Gesten- oder Maustastenauslösers.
b = ContextGetStrokeButton();
if (b == MouseButton.Secondary) {
WindowMinimize(ContextGetWindow());
} else if (b == MouseButton.Middle) {
WindowClose(ContextGetWindow());
} else if (b == -1) {
UtilityPrint("Not triggered by a mouse button");
}
Einen Screenshot des umkreisten Bereichs erstellen
Speichert das umgebende Rechteck der Geste als PNG im Ordner „Bilder“.
path = ShellExpandEnvironmentVariables("%USERPROFILE%\\Pictures\\gesture-capture.png");
ok = CaptureSaveRegion(path, ContextGetBoundingBoxX(), ContextGetBoundingBoxY(),
ContextGetBoundingBoxWidth(), ContextGetBoundingBoxHeight());
if (ok) ShellShowToast("Captured", path);
Eine nicht erkannte Zeichnung durchlassen
Wurde eine Geste über einem Zeichenprogramm gezeichnet, wird der Strich als normales Ziehen an das Programm wiedergegeben.
if (StringToLower(ContextGetApplicationName()) == "mspaint.exe") {
ContextRelayGesture();
}
Irgendwo klicken und dann den Mauszeiger zurücksetzen
Die Mauszeigerposition in Variablen sichern, klicken und zurückkehren.
x = MouseGetCursorX();
y = MouseGetCursorY();
MouseClick(20, 20, MouseButton.Primary);
UtilityWait(50);
MouseMoveTo(x, y);
Auf einen Punkt in einem Fenster klicken
Clientkoordinaten bleiben korrekt, wohin das Fenster auch verschoben wurde.
w = WindowFindByTitle("Calculator");
if (w) {
WindowSetActive(w);
MouseClickAtClientPoint(w, 40, 60, MouseButton.Primary);
}
Ein per Skript gesteuertes Ziehen
Drücken, schrittweise bewegen, loslassen. Dafür gibt es die getrennten Funktionen für Drücken, Bewegen und Loslassen.
x = MouseGetCursorX();
y = MouseGetCursorY();
MouseButtonDown(MouseButton.Primary);
for (i = 1; i <= 20; i = i + 1) {
MouseMoveTo(x + i * 10, y);
UtilityWait(10);
}
MouseButtonUp(MouseButton.Primary);
Um Rasterstufen scrollen
Eine Mausradstufe ist 120. Negative Werte scrollen nach unten bzw. links.
MouseScrollVertical(-3 * 120); // three notches down
MouseScrollHorizontal(120); // one notch right
Den Mauszeiger 5 Sekunden lang auf ein Fenster beschränken
MouseLockToRect gilt systemweit bis MouseUnlock; verwenden Sie die beiden daher immer als Paar.
w = ContextGetWindow();
MouseLockToRect(WindowGetX(w), WindowGetY(w), WindowGetWidth(w), WindowGetHeight(w));
UtilityWait(5000);
MouseUnlock();
Tastenkombinationen
Modifizierer-Präfixe ^ Strg, + Umschalt, % Alt und @ Win, dann eine Taste.
KeyboardPressKeyCombo("^c"); // Ctrl+C
KeyboardPressKeyCombo("^+{ESC}"); // Ctrl+Shift+Esc
KeyboardPressKeyCombo("@{LEFT}"); // Win+Left
KeyboardPressKeyCombo("%{F4}"); // Alt+F4
Eine Signatur tippen
KeyboardTypeText tippt Zeichen. Senden Sie Enter zwischen den Zeilen als Tastenkombination, damit
jede App einen echten Druck der Eingabetaste sieht.
KeyboardTypeText("Best regards,");
KeyboardPressKeyCombo("{ENTER}");
KeyboardTypeText("Sam");
Umschalt-Klick
Eine Taste während einer Mausaktion gedrückt halten und im selben Skript loslassen. Eine gedrückt gelassene Taste bleibt gedrückt.
KeyboardKeyDown(VirtualKey.ShiftKey);
MouseClick(MouseGetCursorX(), MouseGetCursorY(), MouseButton.Primary);
KeyboardKeyUp(VirtualKey.ShiftKey);
Medientasten
Medien- und Lautstärketasten über ihre VirtualKey-Namen senden.
KeyboardPressKey(VirtualKey.MediaPlayPause);
UtilityWait(200);
KeyboardPressKey(VirtualKey.MediaNextTrack);
Verhalten ändern, solange Strg gedrückt ist
Einen aktuellen Tastenzustand prüfen, um einer Geste zwei Bedeutungen zu geben.
w = ContextGetWindow();
if (KeyboardIsKeyDown(VirtualKey.ControlKey)) {
WindowClose(w);
} else {
WindowMinimize(w);
}
Den markierten Text in Großbuchstaben umwandeln
Die Markierung kopieren, ändern, wieder einfügen und den vorherigen Inhalt der Zwischenablage wiederherstellen.
ClipboardSave();
ClipboardClear();
KeyboardPressKeyCombo("^c");
UtilityWait(100);
text = ClipboardGetText();
if (text) {
ClipboardPasteReplacementText(StringToUpper(text));
UtilityWait(100);
}
ClipboardRestore();
Im Web nach der Markierung suchen
Die Markierung kopieren und eine Such-URL öffnen. Leerzeichen werden zu +. Um auch alle anderen
Zeichen zu codieren, verwenden Sie StringUrlEncode, wie es
Im Web nach dem markierten Text suchen tut.
ClipboardSave();
KeyboardPressKeyCombo("^c");
UtilityWait(100);
q = StringTrim(ClipboardGetText());
ClipboardRestore();
if (q) {
ShellRun("https://www.bing.com/search?q=" + StringReplace(q, " ", "+"));
}
Ein kopiertes Bild in einer Datei speichern
Schreibt das Bild aus der Zwischenablage auf den Datenträger und meldet das Ergebnis.
path = ShellExpandEnvironmentVariables("%USERPROFILE%\\Desktop\\clipboard.png");
if (ClipboardSaveImage(path)) ShellShowToast("Saved", path);
else UtilityPrint("No image on the clipboard");
An eine Protokolldatei anhängen
Erstellt die Datei beim ersten Mal mit einer Kopfzeile und hängt dann pro Ausführung eine Zeile an.
log = ShellExpandEnvironmentVariables("%TEMP%\\input-observer-gestures.log");
if (!FileExists(log)) FileCreate(log, "gesture\tapplication\n");
FileAppendText(log, StringFormat("{0}\t{1}\n", ContextGetGestureName(), ContextGetApplicationName()));
Eine Datei lesen und ihre Zeilen zählen
FileReadText gibt die ganze Datei als Text zurück, der dann an \n aufgeteilt wird.
path = "C:\\Windows\\System32\\drivers\\etc\\hosts";
text = FileReadText(path);
n = StringSplit(text, "\n");
comments = 0;
for (i = 0; i < n; i = i + 1) {
if (StringStartsWith(StringTrim(StringGetSplitPartAt(i)), "#")) comments = comments + 1;
}
UtilityPrint(StringFormat("{0} lines, {1} comments", n, comments));
UtilityPrint(StringFormat("{0} bytes, modified {1}", FileGetSize(path), FileGetModifiedDate(path)));
Dateitypen in einem Ordner zählen
Zählt einen Ordner ohne Rekursion auf und zählt Treffer ohne Beachtung der Groß-/Kleinschreibung.
folder = ShellExpandEnvironmentVariables("%USERPROFILE%\\Downloads");
n = FolderEnumerateAll(folder, false);
pdf = 0; zip = 0;
for (i = 0; i < n; i = i + 1) {
p = StringToLower(FolderGetEnumeratedPathAt(i));
if (StringEndsWith(p, ".pdf")) pdf = pdf + 1;
else if (StringEndsWith(p, ".zip")) zip = zip + 1;
}
UtilityPrint(StringFormat("{0} PDFs, {1} ZIPs", pdf, zip) + StringFormat(" of {0} entries", n, ""));
Eine Datei vor dem Bearbeiten sichern
Mit Überschreiben kopieren, dann den Inhalt ersetzen.
path = ShellExpandEnvironmentVariables("%USERPROFILE%\\notes.txt");
if (FileExists(path)) {
FileCopy(path, path + ".bak", true);
FileEditText(path, StringToUpper(FileReadText(path)));
}
Einen Ordner überwachen
Kombinieren Sie FileNotify-Flags mit |. Das Skript der Überwachung ist Text, daher sind die
Anführungszeichen darin mit Escapezeichen versehen. Es liest über ContextGetWatch*, was geschehen
ist.
FolderWatchCreate("downloads",
ShellExpandEnvironmentVariables("%USERPROFILE%\\Downloads"),
false,
FileNotify.FileName | FileNotify.LastWrite,
"UtilityPrint(ContextGetWatchAction() + \": \" + ContextGetWatchPath());");
// later: FolderWatchDelete("downloads");
Ein wiederholender Timer, der zählt
Das Skript eines Timers hat eigene Variablen, daher trägt Storage den Zählerstand von Auslösung zu Auslösung. Löst 5-mal im Abstand von einer Sekunde aus.
StorageSetValue("ticks", 0);
TimerCreate("counter", 1000, 1000, 5,
"t = StorageGetValue(\"ticks\") + 1; StorageSetValue(\"ticks\", t); UtilityPrint(StringFormat(\"tick {0}\", t, \"\"));");
Timerskript aus einem Snippet, ohne Escapes
Legen Sie ein langes Timerskript in einem Snippet ab, und übergeben Sie seinen Text, damit keine verschachtelten Anführungszeichen mit Escapes versehen werden müssen.
// Fires once, 10 minutes from now (repeat count 1).
TimerCreate("stretch-reminder", 600000, 1000, 1, SnippetGetScript("Stretch reminder"));
Timer auflisten und beenden
Die benannten Timer aufzählen und einen oder alle löschen.
n = TimerEnumerateAll();
for (i = 0; i < n; i = i + 1) UtilityPrint(TimerGetEnumeratedNameAt(i));
TimerDelete("counter");
// TimerDeleteAll();
Ein Umschalter, der zwischen Ausführungen erhalten bleibt
StorageGetValue für einen nie gesetzten Schlüssel ist Integer 0, was als falsch gilt, daher
schaltet die erste Ausführung den Modus ein. Der Wert bleibt erhalten, bis Input.Observer beendet
wird; die Persistent-Funktionen bewahren einen Wert über Neustarts hinweg.
on = !StorageGetValue("quietMode");
StorageSetValue("quietMode", on);
MultimediaSetMute(AudioEndpoint.Playback, on);
if (on) ShellShowToast("Quiet mode", "On"); else ShellShowToast("Quiet mode", "Off");
Ein Zähler, der einen Neustart übersteht
Die Storage*Persistent*-Funktionen speichern Werte in storage.toml neben der Konfiguration,
sodass sie nach einem Neustart von Input.Observer noch vorhanden sind. Klartext, nie verschlüsselt:
Speichern Sie dort keine Kennwörter. Fenster können nicht gespeichert werden; ein Handle bedeutet
nach einem Neustart nichts mehr. Ist storage.toml vorhanden, kann aber beim Start von
Input.Observer nicht gelesen werden, gibt StorageSetPersistentValue false zurück: Der Wert bleibt
nur erhalten, bis Input.Observer beendet wird, und bis zum nächsten Start wird nichts gespeichert.
n = StorageGetPersistentValue("gestures.used") + 1; // 0 the first time ever
StorageSetPersistentValue("gestures.used", n);
UtilityPrint(StringFormat("{0} gestures since this counter started", n, ""));
Eine in Storage gehaltene Liste
Keine Arrays, aber mit StringFormat gebildete nummerierte Schlüssel funktionieren wie eines.
count = StorageGetValue("recent.count");
StorageSetValue(StringFormat("recent.{0}", count, ""), WindowGetTitle(ContextGetWindow()));
StorageSetValue("recent.count", count + 1);
for (i = 0; i <= count; i = i + 1) {
UtilityPrint(StorageGetValue(StringFormat("recent.{0}", i, "")));
}
Nur eine Aktion gleichzeitig einen Abschnitt ausführen lassen
Eine benannte Sperre verhindert, dass sich zwei überlappende Ausführungen verschränken. Prüfen Sie
das Ergebnis gegen LockResult, und geben Sie die Sperre frei, wenn Sie fertig sind.
r = UtilityLockAcquire("clipboard-work", 5);
if (r == LockResult.Acquired) {
ClipboardSave();
// ...work that must not overlap another run...
ClipboardRestore();
UtilityLockRelease("clipboard-work");
} else {
UtilityPrint("Another action is busy with the clipboard");
}
Eine Frage stellen
Schaltflächen und Symbol sind Textnamen. Das Ergebnis ist der Name der geklickten Schaltfläche.
answer = UIShowMessageBox("Save the layout before closing?", "Input.Observer", "YesNoCancel", "Question");
if (answer == "Yes") {
UtilityPrint("saving");
} else if (answer == "No") {
UtilityPrint("discarding");
} else {
UtilityPrint("cancelled");
}
Lauter mit Bildschirmanzeige
Die Lautstärke ist ein Real von 0.0 bis 1.0. UIShowDisplayMessage nimmt 19 Positionsargumente an.
v = MathMin(MultimediaGetVolume(AudioEndpoint.Playback) + 0.05, 1.0);
MultimediaSetVolume(AudioEndpoint.Playback, v);
UIShowDisplayMessage(
"Volume", StringFormat("{0}%", MathRound(v * 100), ""),
1200, // durationMs
0.9, // opacity (Real)
Location.BottomCenter, // or a "x,y" Text point
"Segoe UI", 14, true, false, // title font, size, bold, italic
"Segoe UI", 12, false, false, // message font, size, bold, italic
"#1F1F1F", "#F7F7F5", // fore / back color: name, #RRGGBB or "R,G,B"
12, // padding
false, // usePrimaryScreen
TextAlign.Center, TextAlign.Center);
Eine sich laufend aktualisierende Anzeigemeldung
Behalten Sie die Sitzungs-ID, und übergeben Sie sie mit denselben 19 Argumenten an
UIUpdateDisplayMessage.
id = UIShowDisplayMessage("Working", "0%", 10000, 0.95, Location.TopRight,
"Segoe UI", 12, true, false, "Segoe UI", 11, false, false,
"black", "255,255,255", 10, true, TextAlign.Left, TextAlign.Left);
for (p = 0; p <= 100; p = p + 20) {
UIUpdateDisplayMessage(id, "Working", StringFormat("{0}%", p, ""), 10000, 0.95, Location.TopRight,
"Segoe UI", 12, true, false, "Segoe UI", 11, false, false,
"black", "255,255,255", 10, true, TextAlign.Left, TextAlign.Left);
UtilityWait(400);
}
UICloseDisplayMessage(id);
Eine Windows-Benachrichtigung
Ein Titel und eine Meldung, als Popupbenachrichtigung angezeigt.
ShellShowToast("Input.Observer", StringFormat("Profile: {0}", GestureProfileGetActiveId(), ""));
Die Stummschaltung des Mikrofons umschalten
Der Endpunkt Capture ist das Standardaufnahmegerät.
MultimediaToggleMute(AudioEndpoint.Capture);
if (MultimediaGetMute(AudioEndpoint.Capture)) ShellShowToast("Microphone", "Muted");
else ShellShowToast("Microphone", "Live");
Einen Sound abspielen
WAV- und MP3-Dateien aus einem Pfad.
MultimediaPlayWavFile("C:\\Windows\\Media\\chimes.wav");
Eine App starten oder zu ihr wechseln
Aktiviert die App, wenn sie bereits läuft, und startet sie andernfalls.
ShellRunOrActivate("notepad.exe");
Ein Programm mit Verb und Fensterstil ausführen
Das Verb ist eine ShellVerb-Konstante oder ein beliebiges Verb als Text. Der Fensterstil ist eine
WindowStyle-Konstante.
ShellRunProgram("notepad.exe", "C:\\Temp\\todo.txt", ShellVerb.Open, WindowStyle.Maximized, false);
ShellRunProgram("C:\\Temp\\report.pdf", "", "print", WindowStyle.Hidden, false); // Text verb
Ausführen und auf das Ende warten
Ist waitForExit auf true gesetzt, blockiert der Thread des Skripts, bis das Programm geschlossen
wird. Eingaben laufen währenddessen weiter. Das Beenden aller Aktionen beendet das Warten: Das
Programm läuft weiter, und der Aufruf gibt false zurück.
ShellRunProgram("notepad.exe", "", ShellVerb.Open, WindowStyle.Normal, true);
ShellShowToast("Notepad", "was closed");
Umgebungsvariablen erweitern
Bildet einen Pfad, der auf dem Computer jedes Benutzers funktioniert.
UtilityPrint(ShellExpandEnvironmentVariables("%APPDATA%\\Input.Observer"));
UtilityPrint(ShellExpandEnvironmentVariables("%COMPUTERNAME% / %USERNAME%"));
An AutoHotkey übergeben
Führt AutoHotkey-Code in einem eigenen Prozess aus und gibt dessen Exitcode zurück oder -1, wenn
AutoHotkey nicht konfiguriert ist.
rc = AutoHotkeyExecuteScript("SoundBeep 750, 200");
if (rc == -1) UtilityPrint("AutoHotkey isn't set up");
Monitore auflisten
Name, vollständige Grenzen, Arbeitsbereich und DPI jedes Monitors, nach Index.
n = DisplayMonitorEnumeratedAll();
for (i = 0; i < n; i = i + 1) {
UtilityPrint(StringFormat("#{0} {1}", i, DisplayMonitorGetEnumeratedFriendlyNameAt(i)));
UtilityPrint(StringFormat(" bounds {0} x {1}", DisplayMonitorGetEnumeratedWidthAt(i, false), DisplayMonitorGetEnumeratedHeightAt(i, false))
+ StringFormat(", work area {0} x {1}", DisplayMonitorGetEnumeratedWidthAt(i, true), DisplayMonitorGetEnumeratedHeightAt(i, true))
+ StringFormat(", {0} dpi", DisplayMonitorGetEnumeratedDpiAt(i), ""));
}
Ein Fenster auf einen bestimmten Monitor senden
Nach dem Index aus der Aufzählung; gibt es diesen Monitor nicht, wird ersatzweise der nächste Bildschirm verwendet.
w = ContextGetWindow();
if (DisplayMonitorEnumeratedAll() > 1) {
WindowSendToMonitorIndex(w, 1, false);
} else {
WindowSendToNextScreen(w, false);
}
Zum nächsten Gestenprofil wechseln
Den Index des aktiven Profils finden, eins addieren und mit dem Rest-Muster wieder bei null beginnen.
n = GestureProfileEnumerateAll();
if (n > 0) {
active = GestureProfileGetActiveId();
next = 0;
for (i = 0; i < n; i = i + 1) {
if (GestureProfileGetEnumeratedIdAt(i) == active) next = i + 1;
}
next = next - (next / n) * n; // next % n
GestureProfileSwitch(GestureProfileGetEnumeratedIdAt(next));
ShellShowToast("Gesture profile", GestureProfileGetEnumeratedNameAt(next));
}
Zustand der Engine
Lesen, ob die Engine deaktiviert ist oder im abgesicherten Modus läuft, und sie dann anhalten. Aktivieren Sie sie über das Infobereichsmenü wieder.
UtilityPrint(StringFormat("disabled={0} safeMode={1}", EngineIsDisabled(), EngineIsSafeMode()));
if (!EngineIsDisabled()) {
EngineDisable();
ShellShowToast("Input.Observer", "Paused. Re-enable it from the tray menu.");
}
Das nächste Ziehen mit der rechten Maustaste durchlassen
Überspringt die Gestenerfassung einmal, sodass das nächste Ziehen mit der rechten Maustaste an die App geht.
EngineDisableNextGesture();
Snippets als wiederverwendbare Funktionen
Argumente und Ergebnisse über Storage übergeben. Das Snippet wird vollständig ausgeführt, bevor die nächste Zeile folgt.
// Snippet "Tile window" reads tile.index and positions ContextGetWindow() accordingly.
StorageSetValue("tile.index", 2);
SnippetExecuteScript("Tile window");
UtilityPrint(StringFormat("snippet reported: {0}", StorageGetValue("tile.result"), ""));
Mit einem Plug-in kommunizieren
Sendet einen Textbefehl an ein verbundenes Plug-in und wartet bis zum Zeitlimit auf dessen Textantwort.
reply = PluginSendMessage("MyRenderer", "theme dark", 2);
UtilityPrint("Plugin replied: " + reply);
Ein serielles Gerät etwas fragen
Den Anschluss öffnen, eine Zeile schreiben, bis zu 2 Sekunden auf die Antwort warten und den Anschluss schließen. Parität und Stoppbits sind Konstanten.
if (SerialOpenPort("COM3", 9600, SerialParity.None, 8, SerialStopBits.One, "\n")) {
SerialWriteTextLine("COM3", "PING", 9600);
reply = SerialGetTextLine("COM3", 2, 9600);
SerialClosePort("COM3");
if (reply) UtilityPrint("Device: " + reply); else UtilityPrint("No reply");
}
Tasten eines seriellen Geräts Medientasten zuordnen
Ein Monitor führt sein Skript für jede empfangene Zeile aus. ContextGetSerialTextLine ist die
Zeile.
SerialMonitorCreate("pad", "COM3", 115200, SerialParity.None, 8, SerialStopBits.One, "\n",
"line = StringTrim(ContextGetSerialTextLine()); if (line == \"B1\") KeyboardPressKey(VirtualKey.MediaPlayPause); else if (line == \"B2\") KeyboardPressKey(VirtualKey.MediaNextTrack);");
Die COM-Anschlüsse auflisten
Welche Anschlüsse gerade vorhanden sind, etwa der, den ein Arduino beim Einstecken soeben erhalten hat. Siehe Serielle Geräte und Arduino.
n = SerialEnumeratePorts();
if (n == 0) UtilityPrint("No COM ports. Is the board plugged in?");
for (i = 0; i < n; i = i + 1) {
UtilityPrint(SerialGetEnumeratedPortAt(i));
}
Den Anschluss eines Arduino offen halten und ihm Befehle senden
Den Anschluss einmal öffnen, damit ein Board, das beim Öffnen seines Anschlusses neu startet, keine Befehle verpasst, dann eine Zeile senden und die Antwort lesen.
// Load global event: open the port once, at the sketch's speed. An Uno or Nano
// restarts every time its port opens, so a port opened per command would lose
// the command while the board boots.
if (!SerialOpenPort("COM4", 115200, SerialParity.None, 8, SerialStopBits.One, "")) {
UtilityPrint("COM4 isn't available: unplugged, or open in the Arduino IDE's Serial Monitor?");
}
// Any gesture or hotkey: send a command line and read the board's reply.
// (The sketch reads a line with Serial.readStringUntil('\n') and answers OK.)
if (SerialWriteTextLine("COM4", "LED 255 0 0", 115200)) {
reply = SerialGetTextLine("COM4", 1, 115200);
if (reply != "OK") UtilityPrint(StringFormat("Board said: {0}", reply, ""));
}
Einen Arduino-Drehknopf zum Lautstärkeregler machen
Ein Potentiometerwert von 0 bis 1023 in jeder Zeile wird zur Wiedergabelautstärke.
// Arduino side: a potentiometer on A0, one reading per line.
// void setup() { Serial.begin(115200); }
// void loop() { Serial.println(analogRead(A0)); delay(50); }
// Empty text as the terminator means CR LF, which Serial.println sends.
SerialMonitorCreate("knob", "COM4", 115200, SerialParity.None, 8, SerialStopBits.One, "",
"line = ContextGetSerialTextLine(); if (StringIsNumber(line, true)) MultimediaSetVolume(AudioEndpoint.Playback, StringToNumber(line, true) / 1023.0);");