Ejemplos
Scripts que funcionan, que abarcan la sintaxis y las áreas de funciones integradas. Filtre por tema o
busque en su código y su texto. Los scripts que usan funciones integradas Context* necesitan un
disparador de gesto o de tecla de acceso rápido. En la consola de diagnóstico, esas funciones
integradas devuelven sus valores vacíos predeterminados.
Hola, consola
El script más pequeño. UtilityPrint escribe en la consola de diagnóstico, o en el registro de
impresión cuando el script no se ejecutó desde la consola.
UtilityPrint("Hello from Input.Observer");
Los cinco tipos de valor
Una variable de cada tipo, impresa mediante StringFormat, que es la única forma de convertir en
Text un valor que no es Text.
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, ""));
Veracidad de cada tipo
Lo que if considera verdadero para cada tipo: números distintos de cero, Text no vacío,
identificadores no nulos.
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");
Cadena else-if
Clasifica la posición horizontal del cursor en tercios del monitor que está debajo de él.
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");
Bucles de conteo: hacia arriba, hacia abajo y por saltos
Las tres partes de for son asignaciones o expresiones que usted elige.
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
Bucles anidados: una tabla de multiplicar
Bucles for anidados que construyen una línea de Text por fila.
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);
}
Bucle while: esperar una ventana, con tiempo de espera
La condición hace el trabajo del “while”, y el contador lo limita a 5 segundos.
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) con una marca de salida
Un paso que se asigna a sí mismo (go = go) crea un bucle que solo se detiene cuando su cuerpo
borra la marca. La tecla de acceso rápido para detener todo también lo termina siempre.
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 y continue
Lleve el contador más allá del límite para salir con break. Ponga el resto del cuerpo dentro de un
if para seguir con continue.
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);
}
}
Sorpresas de precedencia
Dos trampas de precedencia de C, y los paréntesis explícitos que las corrigen.
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));
&& y || evalúan ambos lados
Ambos operandos se ejecutan siempre, lo que importa cuando el lado derecho tiene un efecto o puede fallar.
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));
}
Igualdad entre tipos
Integer y Real se comparan numéricamente. Cualquier otro par de tipos distintos simplemente no es igual.
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
La aritmética de tipos mixtos da 0
Las combinaciones que un operador no entiende dan Integer 0 sin error. Imprima un valor cuando un resultado parezca incorrecto.
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);
Comentarios, instrucciones vacías y bloques
Comentarios de línea y de bloque, un punto y coma suelto y un bloque de nivel superior (que no crea un ámbito).
// 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
División de Integer frente a Real, y división entre cero
La división entera trunca hacia cero, un operando Real da un resultado Real y dividir entre cero da 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, ""));
Resto sin %
n - (n / d) * d es el % de C. Con un divisor que es potencia de dos, una máscara hace lo mismo
para números no negativos.
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, ""));
Redondeo y funciones integradas matemáticas de Real
Un Integer que se pasa donde una función integrada declara Real se convierte en Real. El redondeo aleja las mitades de cero.
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
Limitar un valor a un intervalo
MathClamp (como MathMin/MathMax) acepta cualquiera de los dos tipos numéricos y devuelve el
ganador tal como era.
v = 300;
v = MathClamp(v, 0, 255); // 255
dist = MathAbs(-42); // 42 (Integer stays Integer)
UtilityPrint(StringFormat("clamped={0} abs={1}", v, dist));
Números aleatorios y un volado
MathRandom incluye ambos extremos del intervalo.
die = MathRandom(1, 6);
if (MathRandom(0, 1) == 1) side = "heads"; else side = "tails";
UtilityPrint(StringFormat("die={0}, coin={1}", die, side));
Longitud del trazo de un gesto
Suma la distancia en línea recta entre puntos consecutivos del gesto. La suma de cuadrados Integer
se convierte en Real al pasar a MathSqrt.
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)));
Mover el mouse en círculo
Grados a radianes, trigonometría con Real y MathRound de vuelta a coordenadas de píxel Integer.
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);
Dar formato a un Real sin seis decimales
Escale y redondee para obtener un porcentaje, o para separar un valor en parte entera y centésimas y mostrar dos decimales. Funciona con valores no negativos.
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
Máscaras de marcas: activar, borrar, alternar, comprobar
Las cuatro operaciones habituales de máscara sobre sus propios valores de marca.
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, ""));
Leer el color del píxel bajo el cursor
Desempaquete el Integer 0xRRGGBB con desplazamientos y máscaras.
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");
}
De Integer a texto hexadecimal
Ninguna función integrada da formato hexadecimal, así que separe cuatro bits a la vez y busque cada dígito en un Text.
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
Contar los bits activos
Recorra los 64 bits con desplazamientos y sume cada bit bajo.
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
Casos límite del desplazamiento
>> conserva el signo, y una cantidad de desplazamiento fuera de 0–63 da 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
Intercambiar dos Integer
La forma habitual necesita una variable temporal. XOR los intercambia sin ella.
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 de estado de tecla
KeyboardGetKeyState devuelve el valor de Win32 sin procesar: el bit alto significa que la tecla
está presionada y el bit bajo, que está alternada. Las funciones integradas Is* hacen esa misma
comprobación por usted.
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)));
Secuencias de escape y rutas de Windows
Duplique cada barra invertida de una ruta. \t, \n y \r son secuencias de escape, y cualquier
otra barra invertida se descarta.
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);
Dar formato a más de dos valores
StringFormat solo rellena {0} y {1}. Anide una llamada, o una varias con +.
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);
Dividir y recorrer
StringSplit devuelve el recuento y StringGetSplitPartAt lee cada parte. Las partes entre dos
delimitadores contiguos están vacías.
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]
Divisiones anidadas: pares clave=valor
La división interior reemplaza las partes de la división exterior, así que vuelva a dividir la lista exterior al principio de cada pasada.
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)));
}
Último índice de: una extensión de archivo
No existe LastIndexOf, así que compruebe cada posición y quédese con la última coincidencia.
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
}
Leer un número que escribió alguien
false lo lee en el formato regional del usuario (un usuario alemán escribe 1.234,5). Los
grupos de dígitos deben seguir entonces ese formato: para un usuario de español (México), 1,234.5
es un número y 1,5 no. StringIsNumber detecta el texto que no es un número, que StringToNumber por sí sola convertiría
en 0.
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);
}
Iniciar un programa, esperar su ventana y actuar sobre ella
WindowWaitFor sondea durante el tiempo de espera (60 segundos como máximo) y da una ventana nula si
nada coincidió. El patrón es una expresión regular sobre el título que no distingue mayúsculas de
minúsculas; el título de un programa sigue el idioma de presentación de Windows, así que busque la
parte que no cambia.
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");
}
Extraer un valor de un texto copiado con una expresión regular
Sintaxis PCRE2, distingue mayúsculas de minúsculas a menos que el patrón empiece con (?i), y
reconoce Unicode (\w coincide con letras acentuadas). El grupo 0 es la coincidencia completa; una
barra invertida del patrón se escribe \\ dentro de una cadena de script. $1 en un reemplazo es el
grupo 1. Las funciones integradas Window*Regex/Shell*Regex usan el mismo motor, siempre sin
distinguir mayúsculas de minúsculas.
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"));
Rellenar un número con ceros
Anteponga caracteres hasta que el Text tenga la longitud suficiente.
n = 7;
s = StringFormat("{0}", n, "");
for (s = s; StringGetLength(s) < 3; s = s) {
s = "0" + s;
}
UtilityPrint(s); // 007
Invertir un Text
Recorra el Text hacia atrás, una unidad UTF-16 a la vez. Los caracteres fuera del plano multilingüe básico (la mayoría de los emoji) ocupan dos unidades y saldrían partidos.
text = "Input.Observer";
rev = "";
for (i = StringGetLength(text) - 1; i >= 0; i = i - 1) {
rev = rev + StringGetSubstring(text, i, 1);
}
UtilityPrint(rev); // revresbO.tupnI
Contar las palabras del portapapeles
Convierta las tabulaciones y los saltos de línea en espacios, divida por espacios y cuente las partes que no están vacías.
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, ""));
Comparaciones sin distinguir mayúsculas de minúsculas
Pase ambos lados a minúsculas, porque todos los operadores y funciones integradas de Text distinguen mayúsculas de minúsculas.
title = WindowGetTitle(WindowGetActive());
if (StringContains(StringToLower(title), "visual studio")) {
UtilityPrint("In Visual Studio");
}
exe = WindowGetExecutableName(WindowGetActive());
if (StringToLower(exe) == "notepad.exe") UtilityPrint("In Notepad");
El orden del texto es ordinal
< compara unidades de código UTF-16: todas las letras ASCII mayúsculas van antes que todas las
minúsculas.
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
Rellenar una plantilla y pegarla
StringReplace rellena los marcadores %NAME%. El portapapeles se guarda y se restaura alrededor del
pegado.
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();
Unir las líneas del portapapeles en una sola
Divida por \n. StringTrim también quita el \r de los finales de línea de Windows, así que esto
funciona tanto si las líneas terminan con \r\n como solo con \n.
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);
Buscar en la web el texto seleccionado
ClipboardCopySelection espera a que llegue la copia en lugar de adivinar. StringUrlEncode evita
que &, #, los espacios y las letras acentuadas rompan la dirección. Codifique solo el término de
búsqueda, nunca la URL completa.
ClipboardSave();
term = StringTrim(ClipboardCopySelection(1000));
ClipboardRestore();
if (term) ShellRun("https://www.bing.com/search?q=" + StringUrlEncode(term));
Un gesto, varias opciones
UIShowMenu recibe un elemento por línea (- solo es un separador) y devuelve el índice del
elemento elegido, contando desde 0 y omitiendo los separadores, o -1 si se descarta el menú.
UIShowInputBox devuelve "" al cancelar.
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);
}
La fecha de hoy y un nombre de archivo con marca de tiempo
DateTimeGetNow devuelve texto ISO 8601. DateTimeFormat lo escribe a la manera del usuario, o como
un FileStamp que se ordena por tiempo y es seguro en un nombre de archivo.
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");
Constantes con nombre frente a números sin procesar
Una constante se compila a su número, así que estas llamadas son idénticas. El hexadecimal coincide con la documentación de Win32.
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));
Alternar maximizar en la ventana del gesto
La acción de gesto más común. ContextGetWindow es la ventana sobre la que empezó el gesto.
w = ContextGetWindow();
if (WindowIsMaximized(w)) WindowRestore(w); else WindowMaximize(w);
Fijar una ventana encima
WindowSetTopmost establece explícitamente “siempre visible”, y WindowToggleTopmost lo invierte.
Una propiedad de ventana recuerda qué estado eligió este script.
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));
}
Recorrer niveles de transparencia de una ventana
Baja la opacidad por pasos de 255 a 105 y vuelve a 255. Una ventana que no es por capas informa 255.
w = ContextGetWindow();
a = WindowGetAlpha(w) - 50;
if (a < 100) a = 255;
WindowSetAlpha(w, a);
Ajustar la ventana activa a la mitad izquierda de su monitor
Usa el área de trabajo (true) para que la ventana no cubra la barra de tareas.
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);
Ajustar una ventana a la celda de una cuadrícula de 3×2 bajo el cursor
Las funciones integradas Region* dividen un rectángulo en celdas, encuentran la celda que contiene
un punto y dan sus límites.
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));
}
Lanzar una ventana al siguiente monitor
El segundo argumento mueve el mouse junto con la ventana.
WindowSendToNextScreen(ContextGetWindow(), true);
Enumerar las ventanas de nivel superior visibles
Enumerar y luego leer por índice, omitiendo las ventanas ocultas, encubiertas y sin título.
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));
Minimizar todas las ventanas de una aplicación
Busca el ejecutable con una expresión regular que no distingue mayúsculas de minúsculas. Observe el
\\.: un \. de expresión regular escrito dentro de una cadena de script.
n = WindowFindAllByModuleRegex("notepad\\.exe$");
for (i = 0; i < n; i = i + 1) {
WindowMinimize(WindowGetEnumeratedAt(i));
}
UtilityPrint(StringFormat("Minimized {0} Notepad windows", n, ""));
Cerrar ventanas por patrón de título, después de confirmar
Una expresión regular sobre los títulos, un recuento en el mensaje y una comprobación de qué botón se presionó.
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));
}
}
Recordar y restaurar la posición de una ventana
Las propiedades de ventana guardan valores Integer en la propia ventana, entre ejecuciones, hasta que se cierra. Una propiedad que nunca se estableció se lee como 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);
}
Inspeccionar los controles secundarios de una ventana
Las ventanas secundarias usan la misma caché de ventanas que la enumeración de nivel superior.
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)));
}
Del proceso a la ventana
Enumere los identificadores de proceso por nombre de ejecutable y luego encuentre la ventana de cada uno.
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)));
}
Describir lo que está bajo el cursor
El control que está bajo un punto, su ventana de nivel superior y el punto convertido a coordenadas de cliente.
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)));
Ocultar una ventana en la bandeja
Minimiza al área de notificación. TrayRestoreAllWindows() las devuelve todas.
TrayMinimizeWindow(ContextGetWindow());
Todo lo que sabe el contexto del disparador
Asócielo a un gesto para ver lo que puede leer su script.
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()));
¿Hacia dónde fue el trazo?
Compare el primer y el último punto y elija el eje dominante.
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);
}
Bifurcar según el botón del trazo
ContextGetStrokeButton devuelve un valor MouseButton.*, o -1 fuera de un disparador de gesto o
de botón del mouse.
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");
}
Capturar el área que encerró en un círculo
Guarda el rectángulo delimitador del gesto como PNG en Imágenes.
path = ShellExpandEnvironmentVariables("%USERPROFILE%\\Pictures\\gesture-capture.png");
ok = CaptureSaveRegion(path, ContextGetBoundingBoxX(), ContextGetBoundingBoxY(),
ContextGetBoundingBoxWidth(), ContextGetBoundingBoxHeight());
if (ok) ShellShowToast("Captured", path);
Dejar pasar un dibujo no reconocido
Si se dibujó un gesto sobre una aplicación de dibujo, reproduce el trazo en la aplicación como un arrastre normal.
if (StringToLower(ContextGetApplicationName()) == "mspaint.exe") {
ContextRelayGesture();
}
Hacer clic en algún lugar y devolver el cursor
Guarde la posición del cursor en variables, haga clic y regrese.
x = MouseGetCursorX();
y = MouseGetCursorY();
MouseClick(20, 20, MouseButton.Primary);
UtilityWait(50);
MouseMoveTo(x, y);
Hacer clic en un punto dentro de una ventana
Las coordenadas de cliente siguen siendo correctas dondequiera que se haya movido la ventana.
w = WindowFindByTitle("Calculator");
if (w) {
WindowSetActive(w);
MouseClickAtClientPoint(w, 40, 60, MouseButton.Primary);
}
Un arrastre por script
Presionar, mover por pasos, soltar. Las funciones integradas separadas de presionar, mover y soltar existen para esto.
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);
Desplazarse por muescas
Una muesca de la rueda es 120. Un valor negativo desplaza hacia abajo o hacia la izquierda.
MouseScrollVertical(-3 * 120); // three notches down
MouseScrollHorizontal(120); // one notch right
Confinar el cursor a una ventana durante 5 segundos
MouseLockToRect se aplica en todo el sistema hasta MouseUnlock, así que úselas siempre en pareja.
w = ContextGetWindow();
MouseLockToRect(WindowGetX(w), WindowGetY(w), WindowGetWidth(w), WindowGetHeight(w));
UtilityWait(5000);
MouseUnlock();
Combinaciones de teclas
Prefijos de modificador ^ Ctrl, + Shift, % Alt y @ Win, y luego una tecla.
KeyboardPressKeyCombo("^c"); // Ctrl+C
KeyboardPressKeyCombo("^+{ESC}"); // Ctrl+Shift+Esc
KeyboardPressKeyCombo("@{LEFT}"); // Win+Left
KeyboardPressKeyCombo("%{F4}"); // Alt+F4
Escribir una firma
KeyboardTypeText escribe caracteres. Envíe Enter como combinación de teclas entre líneas, para que
todas las aplicaciones reciban una pulsación real de la tecla Enter.
KeyboardTypeText("Best regards,");
KeyboardPressKeyCombo("{ENTER}");
KeyboardTypeText("Sam");
Shift+clic
Mantenga presionada una tecla alrededor de una acción del mouse y suéltela en el mismo script. Una tecla que se deja presionada sigue presionada.
KeyboardKeyDown(VirtualKey.ShiftKey);
MouseClick(MouseGetCursorX(), MouseGetCursorY(), MouseButton.Primary);
KeyboardKeyUp(VirtualKey.ShiftKey);
Teclas multimedia
Envíe teclas multimedia y de volumen por sus nombres de VirtualKey.
KeyboardPressKey(VirtualKey.MediaPlayPause);
UtilityWait(200);
KeyboardPressKey(VirtualKey.MediaNextTrack);
Cambiar el comportamiento mientras se mantiene presionada Ctrl
Compruebe el estado actual de una tecla para dar a un gesto dos significados.
w = ContextGetWindow();
if (KeyboardIsKeyDown(VirtualKey.ControlKey)) {
WindowClose(w);
} else {
WindowMinimize(w);
}
Pasar a mayúsculas el texto seleccionado
Copie la selección, cámbiela, péguela de nuevo y restaure lo que hubiera antes en el portapapeles.
ClipboardSave();
ClipboardClear();
KeyboardPressKeyCombo("^c");
UtilityWait(100);
text = ClipboardGetText();
if (text) {
ClipboardPasteReplacementText(StringToUpper(text));
UtilityWait(100);
}
ClipboardRestore();
Buscar en la web la selección
Copie la selección y abra una URL de búsqueda. Los espacios se convierten en +. Para codificar
también todos los demás caracteres, use StringUrlEncode, como lo hace
Buscar en la web el texto seleccionado.
ClipboardSave();
KeyboardPressKeyCombo("^c");
UtilityWait(100);
q = StringTrim(ClipboardGetText());
ClipboardRestore();
if (q) {
ShellRun("https://www.bing.com/search?q=" + StringReplace(q, " ", "+"));
}
Guardar en un archivo una imagen copiada
Escribe en el disco la imagen del portapapeles e informa el resultado.
path = ShellExpandEnvironmentVariables("%USERPROFILE%\\Desktop\\clipboard.png");
if (ClipboardSaveImage(path)) ShellShowToast("Saved", path);
else UtilityPrint("No image on the clipboard");
Agregar a un archivo de registro
Crea el archivo con un encabezado la primera vez y luego agrega una línea por ejecución.
log = ShellExpandEnvironmentVariables("%TEMP%\\input-observer-gestures.log");
if (!FileExists(log)) FileCreate(log, "gesture\tapplication\n");
FileAppendText(log, StringFormat("{0}\t{1}\n", ContextGetGestureName(), ContextGetApplicationName()));
Leer un archivo y contar sus líneas
FileReadText devuelve todo el archivo como Text, que luego se divide por \n.
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)));
Contar los tipos de archivo de una carpeta
Enumera una carpeta sin recursividad y cuenta las coincidencias sin distinguir mayúsculas de minúsculas.
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, ""));
Hacer una copia de seguridad de un archivo antes de editarlo
Copiar sobrescribiendo y luego reemplazar el contenido.
path = ShellExpandEnvironmentVariables("%USERPROFILE%\\notes.txt");
if (FileExists(path)) {
FileCopy(path, path + ".bak", true);
FileEditText(path, StringToUpper(FileReadText(path)));
}
Vigilar una carpeta
Combine marcas FileNotify con |. El script de la vigilancia es Text, así que sus comillas
interiores llevan secuencia de escape. Lee lo que ocurrió mediante ContextGetWatch*.
FolderWatchCreate("downloads",
ShellExpandEnvironmentVariables("%USERPROFILE%\\Downloads"),
false,
FileNotify.FileName | FileNotify.LastWrite,
"UtilityPrint(ContextGetWatchAction() + \": \" + ContextGetWatchPath());");
// later: FolderWatchDelete("downloads");
Un temporizador repetitivo que cuenta
El script de un temporizador tiene sus propias variables, así que Storage lleva la cuenta entre activaciones. Se activa 5 veces, con un segundo de separación.
StorageSetValue("ticks", 0);
TimerCreate("counter", 1000, 1000, 5,
"t = StorageGetValue(\"ticks\") + 1; StorageSetValue(\"ticks\", t); UtilityPrint(StringFormat(\"tick {0}\", t, \"\"));");
Script de temporizador desde un snippet, sin secuencias de escape
Guarde un script de temporizador largo en un snippet y pase su texto, así no hay comillas anidadas que escapar.
// Fires once, 10 minutes from now (repeat count 1).
TimerCreate("stretch-reminder", 600000, 1000, 1, SnippetGetScript("Stretch reminder"));
Enumerar y detener temporizadores
Enumere los temporizadores con nombre y elimine uno o todos.
n = TimerEnumerateAll();
for (i = 0; i < n; i = i + 1) UtilityPrint(TimerGetEnumeratedNameAt(i));
TimerDelete("counter");
// TimerDeleteAll();
Un interruptor que se conserva entre ejecuciones
StorageGetValue de una clave que nunca se estableció es Integer 0, que es falso, así que la primera
ejecución activa el modo. El valor dura hasta que Input.Observer se cierra; las funciones integradas
Persistent conservan uno entre reinicios.
on = !StorageGetValue("quietMode");
StorageSetValue("quietMode", on);
MultimediaSetMute(AudioEndpoint.Playback, on);
if (on) ShellShowToast("Quiet mode", "On"); else ShellShowToast("Quiet mode", "Off");
Un contador que se conserva después de un reinicio
Las funciones integradas Storage*Persistent* guardan los valores en storage.toml junto a la
configuración, así que siguen ahí después de que Input.Observer se reinicia. Es texto sin formato,
nunca cifrado: no guarde contraseñas ahí. Las ventanas no se pueden conservar; un identificador no
significa nada después de un reinicio. Si storage.toml existe pero no se puede leer cuando
Input.Observer se inicia, StorageSetPersistentValue devuelve false: el valor solo se conserva
hasta que Input.Observer se cierra, y no se guarda nada hasta el siguiente inicio.
n = StorageGetPersistentValue("gestures.used") + 1; // 0 the first time ever
StorageSetPersistentValue("gestures.used", n);
UtilityPrint(StringFormat("{0} gestures since this counter started", n, ""));
Una lista guardada en Storage
No hay arreglos, pero las claves numeradas creadas con StringFormat funcionan como uno.
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, "")));
}
Permitir que solo una acción ejecute una sección a la vez
Un bloqueo con nombre impide que dos ejecuciones superpuestas se intercalen. Compruebe el resultado con
LockResult y libere el bloqueo cuando termine.
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");
}
Hacer una pregunta
Los botones y el ícono son nombres Text. El resultado es el nombre del botón en el que se hizo clic.
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");
}
Subir el volumen con indicación en pantalla
El volumen es un Real de 0.0 a 1.0. UIShowDisplayMessage recibe 19 argumentos posicionales.
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);
Un mensaje en pantalla que se actualiza en vivo
Conserve el id de sesión y páselo a UIUpdateDisplayMessage con los mismos 19 argumentos.
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);
Una notificación de Windows
Un título y un mensaje, mostrados como notificación del sistema.
ShellShowToast("Input.Observer", StringFormat("Profile: {0}", GestureProfileGetActiveId(), ""));
Alternar el silencio del micrófono
El extremo Capture es el dispositivo de grabación predeterminado.
MultimediaToggleMute(AudioEndpoint.Capture);
if (MultimediaGetMute(AudioEndpoint.Capture)) ShellShowToast("Microphone", "Muted");
else ShellShowToast("Microphone", "Live");
Reproducir un sonido
Archivos WAV y MP3 desde una ruta.
MultimediaPlayWavFile("C:\\Windows\\Media\\chimes.wav");
Iniciar una aplicación o cambiar a ella
Activa la aplicación si ya está en ejecución y, si no, la inicia.
ShellRunOrActivate("notepad.exe");
Ejecutar un programa con un verbo y un estilo de ventana
El verbo es una constante ShellVerb o cualquier verbo como Text. El estilo de ventana es una
constante WindowStyle.
ShellRunProgram("notepad.exe", "C:\\Temp\\todo.txt", ShellVerb.Open, WindowStyle.Maximized, false);
ShellRunProgram("C:\\Temp\\report.pdf", "", "print", WindowStyle.Hidden, false); // Text verb
Ejecutar y esperar a que termine
Con waitForExit establecido en true, el subproceso del script se bloquea hasta que el programa se
cierra. Mientras tanto, la entrada sigue fluyendo. Detener todas las acciones termina la espera: el
programa sigue en ejecución y la llamada devuelve false.
ShellRunProgram("notepad.exe", "", ShellVerb.Open, WindowStyle.Normal, true);
ShellShowToast("Notepad", "was closed");
Expandir variables de entorno
Construye una ruta que funciona en el equipo de cualquier usuario.
UtilityPrint(ShellExpandEnvironmentVariables("%APPDATA%\\Input.Observer"));
UtilityPrint(ShellExpandEnvironmentVariables("%COMPUTERNAME% / %USERNAME%"));
Pasar el trabajo a AutoHotkey
Ejecuta código de AutoHotkey fuera del proceso y devuelve su código de salida, o -1 si AutoHotkey
no está configurado.
rc = AutoHotkeyExecuteScript("SoundBeep 750, 200");
if (rc == -1) UtilityPrint("AutoHotkey isn't set up");
Enumerar los monitores
Nombre, límites completos, área de trabajo y PPP de cada monitor, por índice.
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), ""));
}
Enviar una ventana a un monitor concreto
Por índice de la enumeración, con la pantalla siguiente como alternativa cuando ese monitor no existe.
w = ContextGetWindow();
if (DisplayMonitorEnumeratedAll() > 1) {
WindowSendToMonitorIndex(w, 1, false);
} else {
WindowSendToNextScreen(w, false);
}
Pasar al siguiente perfil de gestos
Encuentre el índice del perfil activo, súmele uno y vuelva al principio con el patrón del resto.
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));
}
Estado del motor
Lea si el motor está desactivado o en modo seguro y luego póngalo en pausa. Vuelva a activarlo desde el menú del ícono de la bandeja.
UtilityPrint(StringFormat("disabled={0} safeMode={1}", EngineIsDisabled(), EngineIsSafeMode()));
if (!EngineIsDisabled()) {
EngineDisable();
ShellShowToast("Input.Observer", "Paused. Re-enable it from the tray menu.");
}
Dejar pasar el siguiente arrastre con el botón derecho
Omite una vez la captura de gestos, para que el siguiente arrastre con el botón derecho llegue a la aplicación.
EngineDisableNextGesture();
Snippets como funciones reutilizables
Pase argumentos y resultados mediante Storage. El snippet se ejecuta hasta el final antes de la siguiente línea.
// 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"), ""));
Comunicarse con un complemento
Envía un comando Text a un complemento conectado y espera su respuesta Text durante el tiempo de espera.
reply = PluginSendMessage("MyRenderer", "theme dark", 2);
UtilityPrint("Plugin replied: " + reply);
Hacer una pregunta a un dispositivo serie
Abra el puerto, escriba una línea, espere hasta 2 segundos la respuesta y cierre el puerto. La paridad y los bits de parada son constantes.
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");
}
Asignar los botones de un dispositivo serie a teclas multimedia
Un monitor ejecuta su script por cada línea recibida. ContextGetSerialTextLine es la línea.
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);");
Enumerar los puertos COM
Qué puertos existen en este momento, como el que acaba de recibir un Arduino al conectarlo. Consulte Dispositivos serie y 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));
}
Mantener abierto el puerto de un Arduino y enviarle comandos
Abra el puerto una sola vez, para que una placa que se reinicia al abrirse su puerto no pierda comandos, y luego envíe una línea y lea la respuesta.
// 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, ""));
}
Convertir una perilla de Arduino en un control de volumen
La lectura de un potenciómetro, de 0 a 1023 en cada línea, se convierte en el volumen de reproducción.
// 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);");