работа с мышкой

Тема в разделе "Другие", создана пользователем A, 23 ноя 2010.

  1. A

    A Гость

    Помогите пожалуйста переделать, чтобы каждый раз линии рисовались новым цветом.
    Код (Text):
    ; mousedr.asm
    ;Рисует на экране прямые линии, оканчивающиеся в позициях, которые указываются мышью.
    ;
    .model tiny
    .code
    org          100h                         ; COM-файл.
    .186                                          ; Для команжы shr cx, 3.
    start:
    mov          ax, 12h
    int          10h                            ; Видеорежим 640*480.
    mov          ax, 0                       ; Инициализировать мышь.
    int          33h
    mov          ax, 1                       ; Показать курсор мыши.
    int          33h

    mov          ax, 000Ch                   ; Установить обработчик событий мыши.
    mov          cx, 0002h                   ; Событие - нажатие левой кнопки.
    mov          dx, offset handler          ; ES:DX - адрес обработчика.
    int          33h

    mov          ah, 0                       ; Ожидание нажатия любой клавиши.
    int          16h
    mov          ax, 000Ch
    mov          cx, 0000h                   ; Удалить обработчик событий мыши.
    int          33h
    mov          ax, 3                       ; Текстоый режим.
    int          10h
    ret                                         ; Конец программы.

    ; Обработчик событий мыши: при первом нажатии выводит точку на экран,
    ; при каждом дальнейшем вызове проводит прямую линию от предыдущей
    ; точки к текущей.

    handler:
    push            0A000h
    pop          es                          ; ES - начало видеопамяти.
    push            cs
    pop          ds                          ; DS - сегмент кода и данных этой программы.
    push            cx                           ; CX (X-координата) и DX(Y-координата)
    push            dx                           ; потребуются в конце.

    mov          ax, 2                       ; Спрятать курсор мыши перед выводом на экран.
    int          33h

    cmp          word ptr previous_X, -1          ; Если это первый вызов,
    je           first_point                    ; только вывести точку.

    call            line_bresenham                  ; Иначе - провести прямую.                                                

    exit_handler:
    pop          dx                          ; Восстановить CX и DX
    pop          cx
    mov          previous_X, cx                 ; и запомнить их как предыдущие
    mov          previous_Y, dx                 ; координаты.

    mov          ax, 1                       ; Показать курсор мыши.
    int          33h

    retf                                          ; Выход из обработчика - команда RETF.

    first_point:
    call            putpixellb                   ; Вывод одной точки (при первом вызове).
    jmp          short exit_handler

    ; Процедура рисования прямой линии с использованием алгоритма Брезенхама.
    ; Вывод CX, DX - X, Y начальной точки.
    ; previous_X, previous_Y - X, Y начальной точки.

    line_bresenham:
    mov          ax, cx
    sub          ax, previous_X                 ; AX = длина проекции прямой на ось X.
    jns          dx_pos                         ; Если AX отрицательный -
    neg          ax                          ; сменить его знак, причем
    mov          word ptr X_increment, 1          ; координата X при выводе
    jmp          short dx_neg                    ; прямой будет расти.
    dx_pos: mov          word ptr X_increment, -1                ; Иначе - уменьшаться.

    dx_neg: mov          bx, dx
    sub          bx, previous_Y                 ; BX = длина проекции прямой на ось Y.
    jns          dy_pos                         ; Если BX отрицательный -
    neg          bx                          ; сменить его знак, причем
    mov          word ptr Y_increment, 1          ; координата Y при выводе
    jmp          short dy_neg                 ; прямой будет расти.
    dy_pos: mov          word ptr Y_increment, -1                ; иначе - уменьшаться.
    dy_neg:
    shl          ax, 1                       ; Удвоить значения проекций,
    shl          bx, 1                       ; чтобы избежать работы с полуцелыми числами.

    call            putpixellb                   ; Вывести первую точку (прямая рисуется от
    ; CX, DX к previous_X, previous_Y).
    cmp          ax, bx                      ; Если проекция на ось X больше, чем на Y,
    jna          dx_le_dy
    mov          di, ax                      ; DI будет указывать, в какую сторону мы
    shr          di, 1                       ; отклонились от идеальной прямой.
    neg          di                          ; Оптимальное начальное значение DI:
    add          di, bx                      ; DI = 2 * dy - dx
    cycle:
    cmp          cx, word ptr previous_X          ; Основной цикл выполняется,
    je           exit_bres                   ; пока X не станет равное previous_X.
    cmp          di, 0                       ; Если DI > 0,
    jl           fractlt0

    add          dx, word ptr Y_increment     ; перейти к следующему Y
    sub          di, ax                      ; и уменьшить DI на 2 * dx.
    fractlt0:
    add          cx, word ptr X_increment     ; Следующий X (на каждом шаге).
    add          di, bx                      ; Увеличить на DI на 2 * dy.
    call            putpixellb                   ; Вывести точку.                                                                                                             ;!!!!!
    jmp          short cycle                    ; Продолжить цикл.

    dx_le_dy:                                                    ; Если проекция на ось Y больше, чем на X.
    mov          di, bx
    shr          di, 1
    neg          di                          ; Оптимальное начальное значение DI:
    add          di, ax                      ; DI = 2 * dx - dy.
    cycle2:
    cmp          dx, word ptr previous_Y          ; Основной цикл выполняется,
    je           exit_bres                   ; пока Y не станет равным previous_Y.
    cmp          di, 0                       ; Если DI > 0,
    jl           fractlt02
    add          cx, word ptr X_increment     ; перейти к следующему X
    sub          di, bx                      ; и уменьшить DI на 2 * dy,
    fractlt02:
    add          dx, word ptr Y_increment     ; Следующий Y (на каждом шаге).
    add          di, ax                      ; Увеличить DI на 2 * dy,
    call            putpixellb                   ; вывести точку,
    jmp          short cycle2                 ; продолжить цикл.
    exit_bres:
    ret                                         ; Конец процедуры.

    ; Процедура вывода точки на экран в режиме, использующем один бит для
    ; хранения одного пикселя.
    ; DX = строка, CX = столбец.
    ; Все регистры сохраняются.
    putpixellb:
    pusha                                        ; Сохранить регистры.
    xor          bx, bx
    mov          ax, dx                      ; AX = номер строки.
    imul            ax, ax, 80                   ; AX = номер строки x число байтов в строке.
    push            cx
    shr          cx, 3                       ; CX = номер байта в строке.
    add          ax, cx                      ; AX = номер байта в видеопамяти.
    mov          di, ax                      ; Поместить его в SI и DI для команд
    mov          si, di                      ; строковой обработки.

    pop          cx                          ; CX снова содержит номер столбца.
    mov          bx, 0080h
    and          cx, 07h                          ; Последние три бита CX =
    ; остаток от деления на 8 = номер бита в байте
    ; считая справа налево.
    shr          bx, cl                      ; Теперь в BL установлен в 1 нужный бит.

    lods            es: byte ptr some_label       ; AL = байт из видеопамяти.
    ;or          ax, bx                      ; Установить выводимый бит в 1,
    ; Чтобы стереть пиксел с экрана, эту команду OR можно заменить на
    not bx
    and ax, bx
    ; или лучше инициализировать BX не числом 0080h, а числом FF7Fh и использовать
    ; только and
    stosb                                        ; И вернуть байт на место.
    popa                                          ; Восстановить регистры.
    ret                                         ; Конец.

    previous_X                   dw  -1                  ; Предыдущая X-координата.
    previous_Y                   dw  -1                  ; Предыдущая Y-координата.
    Y_increment                  dw  -1                  ; Направление изменения Y.
    X_increment                  dw  -1                  ; Направление изменения X.
    some_label:                                                 ; Метка, используемая для переопределения
    ; сегмента-источника для lods с DS на ES.
    end  start
     
  2. A

    A Гость

    все. я разобрался. вот, если кому нужно.
    Код (Text):
    ; mousedr.asm
    ;Рисует на экране прямые линии, оканчивающиеся в позициях, которые указываются мышью.
    ;
    .model  tiny
    .code

    org     100h            ; COM-файл.
    .186                    ; Для команжы shr cx, 3.
    start:
    mov     ax, 12h
    int     10h         ; Видеорежим 640*480.
    mov     ax, 0           ; Инициализировать мышь.
    int     33h
    mov     ax, 1           ; Показать курсор мыши.
    int     33h

    mov     ax, 000Ch       ; Установить обработчик событий мыши.
    mov     cx, 0002h       ; Событие - нажатие левой кнопки.
    mov     dx, offset handler  ; ES:DX - адрес обработчика.
    int     33h

    mov     ah, 0           ; Ожидание нажатия любой клавиши.
    int     16h
    mov     ax, 000Ch
    mov     cx, 0000h       ; Удалить обработчик событий мыши.
    int     33h
    mov     ax, 3           ; Текстоый режим.
    int     10h
    ret                 ; Конец программы.

    ; Обработчик событий мыши: при первом нажатии выводит точку на экран,
    ; при каждом дальнейшем вызове проводит прямую линию от предыдущей
    ; точки к текущей.

    handler:
    inc color
    push        0A000h
    pop     es          ; ES - начало видеопамяти.
    push        cs
    pop     ds          ; DS - сегмент кода и данных этой программы.
    push        cx          ; CX (X-координата) и DX(Y-координата)
    push        dx          ; потребуются в конце.

    mov     ax, 2           ; Спрятать курсор мыши перед выводом на экран.
    int     33h

    cmp     word ptr previous_X, -1; Если это первый вызов,
    je      first_point     ; только вывести точку.

    call        line_bresenham  ; Иначе - провести прямую.                          

    exit_handler:
    pop     dx          ; Восстановить CX и DX
    pop     cx
    mov     previous_X, cx  ; и запомнить их как предыдущие
    mov     previous_Y, dx  ; координаты.

    mov     ax, 1           ; Показать курсор мыши.
    int     33h

    retf                    ; Выход из обработчика - команда RETF.

    first_point:       
    call        putpixellb      ; Вывод одной точки (при первом вызове).
    mov         ah, 2
    mov         dl, 07h        
    int         21h
    jmp     short exit_handler     

    ; Процедура рисования прямой линии с использованием алгоритма Брезенхама.
    ; Вывод CX, DX - X, Y начальной точки.
    ; previous_X, previous_Y - X, Y начальной точки.

    line_bresenham:
    mov     ax, cx
    sub     ax, previous_X  ; AX = длина проекции прямой на ось X.
    jns     dx_pos      ; Если AX отрицательный -
    neg     ax          ; сменить его знак, причем
    mov     word ptr X_increment, 1; координата X при выводе
    jmp     short dx_neg    ; прямой будет расти.
    dx_pos: mov     word ptr X_increment, -1; Иначе - уменьшаться.

    dx_neg: mov     bx, dx
    sub     bx, previous_Y  ; BX = длина проекции прямой на ось Y.
    jns     dy_pos      ; Если BX отрицательный -
    neg     bx          ; сменить его знак, причем
    mov     word ptr Y_increment, 1; координата Y при выводе
    jmp     short dy_neg        ; прямой будет расти.
    dy_pos: mov     word ptr Y_increment, -1; иначе - уменьшаться.
    dy_neg:
    shl     ax, 1           ; Удвоить значения проекций,
    shl     bx, 1           ; чтобы избежать работы с полуцелыми числами.

    call        putpixellb      ; Вывести первую точку (прямая рисуется от
    ; CX, DX к previous_X, previous_Y).
    cmp     ax, bx          ; Если проекция на ось X больше, чем на Y,
    jna     dx_le_dy
    mov     di, ax          ; DI будет указывать, в какую сторону мы
    shr     di, 1           ; отклонились от идеальной прямой.
    neg     di          ; Оптимальное начальное значение DI:
    add     di, bx          ; DI = 2 * dy - dx
    cycle:
    cmp     cx, word ptr previous_X; Основной цикл выполняется,
    je      exit_bres       ; пока X не станет равное previous_X.
    cmp     di, 0           ; Если DI > 0,
    jl      fractlt0

    add     dx, word ptr Y_increment; перейти к следующему Y
    sub     di, ax          ; и уменьшить DI на 2 * dx.
    fractlt0:
    add     cx, word ptr X_increment; Следующий X (на каждом шаге).
    add     di, bx          ; Увеличить на DI на 2 * dy.
    call        putpixellb      ; Вывести точку.                                                    ;!!!!!
    jmp     short cycle     ; Продолжить цикл.

    dx_le_dy:                       ; Если проекция на ось Y больше, чем на X.
    mov     di, bx
    shr     di, 1
    neg     di          ; Оптимальное начальное значение DI:
    add     di, ax          ; DI = 2 * dx - dy.
    cycle2:
    cmp     dx, word ptr previous_Y; Основной цикл выполняется,
    je      exit_bres       ; пока Y не станет равным previous_Y.
    cmp     di, 0           ; Если DI > 0,
    jl      fractlt02
    add     cx, word ptr X_increment; перейти к следующему X
    sub     di, bx          ; и уменьшить DI на 2 * dy,
    fractlt02:
    add     dx, word ptr Y_increment; Следующий Y (на каждом шаге).
    add     di, ax          ; Увеличить DI на 2 * dy,
    call        putpixellb      ; вывести точку,
    jmp     short cycle2        ; продолжить цикл.
    exit_bres:
    mov         ah, 2
    mov         dl, 07h        
    int         21h
    ret                 ; Конец процедуры.

    ; Процедура вывода точки на экран в режиме, использующем один бит для
    ; хранения одного пикселя.
    ; DX = строка, CX = столбец.
    ; Все регистры сохраняются.

    putpixellb:
    pusha                   ; Сохранить регистры.
    mov ah,0ch
    mov bh,0
    mov al,[color]
    int 10h

    popa                    ; Восстановить регистры.
    ret                 ; Конец.

    previous_X          dw  -1      ; Предыдущая X-координата.
    previous_Y          dw  -1      ; Предыдущая Y-координата.
    Y_increment         dw  -1      ; Направление изменения Y.
    X_increment         dw  -1      ; Направление изменения X.
    color db 10
    some_label:                     ; Метка, используемая для переопределения
    ; сегмента-источника для lods с DS на ES.
    end start
     
Загрузка...

Поделиться этой страницей