Работа с окнами



GetForegroundWindow

Возвращает window-handle активного окна, который можно использовать в большинстве "оконных" команд (см. также win_pattern, WIN-HWND, WIN-CHILD-HWND).

Пример:

WIN-SET-TITLE: "%GetForegroundWindow%" "new_title"

SendMessageA ( u u u u -- u )

Операционная система Windows позволяет посылать любому окну специальные управляющие сообщения (Windows Messages). Разумеется, разные окна способны принимать разные сообщения. Сверьтесь с API интересующей вас программы, чтобы узнать, какие сообщения можно посылать ее окнам. Для "отправки" Windows Messages используется специальная win32-функция SendMessage. Вот ее описание:

LRESULT SendMessage(
   HWND hWnd, // handle of destination window
   UINT Msg, // message to send
   WPARAM wParam, // first message parameter
   LPARAM lParam // second message parameter
);

SendMessageA - это постфиксный вариант функции SendMessage, который можно использовать в nnCron. Это означает, что, выяснив Window Handle нужного окна, вы можете посылать ему Windows Messages прямо из своих задач. Не забывайте, что SendMessageA это постфиксное слово: аргументы передаются ему как бы "наоборот":

<lParam> <wParam> <Msg> <hWnd> SendMessageA

Если вы не собираетесь использовать значение, которое возвращает SendMessageA, то его надо явным образом удалить со стека.

Примеры:

\ включаем воспроизведение в WinAmp
0 40045 273 WIN-HWND SendMessageA DROP
\ переходим к следующей песне
0 40048 273 WIN-HWND SendMessageA DROP
\ выясняем текущий статус WinAmp'а (play, stop, pause)
104 0 1024 WIN-HWND SendMessageA IF ... ELSE ... THEN
\ управляем статусом Miranda (online)
0 171144 273 WIN-HWND SendMessageA DROP
\ управляем статусом Miranda (do not disturb)
0 171146 273 WIN-HWND SendMessageA DROP

WIN-CLICK: "win_pattern" "button_pattern"

"Нажимает" на указанную кнопку в указанном окне.

Перед словом WIN-CLICK: можно использовать модификатор ALL.


WIN-CLOSE: "win_pattern"

Посылает WM_CLOSE указанному окну, т. е. эмулирует однократное нажатие левой кнопкой мыши на "крестике" в правом верхнем углу окна.

Перед словом WIN-CLOSE: можно использовать модификатор ALL.


WIN-HIDE: "win_pattern"

Прячет (скрывает) указанное окно. Программа при этом продолжает работать, просто ее окно больше не отображается на экране. Для того, чтобы снова вывести окно на экран, воспользуйтесь словом WIN-SHOW:.

Перед словом WIN-HIDE: можно использовать модификатор ALL.


WIN-SHOW: "win_pattern"

Восстанавливает на экране окна, скрытые с помощью слова WIN-HIDE:, а также окна программ, запущенных с опцией SWHide.

Перед словом WIN-SHOW: можно использовать модификатор ALL.


WIN-TERMINATE: "win_pattern"

Завершает процесс, породивший указанное окно.

Перед словом WIN-TERMINATE: можно использовать модификатор ALL.


WIN-ACTIVATE: "win_pattern"

Активизирует указанное окно.

Пример:

#( test_win_activate
\ активизирует окно 'Notepad' , используя
\ регулярное выражение в качестве маски
NoActive
Action:
    WIN-ACTIVATE: "/.*notepad/i"
)#

Следует указать, что во время работы nnCron, заголовок текущего активного окна всегда находится в переменной %ACTIVE-WINDOW%.

Существует также постфиксный вариант этого слова:

S" win_pattern" WIN-ACTIVATE


WIN-ACTIVE: "win_pattern"

Возвращает флаг TRUE (-1), если указанное окно активно


WIN-EXIST: "win_pattern"

Возвращает флаг TRUE (-1), если указанное окно существует.

Существует также постфиксный вариант этого слова:

S" pattern" WIN-EXIST?

См. также примечание.


WIN-MINIMIZE: "win_pattern"
WIN-MAXIMIZE: "win_pattern"
WIN-RESTORE: "win_pattern"

Сворачивает (минимизирует)/разворачивает (максимизирует)/восстанавливает указанное окно.

Перед словами WIN-MINIMIZE:, WIN-MAXIMIZE: и WIN-RESTORE: можно использовать модификатор ALL.

