Консультация № 174548
26.11.2009, 02:08
35.00 руб.
0 8 1
(tasm x86 Dos) Здравствуйте, уважаемые программисты! Нужна помощь в решении задачи.

Написать программу, которая: 1 - устанавливает курсор мыши в центр экрана; 2 - при перемещении курсора мыши за область квадрата 80*80 пикселей в центре экрана, возвращает курсор в центр экрана. Выход из программы происходит после нажатия любой клавиши на клавиатуре.

Обсуждение

давно
Посетитель
7438
7205
26.11.2009, 11:07
общий
В графическом или текстовом режиме?
Если в графическом, то в каком именно?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
26.11.2009, 16:33
общий
26.11.2009, 17:26
это ответ
Здравствуйте, Svistaplas90.

Вариант программы — в приложении. Поскольку Вы не указали и не уточнили в мини-форуме, какой видеорежим должен использоваться, я написал программу для графического видеорежима VGA 320x200, 256 цветов. Этот видеорежим должны поддерживать все современные компьютеры.

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

Успехов!

Приложение:
JUMPS
LOCALS @@
.model tiny

; размеры экрана в пикселях
SCR_WIDTH EQU 320
SCR_HEIGHT EQU 200

; размеры допустимой области в центре экрана
RC_WIDTH EQU 80
RC_HEIGHT EQU 80

.code
org 100h
start:
mov ax,13h ; режим VGA 320x200, 256 цветов
int 10h

xor ax,ax ; инициализируем мышь
int 33h ; если AX=0FFFFh на выходе, то драйвер мыши установлен
inc ax
jnz @@exit

; закрашиваем прямоугольник RC_WIDTH x RC_HEIGHT в центре экрана для наглядности
; этот способ очень медленный, но скорость нам здесь несущественна

mov ax,0C01h ; поставить синюю точку
mov bh,0 ; видеостраница
mov dx,SCR_HEIGHT/2 - RC_HEIGHT/2
@@next_line:
mov cx,SCR_WIDTH/2 - RC_WIDTH/2
@@next_pixel:
int 10h
inc cx

; Такое вычисление: SCR_WIDTH/2 - RC_WIDTH/2 + RC_WIDTH
; вместо SCR_WIDTH/2 + RC_WIDTH/2
; связано с тем, что, в общем случае, ширина (высота) может быть нечетной.
; В данном случае (ширина и высота четные), эти выражения дают одинаковый результат.

cmp cx,SCR_WIDTH/2 - RC_WIDTH/2 + RC_WIDTH
jb @@next_pixel
inc dx
cmp dx,SCR_HEIGHT/2 - RC_HEIGHT/2 + RC_HEIGHT
jb @@next_line
; ----- конец закраски прямоугольника

mov ax,0Ch ; 000Ch - устанавливаем обработчик событий от мыши
mov cx,1 ; отслеживаем только движение мыши
mov dx,offset mouse_handler
int 33h

mov al,1 ; ax=1 - показываем курсор мыши
int 33h

call mouse_move_to_center

xor ax,ax
int 16h

mov ax,0Ch
xor cx,cx ; сбрасываем обработчик мыши
int 33h

@@exit:
mov ax,3 ; восстанавливаем текстовый режим 80x25
int 10h
int 20h ; выходим из программы

mouse_handler PROC FAR
; CX - горизонтальная позиция
; DX - вертикальная позиция
; нам не нужно сохранять/восстанавливать регистры, т.к. за нас это делает драйвер
shr cx,1
cmp cx,SCR_WIDTH/2 - RC_WIDTH/2
jb @@move
cmp cx,SCR_WIDTH/2 - RC_WIDTH/2 + RC_WIDTH
jae @@move
cmp dx,SCR_HEIGHT/2 - RC_HEIGHT/2
jb @@move
cmp dx,SCR_HEIGHT/2 - RC_HEIGHT/2 + RC_HEIGHT
jb @@exit
@@move:
call mouse_move_to_center
@@exit:
ret
mouse_handler ENDP

mouse_move_to_center PROC
mov ax,4
mov cx,SCR_WIDTH
mov dx,SCR_HEIGHT/2
int 33h
ret
mouse_move_to_center ENDP

