Интерфейс
Объекты управления
Первый скрипт
Циклы
Функции
Классы и объекты
Работа с клавиатурой и мышью
Перемещение курсора
Задержки
Система задержек
Изменение скорости или множитель задержек
Синхронизация затраченного времени в методе combined.run
Захват событий
Интерфейс
Верхнея панель управления содержит основные элементы управления работы с приложением.
Снизу расположено два текстовых поля: верхнее ; для редактирования скрипта (поле редактирования), который будет выполняться программой, нижнее ; для вывода системных сообщений.
Объекты управления
Для создания сценариев в приложение используется"JavaScript"под движком"Nashorn". Это означает, что может использоваться полный синтаксис и библиотеки поддерживаемые данным движком. Полную информацию о поддерживаемых библиотеках и синтаксисе можете найти здесь ***.
Для управления компьютером в окружение скрипта введены несколько основных объектов, которые отображаю основные элементы компьютера.
Перечень доступных объектов:
Доступ к параметрам и методом объекта осуществляется через оператор точку.
Первый скрипт
Напишем первый скрипт. Вставьте следующий код в поле редактирования и выполните скрипт нажав кнопку "Запуск".
CODE:SELECT ALL
system.println('Hello world);
Если все сделано правильно, то вы увидите в поле вывода сообщение "Hello world". Системный объект содержит методы для работы с системой, такие как вывод системных сообщений или приостановка выполнения. При выводе сообщений сообщения выводятся и в стандартный поток вывода. Для проверки этого можете запустить приложение через консоль.
Так что, для работы с любым из объектов можно выделить основный принцип доступа
CODE:SELECT ALL
объект.метод('текстовый параметр',параметр);
Полный список доступных объектов и их методов можно найти в документации либо пройти в правое меню в подпункт "Шаблоны", где можно вставить нужный шаблон и прочитать краткое описание для данного метода.
Циклы
Напишем свой первый цикл. Пускай нам нужно вывести все числа от одного десяти в консоль. Нужный шаблон для цикла можно найти во вкладке"Шаблоны>Язык>loop for i++". Будет вставлен следующий код:
CODE:SELECT ALL
for(i=0;i<10;i++){
}
Данный код выполняет перебор от 0 до 10. Вы можете найти другие циклы во вкладке с шаблонами для убывающего цикла или цикла while.
Теперь добавим вывод числа в консоль методом"sytem.println()". Можно использовать метод system.print(), который выполняет ту же работу, но не ставит в конце сообщения перенос строки.
Скопируйте следующий код и запустите скрипт. Проверьте что все выполняется корректно и в поле вывода появились записи 'i=0' до 9.
CODE:SELECT ALL
for(i=0;i<10;i++){
system.println('i='+i);
}
Функции
Для создания функции добавим шаблон из меню "Шаблоны>Язык>function echo". Данный пункт вставляет код для так называемой эхо-функции, которая принимает значение и возвращает его. Вынесем код указанный выше в функцию и добавим пару вызовов данной функции. Код приведен ниже.
CODE:SELECT ALL
function count(n){
for(i=0;i<n;i++){
system.println('i='+i);
}
}
system.sleep(2000);
count(2);
system.sleep(2000);
count(3);
При запуске скрипта обратите внимание, что вывод в консоль производится не сразу, а с периодичность в две секунды. Здесь для наглядности используется метод "system.sleep()" который указывает, что системы следует подождать указанное количество миллисекунд. 2000 миллисекунд = секунды.
Классы и объекты
Для создания класса добавим шаблон из меню "Шаблоны>Язык>class". В поле редактирования будет вставлен шаблон функции с именем "Class". Оператор "class" не поддерживается, потому придется использовать такую конструкцию.
CODE:SELECT ALL
function Class (name) {
this.name = name; // поле класса
this.echo = function(text){ // метод класса
return text;
};
}
В шаблоне вставляется класс с одним полем и эхо-функцией.
Объект можно создать при помощи следующего кода
CODE:SELECT ALL
var obj = new CLass();
Приведем более наглядный пример с использованием классов и объектов. Создадим объект "math" который сможет хранить в себе число и увеличивать его на единицу.
CODE:SELECT ALL
function Number(n) {
this.n = n; // поле класса
this.inc = function(){ // метод "увеличить число на 1"
n++;
};
this.get = function(){ // метод "получить значение"
return n;
};
}
var myNumber = new Number(0); // создание объекта
myNumber.inc(); // вызов метода 3 раза
myNumber.inc();
myNumber.inc();
system.println('My number = '+myNumber.get()); // вывод
Работа с клавиатурой и мышью
Для работы с мышью и клавиатурой используются два встроенных объекта "mouse" и "key".
Рассмотрим пример кода для работы с объектом клавиатуры. Вставьте код, запустите его и выберите любое текстовое поле. После запуска кода на все про все у вас есть 5 секунд. Поторопитесь!
CODE:SELECT ALL
system.sleep(5000);
key.press('H');
key.release('H');
key.perform('E','PRESS');
key.perform('E','RELEASE');
key.type('L L O SPACE W O R L D');
Данный скрипт генерирует события нажатия и отпускания клавиш клавиатуры. В нем используются основные доступные методы. В качестве параметров используются имена клавиш, с которыми вы хотите работать, записанные через пробел. Если в параметре указано больше одной клавиши, то события для каждой клавиши будут вызваны последовательно в порядке следования. Так, запись
CODE:SELECT ALL
key.press('CONTROL A')
эквивалентна записи
CODE:SELECT ALL
key.press('CONTROL');
key.press('A');
Метод "type" генерирует последовательно для каждой клавиши события нажатия и отпускания клавиш. Строчка
CODE:SELECT ALL
key.type('H E L L O SPACE W O R L D');
последовательно генерирует события для вывода текста"hello
world". Помните, что метод только генерирует указанные события, а не в действительности печатает переданный ему в параметре текст и запись"key.type('Hello World);"работать не будет, так как для отображения заглавных букв нужны события нажатия клавишSHIFTилиCAPS_LOCK, а пробел используется для разделения названий клавиш.
Для работы с кнопками мыши существуют аналогичные методы генерирующие нажатия, отпускания или клики. Методы отличаются названиями но в сущности выполняют ту же работу. Посмотрите приведенный ниже код.
CODE:SELECT ALL
mouse.press('LEFT');
mouse.release('LEFT');
mouse.click('RIGHT');
В стороне от клавиш и кнопок стоит колесо мыши, которое зачастую сочетает в себе среднею кнопку мыши.
CODE:SELECT ALL
mouse.click('MIDDLE');
mouse.wheel('DOWN',3);
Для генерации события нажатия средней кнопки мыши используется аналогичная запись как и с другими кнопками. Для указания работы с колесом прокрутки нужно указывать уже два параметра: направление прокрутки"UP/DOWN"и числовой параметр количество строк.
Перемещение курсора
Для симуляция передвижения мыши существую два основных метода"mouse.move(dx,dy)"и"mouse.moveTo(x,y)".
Метод"move"перемещает курсор относительно текущего положения курсора, то есть, по относительным координатам. Запустите следующий код и обратите внимание на начальное положение курсора и в каком направлении он движется. Параметры могут быть как положительные так и отрицательные. Если параметр отрицательный, то это указывает на обратное смещение по оси координат и курсор будет двигаться в обратную сторону.
CODE:SELECT ALL
for(i=0;i<100;i++){
mouse.move(2,2);
}
Метод"moveTo"передвигает курсор в указанную точку экрана, то есть, передвигает его в указанные абсолютные координаты, где точка 0,0 это левый верхний угол экрана. Координаты не могут быть больше размера вашего монитора или меньше нуля. Нужно быть внимательным с указанием абсолютных координат. Но беспокоиться по этому поводу не стоит, курсор никогда не выйдет за пределы экрана и вы не увидите никаких ошибок.
for(i=0;i<100;i++){
mouse.moveTo(i,i);
}
Существует также множество комбинированных методом, которые упрощают работу с мышью. Все они подчиняются определенным правилам наименования. Если в конце добавляется окончание"At", это означает, что данное событие будет произведено в указанной точке, то есть, курсор сначала будет передвинут в указанную точку и потом будет произведено событие. Если метод начинается со слов"moveAnd", то это означает, что курсор будет сначала передвинут относительно предыдущего положения и потом будет произведено событие.
Для простоты запоминания
Стоит понимать, что данные методы не добавляют нового функционала, а лишь упрощают запись и чтение кода. К примеру, ниже приведены примеры кода, который выполняет абсолютно одинаковые фунции.
CODE:SELECT ALL
mouse.moveTo(0,0);// переместить курсор в точку 0,0
mouse.press('LEFT');// нажать левую кнопку мыши
mouse.release('LEFT');// отпустить левую кнопку мыши
// аналогично
mouse.moveTo(0,0);
mouse.click('LEFT');
// аналогично
mouse.clickAt('LEFT',0,0);
mouse.press('LEFT');// передвинуть курсор вправо
mouse.move(20,0);// нажать левую кнопку мыши
mouse.release('LEFT');// отпустить левую кнопку мыши
// аналогично
mouse.press('LEFT');
mouse.moveAndRelease('LEFT',20,0);
Задержки
Между любыми событиями и вызовами существуют задержки. Мы пока что писали код, который никак не воспроизводил задержки. Для реализации задержки существует метод"system.sleep(delay)". Он приказывает системе подождать в этом месте скрипта указанное количество миллисекунд и только потом продолжить выполнение скрипта. Задержки используются для симуляции реального поведения пользователя. Реальный человек не может мгновенно напечатать более 100 символов, да и не каждая программа способна корректно обработать ввод такого рода, некоторые события будут просто упущены. Потому, скрипт необходимо замедлять принудительно.
Внизу приведен пример скрипта для ввода слова"Hello",который записан с действий реального человека. Скрипт получился длинный, но он делает ровно то, что в него записали – печатает слово"Hello".
CODE:SELECT ALL
key.press('SHIFT');
system.sleep(228);
key.press('H');
system.sleep(65);
key.release('H');
system.sleep(25);
key.release('SHIFT');
system.sleep(142);
key.press('E');
system.sleep(60);
key.release('E');
system.sleep(95);
key.press('L');
system.sleep(65);
key.release('L');
system.sleep(78);
key.press('L');
system.sleep(66);
key.release('L');
system.sleep(102);
key.press('O');
system.sleep(70);
key.release('O');
Обратите внимание на задержки между событиями. В сумме, это именно то время, которое требуется реальному человеку чтобы напечатать данное слово.
Без задержек пользовательский ввод невозможен. Можете попробовать выполнить скрипт с нулевыми задержками, он попросту зависнет. Но сначала прочтите полное руководство к системе контроля задержек в событиях.
Система задержек
У каждого события, для каждого объекта, существует своя предустановленная задержка. К примеру вызов метода"key.press('BTN')"на самом деле не происходит моментально. Внутри уже встроена, так называемая, задержка нажатия"pressDelay", которая вызывается сразу после того, как событие будет вызвано. То есть, внутренняя структура метода"pressDay"выглядит примерно так:
CODE:SELECT ALL
press('BTN');
sleep(pressDelay);
Стандартное значение задержки равно 10мс. Внедрение задержки внутрь метода позволяет избавить себя от заботы прописывать задержки после каждого события. Данная задержка может быть задана методом"key.setDelay(pressDelay)", что позволяет гибко настраивать скрипт и не заботится о том, что скрипт может внезапно зависнуть из-за слишком большого количество событий в секунду.
Аналогичные задержки и методы для их изменения существуют для каждого события:
CODE:SELECT ALL
key.setPressDelay(pressDelay);
key.setReleaseDelay(releaseDealy);
mouse.setPressDelay(pressDelay);
mouse.setReleaseDelay(releaseDelay);
mouse.setWheelDelay(wheelDelay);
mouse.setMoveDelay(moveDelay);
Так же, для каждой из задержек существуют методы для получения задержки"getPressDelay()"и сброса задержки к стандартному значению"resetPressDelay()".
Изменение скорости или множитель
задержек
Для более гибкой настройки выполнение скрипта в приложении есть множители задержекmultiplierи минимальные задержки"minDelay".
Множитель задержки – это вещественное число, на которое умножается каждая задержка в данном объекте. Для объектаmouseон свой и не зависит от аналогичных вkeyиsystem. Стандартно он равен 1. Рассмотрим пример
CODE:SELECT ALL
mouse.setMultiplier(0.5);
key.setMultiplier(0.5);
system.setMultiplier(0.5);
mouse.press('LEFT');
mouse.release('LIFT');
system.sleep(500);
key.press('A');
key.release('A');
ВызовыомиsetMultiplierмы устанавливаем множители равными 0,5. Это означает, что во внутренней реализации стандартная задержка, к примеруpressDelay, будет умножена на это число, а значит уменьшена вдвое. Таким способом, установив задержку меньше 1 можно ускорить воспроизведение событий, а установив множитель больше 1 замедлить.
Для удобства использования есть обратный параметрspeed, который отображает скорость воспроизведения событий. По умолчанию он равен 1, что означает, скрипт будет воспроизводить все событий без изменения задержек. Если установить значение скорости как 2, это означает, что скорость воспроизведения увеличиться в двое.
Параметрspeed- это обратная величина кmultiplier, изменение одной из них приводит к изменению второй. К примеру, еслиspeed = 3, тоmultiplier =
0,33.
Увеличение скорости выполнения скрипта означает, что задержки между событиями уменьшаются. При очень малых значениях задержек скрипт может начать некорректно работать либо полностью прекратить свою работу. Для решения данной проблемы у каждого объекта есть параметр минимальной задержкиminDelay, который ограничивает минимально возможный предел для каждой задержки. По стандарту он равен 5 миллисекунд. Его так же можно установить соответствующим методом и приравнять к 0, чего делать не рекомендуется. Если же вы решили установить значение минимальной задержки равной 0, то будьте очень внимательные и следите за задержками самостоятельно, иначе скрипт может зависнуть.
Для большего понимания, рассмотрим наглядный пример для события нажатия клавиши клавиатуры.
CODE:SELECT ALL
// Любое событие происходит моментально
// без каких либо задержек сразу после вызова метода
press('A');
// После события добавляется задержка
if(pressDelay*multiplier >= minDelay){
// если значение установленной задержки для события,
// при умножении на множитель дает результат
// больший или равный минимальной задержке,
// то подождать получившиеся количество мс.
sleep(pressDelay*multiplier);
}else{
// если полученное значение задержки получается меньше
// чем минимально допустимая задержка,
// то подождать minDelay миллисекунд.
sleep(minDelay);
}
Объект combined
Данный объект служит для воспроизведения действий как мыши, так и клавиатуры одновременно. Основным его методом является методrun. Данный метод получает строку в качестве параметра. Строка представляет из себя компактную запись событий. В каждом символе передаваемой строки закодирован определенный передаваемый параметр. Кодировка происходит в символы юникода (в будущем и другие форматы).
Рассмотрим подробнее каждое возможное событие и их параметры.
Каждое событие записывается с определенной буквы. Некоторые события не имеют параметров(к примеру, зажать левую кнопку мыши), некоторые имеют один параметр(зажать клавишу '#'), а некоторые имеют два параметра (передвинуть курсор в точку (#,$)). При декодировании списка событий каждый из параметров преобразуется в числовое либо буквенное представление и вызывается соответствующий метод.
Синхронизация затраченного времени в
методе combined.run
Одной из особенностей методаrunявляется то, что он проводит синхронизацию по времени выполнения скрипта и реально потраченного времени. Приведем пример: имеется список событий, где записаны различные действия"ld#Ld#k#d#K#d#", используя список событий можно понять, что тут происходит нажатие и отпускание левой кнопки мыши и нажатие и отпускание какой-то клавиши клавиатуры. Переведем эту строку к более наглядному виду и заполним неизвестные параметры:
CODE:SELECT ALL
"ld#Ld#k#d#K#d#" >>>
mouse.press('LEFT');
system.sleep(30);
mouse.release('LEFT');
system.sleep(45);
key.press('A');
system.sleep(100);
key.release('A');
system.sleep(35);
Между каждым событием присутствует задержка. Теоретическое время выполнение скрипта будет равно сумме всех указанных задержек методом"system.sleep() – 30 + 45 + 100 +35 = 210мс". Время за которое данный скрипт выполнится на самом деле, будет немного больше(плюс время выполнение самого скрипта), что будет вносить нежелательное отклонение от реального времени. Для компенсации этого отклонения оно вычитается из времени методаsystem.sleep()после каждого события. Внутренние задержки событий также вычитаются из времени задержки. Приведем пример.
CODE:SELECT ALL
mouse.click('LEFT');
system.sleep(100);
Одно событие клика левой кнопкой мышью и задержка следующая после него. Как было описано в предыдущих главах, метод клика мышью уже содержит в себе стандартные задержки для нажатия кнопки мыши и ее отпускания со всей логикой их вычисления.
Посчитаем время выполнения данного кода без компенсации задержек.
(pressDelay =10, releaseDelay =10)
mouse.click('LEFT'); -> pressDelay + releaseDelay
+ 1(накладные расходы)
system.sleep(100); -> sleepTime + 1(накладные
общее время = 10
+ 10 + 100 + 2(накладные расходы) =122 мс.
указанное время = 100 мс.
разница = 22
мс.
По предварительному подсчету, в такой ситуации фактическое время выполнения будет не менее 120 мс., а с учетом накладных расходов и того больше. Программа при выполнении методаrunкомпенсирует время выполнения отнимая нежелательную разницу из методаsystem.sleep(), фактически, будет выполнен следующий код.
mouse.click('LEFT');
system.sleep(78); // отнял 22 мс. разницы
Таким образом, время выполнения скрипта будет соответствовать реальному времени. Но как всегда, есть ограничения.
Что произойдет, если время самого события будет меньше чем доступное время для компенсации? Посмотрим на пример.
CODE:SELECT ALL
(pressDelay =60, releaseDelay =60)
mouse.click('LEFT'); //60 + 60 + 1(накладные расходы) =121 мс.
system.sleep(100); //100 + 1(накладные расходы) =101 мс.
общее время = 60 + 60 + 100 + 2= 222 мс.
указанное время= 100 мс.
разница = 122 мс.
В данной ситуации получается, что разница во времени больше, чем время, которое возможно компенсировать вычитанием из методаsystem.sleep(). Что же происходит в данной ситуации? Все просто, из методаsystem.sleep()вычитается максимально возможно время (100 мс.), а остаток будет вычтен из следующего события.
CODE:SELECT ALL
mouse.click('LEFT');
system.sleep(0); // остаток 22 мс.
Если и из следующего события не получится вычесть нужное время, то остаток будет накапливаться, но он всегда будет ограничен параметромsystem.delayBuffer(стандартноdelayBuffer= 100 мс.).
Захват событий
Мы рассмотрели основные объекты для симуляция событий клавиатуры и мыши. Теперь рассмотрим механизм их простой записи.
Все необходимые элементы управления для записи событий находятся в правом меню в пункте"Захват событий".
Элементы разделены на отдельные группы. На момент написания все элементы разделены на такие группы:
Для захвата события, выберите место, куда вы хотите вставить код, выберите нужны метод захвата, (используйте контрольную клавишу, если этого требует метод захвата), произведите нужные действия, включите захват событий.
Захват клавиатуры
Особенность захвата клавиатуры в том, что при его включении отключается возможность редактировать скрипт с клавиатуры. Если его включить, то в вывод будут дублироваться клавиши. Так при наборе "hello world" с выбранным методом для вставки имен клавиш "Захват событий > Клавиатура > key name" в выводе будет "H E L O SPACE W O R L D" вместо "hH eE lL lL oO SPACE wW oO rR lL dD ".
Отдельно нужно выделить метод для вставки имен клавиш. Он позволит не лезь в документацию, если вы забыли как называется нужная клавиша.
Захват мыши
Особенность захвата мыши в использовании контрольной клавиши. По умолчанию контрольная клавиша "CONTROL", ее можно изменить в настройках.
Для захвата мыши необходимо выбрать нужный метод, потом зажать контрольную клавишу и произвести необходимые действия, отпустить контрольную клавишу.
Способ захвата с использованием контрольной клавиши выбран для того, чтобы было проще контролировать те события, которые должны попасть в вывод.
Учтите, что во многих приложениях контрольная клавиша "CONTROL" будет работать некорректно, так как часто CONTROL в сочетании с кнопкой мыши уже зарезервирован для других действий. Потому, для каждого приложения вам придется подбирать свою контрольную клавишу, которая не будет конфликтовать с программой.
Захват клавиатура + мышь
Наверное, один из самых мощных инструментов для записи действий пользователя. Он способен записать события клавиатуры и мыши, обработать их надлежащим образом и сохранить это все в компактное текстовое представление.
Для активации комбинированной записи необходимо включить соответствующий элемент управления и нажать контрольную клавишу, которую можно установить в окне настроек.
Запись событий начинается после отпускания контрольной клавиши, а прекращается по ее нажатию. Это позволяет избежать попадания событий контрольной клавиши в список записанных событий.
В качестве контрольной клавиши возможно установить комбинацию клавиш, но стоит учитывать, что в таком случае в список записанных событий попадут события нажатия и отпускания из списка контрольных клавиш.
Для управления записью событий существую несколько опций:
Подробнее остановимся на том, как работают последние три опции. Эти опции созданы для уменьшения объема кода. Если они выключены, то результат будет максимально приближен к действиям пользователя.
Эти опции никоим образом не влияют на все события клавиатуры, колесика и клавиш мыши, а только отсеивают избыточные события перемещения мыши.
Опция "фиксированная частота" указывает максимальную частоту записи событий. Стандартно, курсор может изменять свое положения около 60-120 раз в секунду, что означает, что в результат каждую секунду будут добавлены 60-120 событий перемещения мыши. Указав значение равно 30, к примеру, их количество можно сократить в 4 раза. Чем ниже значение, тем больше событий будут опущены. Возможна ситуация, когда необходимое событие будет не записано.
Данная опция позволяет сократить количество кода и полностью сохраняет скорость передвижения курсора. Если вы в водном месте двигали курсор быстро, а в другом медленно, то эта разница так же будет заметна. Если двигать курсор очень медленно, то данная опция не поможет сократить объем кода, так как все события так же будут попадать в результат.
Опция "Минимальное расстояние" указывает минимальное расстояние меду двумя событиями перемещения мыши. К примеру, минимальное расстояние установлено равным 100 пикселям, вы нажали кнопку мыши и теперь медленно ведете в сторону. Событие передвижения следующее за событием нажатия кнопки гарантировано в результат, однако в результат не попадет ни одно событие расстояние до которого будет меньше чем 100 пикселей.
Эта опция так же поможет вам сократит объем кода. Она позволит убрать избыточные события вне зависимости от того быстро вы передвигаете мышь или очень медленно.
Не рекомендуется устанавливать большие значения, так как результат может быть весьма непредсказуем.
Опция "точки остановки" позволить убрать недостатки от использования предыдущих двух опций. Если курсор простоял в данной точки не двигаясь дольше чем указанное количество мс., то события перемещения курсора в эту точку гарантировано попадет в результат.
Таким образом, можно устанавливать любые значения для предыдущих двух опций и указывать особенно важные точки, которые обязательно должны попасть в результат, просто подержав курсов на месте некоторое время.
Частота обновления стандартного монитора 60 или 120 герц, что дает примерно 8.3 и 16.6 мс. на кадр. Если вы визуально можете заметить, что курсор замер на месте, значит время его остановки было более 17 и 34 мс. соответственно. Указывать значения меньше чем время за 2 кадра нет смысла. Рекомендуется указывать время минимум за 4 кадра: 34 и 67 мс.