Zum Hauptinhalt springen

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();

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);");