Существуют также постфиксные варианты этих слов:

S" pattern" WIN-MINIMIZE
S" pattern" WIN-MAXIMIZE
S" pattern" WIN-RESTORE


<win-hwnd> WIN-POS ( h -- x y )

Постфиксное слово, которое принимает window handle нужного окна в качеcтве аргумента и возвращает два значения: координаты левого верхнего угла этого окна.

Пример:

#( test_position
NoActive 
VARIABLE x
VARIABLE y
Action:
    WIN-EXIST: "nnCron: Options"
    IF
        BEEP: 250 500
        WIN-HWND WIN-POS  y ! x !
        TMSG: "%FOUND-WINDOW% x=%x @% y=%y @%" 2
    THEN
)#

<win-hwnd> WIN-RECT ( h -- r b y x )

Постфиксное слово, которое принимает window handle нужного окна в качеcтве аргумента и возвращает четыре значения: координаты левого верхнего и правого нижнего углов этого окна.

Пример:

#( test_rect_position
NoActive 
VARIABLE x
VARIABLE y
VARIABLE b
VARIABLE r
Action:
    WIN-EXIST: "nnCron: Options"
    IF
        BEEP: 250 500
        WIN-HWND WIN-RECT x ! y ! b ! r !
        TMSG: "%FOUND-WINDOW% x=%x @% y=%y @% b=%b @% r=%r @%" 2
    THEN
)#

<w> <h> WIN-RESIZE

Постфиксное слово, которое изменяет размеры активного окна. Принимает ширину и высоту окна (в пикселах) в качестве аргументов.

Примеры:

600 400 WIN-RESIZE
800 800 WIN-RESIZE

WIN-TOPMOST: "win_pattern"

Помещает указанное окно поверх всех окон. После применения WIN-TOPMOST:, заданное окно останется поверх остальных, даже после потери фокуса. Чтобы вернуть окну "обычные свойства", просто закройте окно и откройте снова или воспользуйтесь словом WIN-NOTOPMOST:.

Пример:

#( test_win_topmost
\ по нажатию клавиатурного сокращения 'CTRL+ALT+t'
\ текущее активное окно помещается поверх остальных окон.
WatchHotKey: "^@t"
Action:
    WIN-TOPMOST: "%ACTIVE-WINDOW%"
)#

WIN-NOTOPMOST: "win_pattern"

Отменяет действие слова WIN-TOPMOST:. Совместное применение слов WIN-TOPMOST: и WIN-NOTOPMOST: позволяет удерживать указанное окно поверх остальных окон на протяжении нужного времени, после чего вернуть этому окну "обычные" свойства.

Пример:

#( test_win_notopmost
\ помещаем указанное окно поверх остальных окон, 
\ выполняем работу и отменяем действие 'WIN-TOPMOST:'
NoActive
Action:
    WIN-TOPMOST: "*Notepad"
    \ ... выполняем работу
    WIN-NOTOPMOST: "*Notepad"
)#

WIN-SEND-KEYS: "win_pattern" "key_code_string"

Активизирует указанное окно и посылает ему последовательность клавиатурных кодов.

Пример:

#( test_win_send_keys
\ запускает 'Notepad', активизирует его окно
\ и "печатает" слово 'test'
NoActive
Action:
    START-APP: notepad.exe
    PAUSE: 1000
    WIN-SEND-KEYS: "/.*notepad/i" "test"
)#

Иногда, при описании клавиатурных сокращений, возникает необходимость указать одновременно нажатые клавиши (например, нажата и удерживается клавиша CTRL и при этом нажимаются клавиши и ALT и G). В этом случае вы сначала указываете первую нажатую и удерживаемую клавишу, а все остальные окружаете круглыми скобками.

Примеры:

\ 'CTRL+s'
WIN-SEND-KEYS: "window name" "^(s)"
\ 'CTRL+SHIFT+a'
WIN-SEND-KEYS: "window name" "^(+a)"
\ 'SHIFT+F12'
WIN-SEND-KEYS: "window name" "+({F12})"

Паузу между "нажатиями" клавиш и между конструкциями WIN-SEND-KEYS: можно задать с помощью слова SEND-KEYS-DELAY:.

См. также главу "Эмуляция ввода с клавиатуры".


WIN-SET-TITLE: "win_pattern" "new_window_title"