end start
Неизвестный
26.11.2009, 16:48
общий
В графическом. Видеорежим 13h
давно
Посетитель
7438
7205
26.11.2009, 16:58
общий
Svistaplas90:
Вот видите, не указали сразу видеорежим, и получили ответ с другим, чем Вы хотели !
Мы не можем догадываться, что Вам надо !
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
26.11.2009, 17:05
общий
Svistaplas90:
Считаю необходимым сделать еще одно пояснение.
В функции mouse_move_to_center у меня написано
mov al,4
Вообще-то, для прерываения 33h номер функции задается в регистре AX. Но в _этой_ простой программе перед вызовом функции mouse_move_to_center всегда AH=0. Для первого вызова это очевидно из текста программы. При вызове из обработчика мыши AX содержит битовую маску, идентифицирующую произошедшее событие, при этом AH=0. В общем случае, не стОит делать предположений о содержимом AX на момент вызова функции и следует писать
mov ax,func_number.
Неизвестный
26.11.2009, 17:19
общий
Несложно исправить для режима 13h (320x200, 256 цветов). Надо только учесть, что драйвер мыши использует виртуальные координаты и X-координата мыши удвоена (для перевода X-координаты мыши, полученной от драйвера, в пиксели, необходимо поделить пополам). По-видимому, преподаватели задают этот режим, чтобы студенты слегка помучились :)

Код:

JUMPS
LOCALS @@
.model tiny

; размеры экрана в пикселях
SCR_WIDTH EQU 320
SCR_HEIGHT EQU 200

; размеры допустимой области в центре экрана
RC_WIDTH EQU 80
RC_HEIGHT EQU 80

.code
org 100h
start:
mov ax,13h ; режим VGA 320x200, 256 цветов
int 10h

xor ax,ax ; инициализируем мышь
int 33h ; если AX=0FFFFh на выходе, то драйвер мыши установлен
inc ax
jnz @@exit

; закрашиваем прямоугольник RC_WIDTH x RC_HEIGHT в центре экрана для наглядности
; этот способ очень медленный, но скорость нам здесь несущественна

mov ax,0C01h ; поставить синюю точку
mov bh,0 ; видеостраница
mov dx,SCR_HEIGHT/2 - RC_HEIGHT/2
@@next_line:
mov cx,SCR_WIDTH/2 - RC_WIDTH/2
@@next_pixel:
int 10h
inc cx

; Такое вычисление: SCR_WIDTH/2 - RC_WIDTH/2 + RC_WIDTH
; вместо SCR_WIDTH/2 + RC_WIDTH/2
; связано с тем, что, в общем случае, ширина (высота) может быть нечетной.
; В данном случае (ширина и высота четные), эти выражения дают одинаковый результат.

cmp cx,SCR_WIDTH/2 - RC_WIDTH/2 + RC_WIDTH
jb @@next_pixel
inc dx
cmp dx,SCR_HEIGHT/2 - RC_HEIGHT/2 + RC_HEIGHT
jb @@next_line
; ----- конец закраски прямоугольника

mov ax,0Ch ; 000Ch - устанавливаем обработчик событий от мыши
mov cx,1 ; отслеживаем только движение мыши
mov dx,offset mouse_handler
int 33h

mov al,1 ; ax=1 - показываем курсор мыши
int 33h

call mouse_move_to_center

xor ax,ax
int 16h

mov ax,0Ch
xor cx,cx ; сбрасываем обработчик мыши
int 33h

@@exit:
mov ax,3 ; восстанавливаем текстовый режим 80x25
int 10h
int 20h ; выходим из программы

mouse_handler PROC FAR
; CX - горизонтальная позиция
; DX - вертикальная позиция
; нам не нужно сохранять/восстанавливать регистры, т.к. за нас это делает драйвер
shr cx,1 ; в режиме 320x200 X-координата мыши удвоена
cmp cx,SCR_WIDTH/2 - RC_WIDTH/2
jb @@move
cmp cx,SCR_WIDTH/2 - RC_WIDTH/2 + RC_WIDTH
jae @@move
cmp dx,SCR_HEIGHT/2 - RC_HEIGHT/2
jb @@move
cmp dx,SCR_HEIGHT/2 - RC_HEIGHT/2 + RC_HEIGHT
jb @@exit
@@move:
call mouse_move_to_center
@@exit:
ret
mouse_handler ENDP

mouse_move_to_center PROC
mov ax,4
mov cx,SCR_WIDTH ; в режиме 320x200 X-координата мыши удвоена
mov dx,SCR_HEIGHT/2
int 33h
ret
mouse_move_to_center ENDP

end start
давно
Посетитель
7438
7205
26.11.2009, 17:25
общий
Я подправил программу в ответе
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
26.11.2009, 17:29
общий
Спасибо большое :)
Форма ответа