Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. ;Эффективное программирование в KOLIBRI
  2. ;Оптимизированный компонент CheckBox (Исходный вариант от Maxxxx32)
  3. ;Оптимизирован вывод строки надписи для CheckBox'a + теперь, при проверке не происходит подсчет кол-ва символов в строке
  4. ;Оптимизация команд - отказался от сохранения регистров в стеке.
  5. ;17.07.2006 произведена оптимизация, при установке чек бокса в положение включено последующие чек боксы в тот же промежуток времени не проверяются
  6. ;<Lrz>  - Теплов Алексей  www.test-kolibri.narod.ru
  7.  
  8. macro use_check_box
  9. {
  10. ch_text_margin=4     ;расстояние от прямоугольника чек бокса до надписи
  11. ch_size=10           ;размер квадрата чек бокса
  12. ch_left equ [edi]    ;координата начала рисования по х
  13. ch_top equ [edi+2]   ;координата начала рисования по у
  14. ch_color equ [edi+4] ;цвет внутри checkbox
  15. ch_border_color equ [edi+8] ;цвет рамки checkbox
  16. ch_text_color equ [edi+12]  ;цвет текста
  17. ch_text_ptr equ [edi+16]    ;указатель на начало текстовой строки
  18. ch_text_length equ [edi+20] ;длина надписи (2^64 такой длины может быть текст)
  19. ch_flags equ [edi+24]       ;флаги
  20. check_box:
  21. .draw:
  22. pusha   ;сохраним все регистры
  23.         mov     eax,38          ;рисование линии
  24.         mov     bx,ch_left      ;положение по х
  25.         ;mov     cx,bx           ;сохраним в регистре cx значение bx
  26.         push   bx  ;3 - микрооперации  используя стек можно выиграть в размере, используя регистры - в скорости
  27.         shl     ebx,16          ;сдвинем на 16 разрядов в лево (умножим на 65536)
  28.         pop    bx  ;2 - микрооперации  на данный момент сформирована [координата начала по оси x]*65536 + [координата начала по оси x]
  29.         ;mov     bx,cx           ;восстановим значение bx
  30.         mov     cx,ch_top       ;загрузим в cx значение y
  31.         mov     si,cx           ;сохраним значение регистра cx в регистр указатель si
  32.         ;push   cx
  33.         shl     ecx,16          ; сдвинем на 16 разрядов в лево (умножим на 65536)      mov     cx,si           ;восстановим значение регистра cx
  34.         mov     cx,si           ;восстановим значение регистра cx
  35.         ;pop    cx      ;[координата начала по оси y]*65536 + [координата начала по оси y]
  36.         ;push   cx
  37.         add     cx,ch_size ;[координата начала по оси y]*65536 + [координата конца по оси y]
  38.         mov     edx,ch_border_color ;Цвет линии
  39.         int     0x40   ;рисование вертикальной левой линии квадрата (прямоугольника)
  40. ;
  41.         mov     bp,bx   ;сохраним регистр bx в регистре указателя базы
  42.         ;push   bx   ;втолкнуть в bx [координата начала по оси х]*65536 + [координата начала по оси x]
  43.         add     bx,ch_size      ;[координата начала + длина стороны по оси х]
  44.         ror     ebx,16          ;[координата начала + дина стороны по оси х]*65536
  45.         add     bx,ch_size      ;[координата начала+длина стороны по оси х]*65536 + [координата начала+длина стороны по оси x]
  46.         int     0x40
  47.         mov     bx,bp           ;восстановим значение регистра bx
  48.         ;pop    bx
  49.         mov     cx,si           ;сохраним значение регистра cx в регистр указатель
  50.         ;pop    cx
  51.         int     0x40
  52.         add     cx,ch_size      ;добавим размер стороны
  53.         mov     si,cx           ;сохраним значение регистра cx в регистр указатель si
  54.         ;push   cx
  55.         shl     ecx,16
  56.         mov     cx,si
  57.         ;pop    cx
  58.         int     0x40            ;нарисовали прямоугольник
  59.  
  60.         mov     eax,13          ;закрашиваем его. Функция 13 - нарисовать полосу
  61.         mov     bx,ch_left      ;загрузить в bx, положение по х
  62.         add     bx,1            ;сдвинем на 1 т.е. прибавим 1 иначе затрется рамка
  63.         shl     ebx,16          ;сдвинем на 16 разрядов в лево (умножим на 65536)
  64.         mov     bx,ch_size      ;прибавим длину стороны прямоугольника
  65.         sub     bx,1            ;вычтем 1 т.к. иначе затрется рамка
  66.         mov     bp,bx           ; сохраним регистр bx в регистре указателя базы
  67.         ;push   bx
  68.         mov     cx,ch_top       ;загрузим координаты по y
  69.         add     cx,1            ;сдвинем на 1 т.е. прибавим 1 иначе затрется рамка
  70.         shl     ecx,16          ;сдвинем на 16 разрядов в лево (умножим на 65536)
  71.         mov     cx,bp           ;восстановим значение регистра cx
  72.         ;pop    cx
  73.         mov     edx,ch_color    ;загрузим цвет полосы
  74.         int     0x40            ;закрасили
  75.         bt      dword ch_flags,1  ;достать значение бита из переменной и поместить в  флаг CF
  76.         jnc     @f              ;в если CF=1, то выполним следующую процедуру иначе перейти на нижнюю @@
  77.         call    .draw_ch  ;нарисовать включенный чек бокс
  78. @@:
  79. ;----------------------------
  80. ;расчет куда будет произведен вывод текста
  81. ;----------------------------
  82.         mov     bx,ch_left      ;загрузить значение х для чек бокса
  83.         add     bx,(ch_size+ch_text_margin) ;добавить размер стороны и расстояние на котором начнется вывод текста
  84.         shl     ebx,16          ;сдвинем на 16 разрядов в лево (умножим на 65536)
  85.         mov     bx,ch_top       ;загрузим значение по y
  86.         add     bx,(ch_size-9+2)        ;добавим значение длины стороны -9+2
  87.         mov     ecx,ch_text_color       ;загрузим цвет надписи
  88.  
  89.         mov     edx,ch_text_ptr         ;укажем адрес от куда нужно выводить строку
  90.         mov     esi,ch_text_length      ;Загрузим длину надписи в esi
  91.         xor     eax,eax                 ;внесем в eax значение вывода надписи на канву
  92.         add     eax,4
  93.         int     0x40            ;Вывод
  94. popa                            ;восстановить значения регистров из стека
  95. ret                             ;выйдем из процедуры
  96.  
  97. .clear_ch:                      ;очистка чек бокса
  98.         mov     edx,ch_color    ;цвет внутри чек бокса
  99.         jmp     @f              ;безусловный прыжок на нижнюю метку @@
  100.  
  101. .draw_ch:            ;нарисовать включенный чек бокс
  102.         mov     edx,ch_border_color     ;загрузить цвет
  103. @@:
  104.         mov     bx,ch_left      ;загрузить координату по х
  105.         add     bx,(ch_size/3)  ;добавить (сторона прямоугольника/3)
  106.         shl     ebx,16          ;сдвинем на 16 разрядов в лево (умножим на 65536)
  107.         mov     bx,(ch_size/2)  ;загрузить (сторона прямоугольника/2)
  108.         mov     bp,bx           ;сохраним регистр bx в регистре указателя базы
  109.         ;push   bx
  110.         mov     cx,ch_top       ;загрузить координату по у
  111.         add     cx,(ch_size/3)  ;добавить (сторона прямоугольника/3)
  112.         shl     ecx,16          ;сдвинем на 16 разрядов в лево (умножим на 65536)
  113.         mov     cx,bp           ;загрузим значения регистра указателя базы в cx
  114.         ;pop    cx
  115.         mov     eax,13          ;в eax - значения функции для вывода полосы т.е. по сути прямоугольника, который отображает включенный компонент чек бокс
  116.         int     0x40            ;вывод
  117. ret                             ;выйти из процедуры
  118.  
  119. .mouse:                 ;обработка мыши
  120. pusha
  121.         mov     eax,37          ;будем что то делать если у нас что - нить нажато
  122.         xor     ebx,ebx         ;обнулить регистр ebx (изменяет флаги)
  123.         add     ebx,2           ;внести в регистр значение 2
  124.         int     0x40            ;проверка не нажал ли пользователь кнопку мышки
  125.         test    eax,eax    ;проверка если у нас в eax=0, то установим флаг и выйдем
  126.         jnz     @f         ;перейти на нижнюю метку @@
  127.         btr     dword ch_flags,2  ;извлечение значения заданного бита в флаг cf и изменение его значения на нулевое.
  128.         popa                    ;если ничего не произошло, то восстановим значения регистров из стека
  129.         ret                     ;выход
  130. @@:
  131.         bts     dword ch_flags,2   ;проверка флага т.е. перенос в cf значение бита и установка бита в состояние включено
  132.         jc      .mouse_end         ;если CF=1 то перейти  в конец т.е. это выход
  133.         mov     esi,ch_text_length ;загрузить кол-во символов в текстовой строке
  134.         ;Умножение на 6 Быстрое умножение можно воспользоваться любым мз методов, но на старых Процессорах (386,486,P1)быстрее будет с инструкцией Lea
  135.         ;lea    esi,[eax*2+eax]
  136.         ;shl    eax,1
  137.         imul    esi,6               ; или можно и так умножить на 6
  138.         add     esi,ch_text_margin   ;добавить 3 - расстояние от чек бокса до надписи
  139.  
  140.         mov     eax,37          ;получим координаты мышки
  141.         xor     ebx,ebx         ;обнулить регистр
  142.         add     ebx,1           ;добавить 1
  143.         int     0x40                ;получить координаты курсора относительно окна
  144.  
  145.         mov     bx,ch_top           ;загрузить в bx значение координаты у
  146.         cmp     ax,bx               ;сравнить с с координатой курсора
  147.         jl      .mouse_end          ;SF <> OF если меньше
  148.         add     bx,ch_size          ;добавить размер
  149.         cmp     ax,bx               ;сравнить
  150.         jg      .mouse_end          ;ZF = 0 и SF = OF если больше
  151.  
  152.         shr     eax,16              ;разделим на 65536 или просто сдвинем биты на 16 значений
  153.         mov     bx,ch_left          ;произведем аналогичное сравнение
  154.         cmp     ax,bx                ;сравнить регистры
  155.         jl      .mouse_end           ;если меньше
  156.         add     bx,ch_size           ;добавить длину стороны прямоугольника
  157.         add     bx,si               ;Учесть в значении по х еще и длину надписи к чекбоксу
  158.         cmp     ax,bx                ;стравнить регистры
  159.         jg      .mouse_end           ;если больше
  160.  
  161.         bts     dword ch_flags,1  ;извлечение значения заданного бита в флаг cf и изменение его значения на 1.
  162.         jc      @f                ;CF=1 то перейти на нижнюю @@
  163.  
  164.         call    .draw_ch          ;отобразить включенный чек бокс
  165.         mov     dword [esp+24],1  ;дальнейшая проверка чек боксов бесмыслена, по этому в стек, где располагается ecx поместитм 0
  166.         jmp     .mouse_end        ;выйти
  167. @@:
  168.         btr     dword ch_flags,1  ;извлечение значения заданного бита в флаг cf и изменение его значения на нулевое.
  169.         call    .clear_ch         ;выключить чек бокс т.е. на месте закрашенного прямоугольника отобразить цвет фона.
  170. .mouse_end:
  171. popa                              ;восстановить регистры из стека
  172. ret                               ;выйти
  173. }
  174.  
  175. struc check_box left,top,color,border_color,text_color,text,text_length,flags
  176. {       ;структура параметров для чек бокса
  177. .left: dw left  ;+0     ;положение по х
  178. .top: dw top    ;+2     ;положение по у
  179. .color: dd color ;+4    ;цвет внутри чек бокса
  180. .border_color: dd border_color ;+8      цвет рамки
  181. .text_color: dd text_color     ;+12     цвет текста надписи
  182. .text: dd text       ;+16               адрес в коде программы где расположен текстр
  183. .text_length: dd text_length ; +20      длина текста
  184. .flags: dd flags+0   ;+24               флаги
  185. }
  186. ch_struc_size=28                        ;общая структура 28 байт
  187. macro draw_check_boxes start,end        ;рисовать чек боксы
  188. {
  189.         mov     edi,start                       ;Указатель на начало данных чек боксов т.е. на начало данных первого чекбокса
  190.         mov     ecx,((end-start)/ch_struc_size) ;Количество чек боксов
  191. @@:
  192.         call    check_box.draw                  ;Отобразить чек бокс
  193.         add     edi,ch_struc_size               ;Указатель на последующие чек боксы  т.е. +28
  194.         loop    @b      ;прыгнуть если в ecx/cx значение не 0 на верхнюю @@
  195. }
  196. macro mouse_check_boxes start,end       ;установка чек боксов, в зависимости от события
  197. {
  198.         mov     edi,start               ; Указатель на начало данных чек боксов т.е. на начало данных первого чекбокса
  199.         mov     ecx,((end-start)/ch_struc_size) ;Количество чек боксов
  200. @@:
  201.         call    check_box.mouse         ;проверка мышки и обработка событий
  202.         add     edi,ch_struc_size       ;Указатель на последующие чек боксы
  203.         loop    @b      ;прыгнуть если в ecx/cx значение не 0 на верхнюю @@
  204. }
  205. macro check_boxes_set_sys_color start,end,color_table
  206. {
  207.         mov     edi,start
  208.         mov     ecx,((end-start)/ch_struc_size)
  209.         mov     esi,color_table
  210. @@:
  211.         push    dword [esi+32]
  212.         pop     dword ch_text_color
  213.         push    dword [esi+36]
  214.         pop     dword ch_border_color
  215.         add     edi,ch_struc_size
  216.         loop    @b
  217. }