Изменяет заголовок указанного окна. Одна из распространенных сфер применения этого слова - создание уникальных заголовков для нескольких одновременно запущенных экземпляров одной и той же программы.

Пример:

#( test_set_title
NoActive
Action:
    START-APP: notepad.exe
    PAUSE: 500
    WIN-SET-TITLE: "%GetForegroundWindow%" "first notepad instance"
    START-APP: notepad.exe
    PAUSE: 500
    WIN-SET-TITLE: "%GetForegroundWindow%" "second notepad instance"
)#

Существует также постфиксный вариант этого слова:

S" win_pattern" S" new_window_title" WIN-SET-TITLE


WIN-MOVE: <x> <y>

Перемещает активное окно в новую позицию с абсолютными координатами x и y (в пикселах).

Узнать нужные координаты можно с помощью утилиты WinSpy.

Примеры:

\ активизируем окно "Ноутпада" и перемещаем его 
\ в точку с координатами    100, 100
WIN-ACTIVATE: "*Notepad"
WIN-MOVE: 100 100
\ а теперь перемещаем его в левый верхний угол экрана
WIN-MOVE: 0 0

WIN-MOVER: <x> <y>

Перемещает активное окно на указанное количество пикселов относительно текущей позиции.

В качестве аргументов слова WIN-MOVER: можно указывать как положительные, так и отрицательные значения:

Узнать нужные координаты можно с помощью утилиты WinSpy.

Примеры:

\ активизируем окно "Ноутпада" и перемещаем его
\ на 100 пикселей вправо и 100 пикселей вниз
WIN-ACTIVATE: "*Notepad"
WIN-MOVER: 100 100
\ перемещаем окно на 250 пикселей вправо 
\ и 100 пикселей вверх 
WIN-MOVER: 250 -100 
\ перемещаем окно на 250 пикселей вправо 
WIN-MOVER: 250 0

WIN-WAIT: <time_in_ms>

Задает время ожидания готовности активного окна.

Например, если приложение после старта выполняет какую-нибудь длительную операцию и окно приложения все это время не реагирует на действия юзера, то можно задать время (в миллисекундах) в течение котрого nnCron будет ожидать готовности активного окна.

Если активное окно освободится раньше указанного срока, то nnCron тут же запустит на выполнение следующую строку задачи. В обратном случае nnCron запустит следующую строку только после окончания всего срока ожидания.

Пример:

\ запускаем медленно стартующую программу
START-APP: "xxx.exe"
PAUSE: 1000
\ ждем готовности активного окна в течение 30 секунд
WIN-WAIT: 30000
\ ... выполняем работу с окном

FOR-WINDOWS: "win_pattern" <...> ;FOR-WINDOWS

Специальный цикл, который позволяет обрабатывать не только отдельные окна, но и целые группы окон, подпавших под указанную маску: для каждого подходящего окна будут выполнены команды, заданные в теле цикла FOR-WINDOWS:.

Работает это так: если, например, под определенную маску подпали пять окон, то цикл FOR-WINDOWS: автоматически будет запущен пять раз, причем при каждом запуске будет обновлено значение переменной %FOUND-WINDOW%, которая содержит заголовок найденного окна. (Вместо переменной %FOUND-WINDOW% можно использовать переменную %WIN-TITLE% - это одно и то же). При каждом цикле обновляется и значение переменной WIN-HWND, которая содержит window handle текущего окна.

Пример:

#( test_for_windows
\ закрываем все найденные окна "ИЭксплорера"
NoActive
Action:
    FOR-WINDOWS: "*Internet Explorer"
        PAUSE: 300
        WIN-CLOSE: "%FOUND-WINDOW%"
    ;FOR-WINDOWS
)#

Значит, при каждом цикле вы получаете доступ к заголовку очередного окна, подпадающего под указанную маску. Вам остается только выполнить над этим окном нужное действие (закрыть, переместить, минимизировать и т. д.) или же предпринять новую проверку, чтобы решить, как именно поступить с конкретным окном.

Возможность произвести проверку дополнительных условий перед выполнением действия с каждым окном - это основное отличие FOR-WINDOWS: от модификатора ALL.

Пример:

#( test_for_windows1
\ выводим запрос и закрываем по очереди все 
\ найденные окна "ИЭксплорера"
NoActive
Action:
    FOR-WINDOWS: "*Internet Explorer"
        QUERY: "Закрыть окно %FOUND-WINDOW%?"
        IF
            WIN-CLOSE: "%FOUND-WINDOW%"
        THEN
    ;FOR-WINDOWS
)#

FOR-CHILD-WINDOWS: "win_pattern" <...> ;FOR-CHILD-WINDOWS

Специальный цикл, который позволяет обрабатывать группы дочерних окон, чей заголовок подпадает под указанную маску. Перед использованием FOR-CHILD-WINDOWS:, переменная WIN-HWND должна содержать window handle того окна, чьи дочерние окна мы будем обрабатывать.

После использования большинства слов WIN*, WIN-EXIST: и цикла FOR-WINDOWS: эта переменная устанавливается должным образом.

Внутри цикла FOR-CHILD-WINDOWS: устанавливается своя переменная, содержащая window handle текущего дочернего окна: WIN-CHILD-HWND.

Примеры:

\ после слова 'WIN-EXIST:' переменная 'WIN-HWND'
\ установлена должным образом
WIN-EXIST: "xxx"
IF 
    FOR-CHILD-WINDOWS: "yyy"
        \ ... выполняем работу с дочерними окнами
    ;FOR-CHILD-WINDOWS
THEN 
   
\ при каждом цикле 'FOR-WINDOWS:' переменная
\ 'WIN-HWND' содержит window handle текущего окна
FOR-WINDOWS: "xxx"
    \ ... выполняем работу
    FOR-CHILD-WINDOWS: "yyy"
        \ ... выполняем работу с дочерними окнами
    ;FOR-CHILD-WINDOWS
;FOR-WINDOWS
#( test_for_child_windows
\ выводим в лог названия всех дочерних 
\ окон программы 'Xnews'
NoActive
Action:
    \ используем 'WIN-EXIST:', чтобы установить 
    \ переменную 'WIN-HWND'
    WIN-EXIST: "*Xnews*"
    IF
        \ в качестве аргумента для ' FOR-CHILD-WINDOWS:' 
        \ используем класс дочернх окон. Его можно 
        \ посмотреть с помощью утилиты 'WinSpy'
        FOR-CHILD-WINDOWS: "TGroupsWindow"
            LOG: "log\nncron.log" "%FOUND-CHILD-WINDOW%"
        ;FOR-CHILD-WINDOWS
    THEN
)#

ALL

Почти перед всеми WIN-* командами можно применять модификатор ALL.

Этот модификатор предписывает соответствующей команде выполнится для всех окон, заголовки которых совпадают с заданной маской.

Примеры:

\ минимизируем все открытые окна "ИЭксплорера"
ALL WIN-MINIMIZE: "*Internet Explorer"
\ закрываем все найденные окна 'Command Prompt'
ALL WIN-CLOSE: "/(Command Prompt)|(.*?cmd.exe)/i"

Примечание: после большинства "оконных" команд (а также WIN-EXIST:) USER-VALUE переменная WIN-HWND содержит window handle соответствующего окна, а переменная %FOUND-WINDOW% - заголовок этого окна. (%WIN-TITLE% является синонимом %FOUND-WINDOW%).

#( task-move-window
\ выдаем запрос и перемещаем указанное 
\ окно в новую точку на экране
Action:
    WIN-EXIST: "*Internet*"
    IF
        QUERY: "Move '%FOUND-WINDOW%' to (0,0)?"
        IF
            WIN-ACTIVATE: "*Internet*"
            PAUSE: 100
            WIN-MOVE: 0 0
        THEN
    THEN
)#

win_pattern - это маски заголовка окна или класса окна. Задавая маску заголовка окна можно применять символы * и ? или регулярные выражения, заключив их в прямые слеши: /<regexp>/. Также в win_pattern можно использовать window handle нужного окна (и в десятичном, и в шестнадцатеричном представлении). Класс, точный заголовок и window handle нужного окна можно узнать с помощью утилиты WinSpy.

Пример:

\ маска заголовка окна
WIN-HIDE: "Calculator"
\ регулярное выражение (на основе заголовка окна)
WIN-HIDE: "/calculator/i"
\ класс окна
WIN-HIDE: "SciCalc"
\ window handle окна (десятеричное представление)
WIN-HIDE: "592738"
\ window handle окна (шестнадцатеричное представление)
WIN-HIDE: "0x90B62"

См. также: