Прототип к варианту 10 - Имитация нажатий клавиш и событий мыши, страница 2

В программу SimKeys входят две переменные уровня формы. Флаг состояния OperationlnProgress сообщает системе о незавершенной операции, которая будет выполнена при срабатывании таймера. Пока этот флаг установлен, приложение не обрабатывает другие команды. Переменная IsWindows95 устанавливается при работе в Windows 95.

' 0 при отсутствии незавершенной операции

' 1 при отправке клавиш

' 2 при отправке команд мыши

1 3 при сохранении всего экрана

' 4 при сохранении активного окна

Dim OperationlnProgress%

Dim IsWindows95%

Команды cmdSendKeys, cmdMouseMove, cmdCaptureAII и cmdCaptureActive похожи друг на друга. Сначала они проверяют, нет ли незавершенной операции, а затем либо включают таймер для отложенного выполнения, либо выполняют свою операцию немедленно.

Таймер срабатывает после истечения времени задержки, установленной пользователем. Для определения выполняемой операции используется переменная OperationlnProgress. Функция MySendKeys находится в SIMKEYS.BAS, остальные функции реализованы в форме.

Если верить документации Win32 для функции keybd_event, сохранение экрана выполняется очень просто. Достаточно передать в качестве первого параметра виртуальную клавишу VK_SNAP-SHOT и присвоить второму параметру (скан-код) ноль для сохранения всего экрана или 1 для сохранения активного окна.

К сожалению, в документации встречаются неточности. Как выяснилось, именно это и произошло в данном случае.

В Windows NT сохранение всего экрана происходит без проблем, но попытка вызвать функцию со скан-кодом 1 ни к чему не приводит. Единственный выход заключается в более точной имитации процесса сохранения, то есть одновременном нажатии клавиш Alt и PrintScreen для сохранения активного окна. Чтобы найти надежное решение этой проблемы, мне пришлось экспериментировать в течение нескольких часов. Перед выполнением снимка функция keybd_event «нажимает» клавишу Alt, представленную виртуальной клавишей VK_MENU. Для получения скан-кода этой клавиши используется функция MapVirtualKey. После сохранения экрана клавиша «отпускается». Для правильной работы сохранение должно выполняться между командами DoEvents. Вероятно, это как-то связано с взаимодействием между очередью клавиатуры и механизмом сохранения экрана, однако не существует никакой документации, которая помогла бы разобраться с этим вопросом. Для сохранения всего экрана команды DoEvents не нужны, однако вреда они не приносят, а в Windows 95 делают работу программы более надежной.

Теперь перейдем к Windows 95. Оказывается, в Windows 95 выбор между сохранением всего экрана или активного окна действительно зависит от второго параметра (скан-кода) функции keybd_event. Однако значения этого параметра в точности противоположны тем, которые приведены в документации Win32. 1 означает сохранение всего экрана.

После сохранения содержимое буфера обмена копируется в графическое поле.

Этот код работает. Он был протестирован в Windows NT 3.51, NT 4.0 и Windows 95.

Перемещение мыши имитируется при помощи функции mouse_event, причем эта задача несколько проще, чем имитация событий клавиатуры. Тем не менее при этом возникают некоторые интересные проблемы, а также используются многие концепции, представленные в главе 5.

Координаты, передаваемые при вызове mouse_event, задаются в другой системе координат — той, которая используется во внутренней работе драйвера мыши. Экран делится по горизонтали и вертикали на 65 535 единиц. Для определения итоговой позиции курсора мы сначала выбираем точку внутри кнопки ClickMe — в нашем примере это точка (10, 10) в клиентских координатах кнопки. Функция ClientToScreen преобразует клиентские координаты кнопки в экранные координаты. Функция GetSystemMetrics определяет общие размеры рабочего стола, соответствующие размерам 65 535x65 535 единиц в системе координат мыши. Функция GetCursorPos определяет текущую позицию курсора.

По этим величинам можно рассчитать текущую и итоговую позицию курсора в координатах мыши. Кроме того, можно вычислить количество единиц мыши на пиксел по вертикали и горизонтали. Мы перемещаемся к итоговой точке с шагом в два пиксела и останавливаемся, когда мышь окажется на месте.

Перемещение курсора осуществляется вызовом функции mouse_event с флагом MOUSEEVENTF_ MOVE. Флаг MOUSEEVENTF_ABSOLUTE сообщает функции о том, что заданные координаты являются абсолютными (вместо смещения курсора по отношению к текущей позиции). Когда курсор окажется в нужной позиции, программа имитирует нажатие и отпускание левой кнопки мыши, то есть щелчок.

Наше знакомство с примером SimKeys подошло к концу. Как видите, мы объединили многие разнородные функции из этой главы и главы 5 для решения полезной задачи, которую невозможно решить одними средствами Visual Basic.