Графические устройства

         

Подпрограмма построения



Пример 6.5. Подпрограмма построения рисунка маскируемого курсора

Showpnt: pusha сохранение содержимого регистров
push Cur win сохранение исходного окна
mov ax, Winpnt ах = окно с рисунком курсора
mov Cur win, ax Cur win = Winpnt
call setwin установка исходного окна
xor si, si очистка регистра si
mov di, Offspnt di = адрес в сегменте видеопамяти
mov ex, pntYsize сх = кол-во повторов внешнег о цикла
mov bx, horsize вычисляем константу для
sub bx, pntXsize коррекции адресов строк
Sh_l: push ex сохраняем значение счетчика строк
mov ex, pntXsize ex = количество точек в строке рисунка
Sh_2 : mov al, es: [di] ! ! al = код точки исходного фона
mov pntbuff[si], al ! ! сохраняем его в pntbuf f
and al, pntmask[si] ! ! накладываем маску


xor al, pnt image [si] ! ! формируем новый код точки
stosb ! ! и записываем его в видеопамять
inc si ! ! коррекция адреса рисунка
or di, di адрес в пределах текущего окна ?
jnz @F -> да, обходим следующую команду
call nxtwin установка следующего окна
@@: loop sh 2 управление повторами цикла
pop ex восстанавливаем счетчик строк
add di, bx корректируем адрес видеопамяти
jnc @F -> адрес в пределах текущего окна
call nxtwin установка следующего окна
@@: loop sh 1 управление внутренним циклом
pop Car win восстановление значения Cur win
popa восстановление всех регистров
call setwin восстановление исходного окна
ret возврат из подпрограммы

Начало примера 6.5 отличается от примера 6.4 только одной командой. Вместо записи адреса массива pntimage в регистр si последний просто очищается. Это сделано потому, что регистр si используется для доступа к трем массивам, а не к одному, как это было в примере 6.4.

Принципиальное различие между примерами в основных действиях, выполняемых во внутреннем цикле, который в данном случае имеет метку sh_2. Первая команда внутреннего цикла считывает код очередной точки из видеопамяти в регистр al, а вторая сохраняет его в очередном байте массива pntbuf f. После этого в регистр al помещается результат вычисления логической функции "И" от исходного значения регистра и содержимого очередного байта маски. В зависимости от кода байта маски регистр al либо будет очищен, либо его исходное значение не изменится — третьего не дано. Следующая команда завершает формирование нового кода точки, она вычисляет логическую функцию "исключающее ИЛИ" от содержимого регистра al и очередного байта массива pntimage. Остается записать новый код точки в видеопамять, что и делает команда stosb, одновременно она увеличивает содержимое регистра di на 1.

Основные действия выполнены, шестая команда увеличивает на 1 адрес оперативной памяти (содержимое регистра si). Адрес видеопамяти (содержимое di) увеличила команда stosb, но надо проверить, остался он в пределах текущего видеосегмента или нет. Признаком выхода за пределы сегмента является нуль в регистре di, при этом подпрограмма nxtwin установит следующее окно видеопамяти. Повторами внутреннего цикла управляет команда :оор Sh_2.

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

В заключение из стека выталкиваются исходные значения переменной cur_wir. У всех регистров, восстанавливается исходное окно видеопамяти и происходит возврат на вызывающий модуль.

Массивы в другом сегменте. Текст примера 6.5 составлен из расчета па то, что массивы pntimage, pntmask и pntbuff расположены в разделе данных п для доступа к ним используется регистр ds, имя которого не указывается перед операндами. Если вы предпочитаете расположить указанные массивы в другом сегменте, то в трех командах примера 6.5 перед именами массивов надо явно указать имя выбранного вами сегментного регистра. Например, mov fs:pntbuf f [si], ai, если для доступ а к массиву pntbuff используется сегментный регистр fs.

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

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

Подпрограмма Hidepnt. Текст подпрограммы, выполняющей удаление изображения курсора, приведен в примере 6.6. В нем использованы те же переменные, что и в примерах 6.4 и 6.5, а из трех массивов нужен только pntbuff, содержащий ранее сохраненный фон.



Содержание раздела