Дела мышиные

Однажды к мудрецу пришел ученик и спросил: "Учитель, Вы знаете так много. Почему же Вы продолжаете учиться?" Мудрец нарисовал на песке два круга: маленький и большой. И сказал: "Маленький круг - твои знания. Большой - мои. Границы моих знаний больше. Я хочу получить ответы на большее количество вопросов."

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

Единственное, что роднит эти компоненты, так это то, что их нет, когда они нужны. А если и есть, то нет документации к ним. Результат - потерянное время. А ведь зачастую в них нет никакой необходимости. Для решения возникшей проблемы может быть достаточно воспользоваться возможностями, которые предоставляет операционная система. Все уважающие себя языки программирования позволяют использовать эти возможности.

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

Не подумайте, что такое явление, как прерывание, происходит лишь в экстренных ситуациях, совсем наоборот. Прерывания от таймера возникают примерно 18 раз в секунду, от клавиатуры - по мере нажатия клавиш, от принтера - периодически. Еще есть звуковые платы, модем, сканер, мышь, наконец. Всего же в MS-DOS зарезервировано 255 прерываний.

Ваша программа может обмениваться данными с программой обработки прерываний. Для передачи данных в или из программы обработки прерывания используются регистры центрального процессора, чаще всего в этой роли выступает регистр AX. Может показаться, что работа с прерываниями возможна только на языке, который позволяет работать с регистрами микропроцессора напрямую, то есть на Ассемблере. Это не так - и C, и Pascal, и Basic позволяют делать то же самое.

Доступ к регистрам процессора в языке C организован через псевдопеременные (_AX, _BX, _CX, _DX и так далее), в языке Pascal - через запись Registers из модуля Dos. Для обращения к программе обработки прерывания в языке C используются функции geninterrupt и intr, а в Pascal процедуры Intr (In: byte; var Regs : Registers) и MsDos (var Regs : Registers).

Дабы не изобретать велосипед, создатели QuickBasic использовали для работы с прерываниями те же приемы, что и в C и Pascal. Поэтому для работы с прерываниями используется процедура GetInterrupt, как в C, а аналогом записи Registers языка Pascal является пользовательский тип RegTypeX, определенный в файле "qb.bi". Чтобы увидеть, из каких полей состоит этот тип, подключите файл к программе оператором '$Include: 'qb.bi'. Содержимое файла 'qb.bi' можно просмотреть с помощью команды Included Lines из меню View.

Обратите внимание на то, что для работы с прерываниями мало подключить файл 'qb.bi' к программе. Кроме этого, дополнительно должна быть загружена библиотека 'qb.qlb'. Подключение библиотеки осуществляется на этапе загрузки интегрированной среды указанием ключа /L в командной строке: qb /L.

А теперь поговорим о прерывании, шестнадцатитеричный номер которого равен 33h. Это прерывание обслуживает такое периферийное оборудование, как мышь. При загрузке операционной системы на прерывание 33h вешается заглушка, которая позволяет системе работать без сбоев. Для того, чтобы использовать мышь, необходимо подключить ее к машине и загрузить драйвер.

После загрузки драйвера заглушка на прерывании 33h заменяется программой обработки прерывания, которая принимает информацию, поступающую от манипулятора, обрабатывает ее, информирует пользователя о состоянии мыши и управляет его работой. Управление работой мыши осуществляется через драйвер посредством тридцати с лишним функций. Сейчас мы рассмотрим только несколько самых необходимых.

Работу с мышью следует начинать с выполнения функции 0, позволяющей проверить, загружен ли драйвер мыши в память, а если загружен, то подключена ли мышь к компьютеру. Если получены положительные ответы на оба вопроса, драйвер помещает в регистр AX значение FFFFh и проводит инициализацию. При этом указатель мыши устанавливается в центр экрана на нулевой странице и удаляется с экрана, курсор мыши принимает форму по умолчанию, и, наконец, определяется, что курсор может перемещаться по всей поверхности экрана. Кроме этого, в регистре BX процессора записывается информация о количестве кнопок мыши. Если хотя бы один ответ отрицательный, инициализация не проводится и в AX остается 0. В этом случае с мышью работать нельзя.

Следующие две функции, 01h и 02h, управляют режимом видимости курсора мыши на экране. Первая выводит изображение курсора на экран, вторая удаляет его с экрана. Состояние курсора сохраняется в специальной переменной. Если значение переменной равно 0, курсор виден на экране. В противном случае - нет. Сразу после инициализации значение этой переменной равно -1. Каждое обращение к функции 02h уменьшает текущее значение на 1. Функция 01h увеличивает значение переменной на 1, но делает это только до тех пор, пока значение не станет равным нулю. Последующие вызовы функции 01h не изменяют значения переменной. Из-за этих особенностей функции следует применять попарно, чтобы не потерять курсор.

Для вызова этих функций необходимо в регистр AX записать 01h или 02h соответственно.

Наконец, функция 03h. Эта функция позволяет определить координаты курсора на экране и текущее состояние кнопок. При вызове функции в регистр AX записывается номер функции. В регистрах CX и DX возвращается горизонтальная и вертикальная координата курсора. Состояние кнопок можно определить, если прочитать содержимое регистра BX.

В регистре BX используются только три первых бита. Бит принимает значение 1 (установлен) если кнопка нажата и 0 (сброшен) в противном случае. Нулевой бит отвечает за левую кнопку мыши, первый - за правую, а второй - за центральную.

Значения координат курсора, возвращаемые в регистрах CX и DX, соответствуют действительности, если вы работаете в графическом режиме. Но если Вы используете текстовый режим работы дисплея, знайте - Вас бессовестно обманывают, в текстовом режиме положение курсора возвращается в "виртуальных" пикселах. Чтобы перейти к нормальным координатам, строке и столбцу, разделите полученные значения на ширину и высоту, занимаемую одним символом на экране.

Даже если вы работаете в графическом режиме, драйвер вводит Вас в заблуждение, хотя и не так сильно как в текстовом. Обратите внимание на то, что отсчет координат ведется не с единицы, а с нуля. Поэтому левый верхний угол экрана имеет координаты (0,0), а правый нижний (количество строк -1, количество столбцов-1).

(Окончание следует)

Сергей ОСОКО

Версия для печатиВерсия для печати

Номер: 

37 за 1997 год

Рубрика: 

Азбука программирования
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!