From 7df9c186219fc618e167e6f09af229fc2ac3ef23 Mon Sep 17 00:00:00 2001 From: "Alexey Teplov (" Date: Fri, 1 Sep 2006 05:24:43 +0000 Subject: [PATCH] add checkbox git-svn-id: svn://kolibrios.org@144 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../examples/checkbox/trunk/build_ru.bat | 2 + .../develop/examples/checkbox/trunk/check.inc | 207 ++++++++++++++++++ .../examples/checkbox/trunk/checkbox.asm | 108 +++++++++ 3 files changed, 317 insertions(+) create mode 100644 programs/develop/examples/checkbox/trunk/build_ru.bat create mode 100644 programs/develop/examples/checkbox/trunk/check.inc create mode 100644 programs/develop/examples/checkbox/trunk/checkbox.asm diff --git a/programs/develop/examples/checkbox/trunk/build_ru.bat b/programs/develop/examples/checkbox/trunk/build_ru.bat new file mode 100644 index 0000000000..134ca2a3ea --- /dev/null +++ b/programs/develop/examples/checkbox/trunk/build_ru.bat @@ -0,0 +1,2 @@ +@fasm checkbox.asm checkbox +@pause \ No newline at end of file diff --git a/programs/develop/examples/checkbox/trunk/check.inc b/programs/develop/examples/checkbox/trunk/check.inc new file mode 100644 index 0000000000..c725a25f13 --- /dev/null +++ b/programs/develop/examples/checkbox/trunk/check.inc @@ -0,0 +1,207 @@ +;Эффективное программирование в KOLIBRI +;Оптимизированный компонент CheckBox (Исходный вариант от Maxxxx32) +;Оптимизирован вывод строки надписи для CheckBox'a + теперь, при проверке не происходит подсчет кол-ва символов в строке +;Оптимизация команд - отказался от сохранения регистров в стеке. +;17.07.2006 произведена оптимизация, при установке чек бокса в положение включено последующие чек боксы в тот же промежуток времени не проверяются +;22.08.2006 произведена оптимизация команд, приняты во внимание замечания DIAMOND'а. +; - Теплов Алексей www.test-kolibri.narod.ru + +macro use_check_box +{ +ch_text_margin=4 ;расстояние от прямоугольника чек бокса до надписи +ch_size=10 ;размер квадрата чек бокса +ch_left equ [edi] ;координата начала рисования по х +ch_top equ [edi+2] ;координата начала рисования по у +ch_color equ [edi+4] ;цвет внутри checkbox +ch_border_color equ [edi+8] ;цвет рамки checkbox +ch_text_color equ [edi+12] ;цвет текста +ch_text_ptr equ [edi+16] ;указатель на начало текстовой строки +ch_text_length equ [edi+20] ;длина надписи (2^64 такой длины может быть текст) +ch_flags equ [edi+22] ;флаги +check_box: +.draw: +pusha ;сохраним все регистры + mov eax,38 ;рисование линии + movzx ebx,word ch_left ;положение по х + mov ecx,ebx ;сохраним в регистре cx значение bx 1 микрооперация + ;push bx ;3 - микрооперации используя стек можно выиграть в размере, используя регистры - в скорости + shl ebx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) + ;pop bx ;2 - микрооперации на данный момент сформирована [координата начала по оси x]*65536 + [координата начала по оси x] + mov bx,cx ;восстановим значение bx + movzx ecx,word ch_top ;загрузим в cx значение y + mov esi,ecx ;сохраним значение регистра cx в регистр указатель si + ;push cx + shl ecx,16 ; сдвинем на 16 разрядов в лево (умножим на 65536) mov cx,si ;восстановим значение регистра cx + mov cx,si ;восстановим значение регистра cx + ;pop cx ;[координата начала по оси y]*65536 + [координата начала по оси y] + ;push cx + add ecx,ch_size ;[координата начала по оси y]*65536 + [координата конца по оси y] + mov edx,ch_border_color ;Цвет линии + int 0x40 ;рисование вертикальной левой линии квадрата (прямоугольника) +; + mov ebp,ebx ;сохраним регистр bx в регистре указателя базы + ;push bx ;втолкнуть в bx [координата начала по оси х]*65536 + [координата начала по оси x] + add ebx,ch_size ;[координата начала + длина стороны по оси х] + ror ebx,16 ;[координата начала + дина стороны по оси х]*65536 + add ebx,ch_size ;[координата начала+длина стороны по оси х]*65536 + [координата начала+длина стороны по оси x] + int 0x40 + + mov bx,bp ;восстановим значение регистра bx + ;pop bx + mov cx,si ;сохраним значение регистра cx в регистр указатель + ;pop cx + int 0x40 + add ecx,ch_size ;добавим размер стороны + mov esi,ecx ;сохраним значение регистра cx в регистр указатель si + ;push cx + shl ecx,16 + mov cx,si + ;pop cx + int 0x40 ;нарисовали прямоугольник + + mov eax,13 ;закрашиваем его. Функция 13 - нарисовать полосу + movzx ebx,word ch_left ;загрузить в bx, положение по х + add ebx,1 ;сдвинем на 1 т.е. прибавим 1 иначе затрется рамка + shl ebx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) + mov bx,ch_size ;прибавим длину стороны прямоугольника + sub ebx,1 ;вычтем 1 т.к. иначе затрется рамка + mov bp,bx ;сохраним регистр bx в регистре указателя базы + ;push bx + movzx ecx,word ch_top ;загрузим координаты по y + add ecx,1 ;сдвинем на 1 т.е. прибавим 1 иначе затрется рамка + shl ecx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) + mov cx,bp ;восстановим значение регистра cx + ;pop cx + mov edx,ch_color ;загрузим цвет полосы + int 0x40 ;закрасили + + test dword ch_flags,2 ;достать значение бита из переменной и поместить в флаг CF + + jz @f ;в если CF=1, то выполним следующую процедуру иначе перейти на нижнюю @@ + call .draw_ch ;нарисовать включенный чек бокс +@@: +;---------------------------- +;расчет куда будет произведен вывод текста +;---------------------------- + movzx ebx,word ch_left ;загрузить значение х для чек бокса + add ebx,(ch_size+ch_text_margin) ;добавить размер стороны и расстояние на котором начнется вывод текста + shl ebx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) + mov bx,ch_top ;загрузим значение по y + add ebx,(ch_size-9+2) ;добавим значение длины стороны -9+2 + mov ecx,ch_text_color ;загрузим цвет надписи + + mov edx,ch_text_ptr ;укажем адрес от куда нужно выводить строку + movzx esi,word ch_text_length ;Загрузим длину надписи в esi + ;внесем в eax значение вывода надписи на канву + mov eax,4 + int 0x40 ;Вывод +popa ;восстановить значения регистров из стека +ret ;выйдем из процедуры + +.clear_ch: ;очистка чек бокса + mov edx,ch_color ;цвет внутри чек бокса + jmp @f ;безусловный прыжок на нижнюю метку @@ + +.draw_ch: ;нарисовать включенный чек бокс + mov edx,ch_border_color ;загрузить цвет +@@: + movzx ebx,word ch_left ;загрузить координату по х + add ebx,(ch_size/3) ;добавить (сторона прямоугольника/3) + shl ebx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) + mov bx,(ch_size/2) ;загрузить (сторона прямоугольника/2) + mov bp,bx ;сохраним регистр bx в регистре указателя базы + ;push bx + movzx ecx,word ch_top ;загрузить координату по у + mov eax,13 ;в eax - значения функции для вывода полосы т.е. по сути прямоугольника, который отображает включенный компонент чек бокс + add ecx,(ch_size/3) ;добавить (сторона прямоугольника/3) + shl ecx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) + mov cx,bp ;загрузим значения регистра указателя базы в cx + ;pop cx + + int 0x40 ;вывод +ret ;выйти из процедуры + +.mouse: ;обработка мыши +pusha + mov eax,37 ;будем что то делать если у нас что - нить нажато + mov ebx,2 ;внести в регистр значение 2 + int 0x40 ;проверка не нажал ли пользователь кнопку мышки + test eax,eax ;проверка если у нас в eax=0, то установим флаг и выйдем + jnz @f ;перейти на нижнюю метку @@ + btr dword ch_flags,2 ;извлечение значения заданного бита в флаг cf и изменение его значения на нулевое. + popa ;если ничего не произошло, то восстановим значения регистров из стека + ret ;выход +@@: + bts dword ch_flags,2 ;проверка флага т.е. перенос в cf значение бита и установка бита в состояние включено + jc .mouse_end ;если CF=1 то перейти в конец т.е. это выход + movzx esi,word ch_text_length ;загрузить кол-во символов в текстовой строке + ;Умножение на 6 Быстрое умножение можно воспользоваться любым мз методов, но на старых Процессорах (386,486,P1)быстрее будет с инструкцией Lea + ;lea esi,[eax*2+eax] + ;shl eax,1 + imul esi,6 ; или можно и так умножить на 6 + add esi,ch_text_margin ;добавить 3 - расстояние от чек бокса до надписи + + mov eax,37 ;получим координаты мышки + mov ebx,1 ;добавить 1 + int 0x40 ;получить координаты курсора относительно окна + + movzx ebx,word ch_top ;загрузить в bx значение координаты у + cmp ax,bx ;сравнить с с координатой курсора + jl .mouse_end ;SF <> OF если меньше + add ebx,ch_size ;добавить размер + cmp ax,bx ;сравнить + jg .mouse_end ;ZF = 0 и SF = OF если больше + + shr eax,16 ;разделим на 65536 или просто сдвинем биты на 16 значений + movzx ebx,word ch_left ;произведем аналогичное сравнение + cmp ax,bx ;сравнить регистры + jl .mouse_end ;если меньше + add ebx,ch_size ;добавить длину стороны прямоугольника + add ebx,esi ;Учесть в значении по х еще и длину надписи к чекбоксу + cmp ax,bx ;стравнить регистры + jg .mouse_end ;если больше + + bts dword ch_flags,1 ;извлечение значения заданного бита в флаг cf и изменение его значения на 1. + jc @f ;CF=1 то перейти на нижнюю @@ + + call .draw_ch ;отобразить включенный чек бокс + mov dword [esp+24],1 ;дальнейшая проверка чек боксов бесмыслена, по этому в стек, где располагается ecx поместитм 0 + jmp .mouse_end ;выйти +@@: + btr dword ch_flags,1 ;извлечение значения заданного бита в флаг cf и изменение его значения на нулевое. + call .clear_ch ;выключить чек бокс т.е. на месте закрашенного прямоугольника отобразить цвет фона. +.mouse_end: +popa ;восстановить регистры из стека +ret ;выйти +} + +struc check_box left,top,color,border_color,text_color,text,text_length,flags +{ ;структура параметров для чек бокса +.left: dw left ;+0 ;положение по х +.top: dw top ;+2 ;положение по у +.color: dd color ;+4 ;цвет внутри чек бокса +.border_color: dd border_color ;+8 цвет рамки +.text_color: dd text_color ;+12 цвет текста надписи +.text: dd text ;+16 адрес в коде программы где расположен текстр +.text_length: dw text_length ; +20 длина текста +.flags: dd flags+0 ;+22 флаги +} +ch_struc_size=26 ;общая структура 24 байт +macro draw_check_boxes start,end ;рисовать чек боксы +{ + mov edi,start ;Указатель на начало данных чек боксов т.е. на начало данных первого чекбокса + mov ecx,((end-start)/ch_struc_size) ;Количество чек боксов +@@: + call check_box.draw ;Отобразить чек бокс + add edi,ch_struc_size ;Указатель на последующие чек боксы т.е. +28 + loop @b ;прыгнуть если в ecx/cx значение не 0 на верхнюю @@ +} +macro mouse_check_boxes start,end ;установка чек боксов, в зависимости от события +{ + mov edi,start ; Указатель на начало данных чек боксов т.е. на начало данных первого чекбокса + mov ecx,((end-start)/ch_struc_size) ;Количество чек боксов +@@: + call check_box.mouse ;проверка мышки и обработка событий + add edi,ch_struc_size ;Указатель на последующие чек боксы + loop @b ;прыгнуть если в ecx/cx значение не 0 на верхнюю @@ +} \ No newline at end of file diff --git a/programs/develop/examples/checkbox/trunk/checkbox.asm b/programs/develop/examples/checkbox/trunk/checkbox.asm new file mode 100644 index 0000000000..4999671fea --- /dev/null +++ b/programs/develop/examples/checkbox/trunk/checkbox.asm @@ -0,0 +1,108 @@ +;Эффективное программирование в KOLIBRI +;Оптимизированный компонент CheckBox (Исходный вариант от Maxxxx32) +;Оптимизирован вывод строки, надписи для CheckBox'a + теперь при проверке не ;происходит подсчет кол-ва символов в строке +;Оптимизация команд. +;22.08.2006 произведена оптимизация команд, приняты во внимание замечания DIAMOND'а. +; - Теплов Алексей www.test-kolibri.narod.ru + +;заголовок приложения +use32 ; транслятор, использующий 32 разрядных команды + org 0x0 ; базовый адрес кода, всегда 0x0 + db 'MENUET01' ; идентификатор исполняемого файла (8 байт) + dd 0x1 ; версия формата заголовка исполняемого файла + dd start ; адрес, на который система передаёт управление + ; после загрузки приложения в память + dd i_end ; размер приложения + dd (i_end+0x100) and not 3 ; Объем используемой памяти, для стека отведем 0х100 байт и выровним на грницу 4 байта + dd (i_end+0x100) and not 3 ; расположим позицию стека в области памяти, сразу за телом программы. Вершина стека в диапазоне памяти, указанном выше + dd 0x0,0x0 ; указатель на строку с параметрами. + ; если после запуска неравно нулю, приложение было + ; запущено с параметрами из командной строки + + ; указатель на строку, в которую записан путь, + ; откуда запущено приложение + + +;------------------ + include 'check.inc' ;включить файл check.inc + use_check_box ;используя макросы внести процедуры для рисования чек бокса +;Область кода +start: ;Точка входа в программу + mov eax,40 ;установить маску для ожидаемых событий + mov ebx,0x25 ;система будет реагировать только на сообщение о перерисовке,нажата кнопка, определённая ранее, событие от мыши (что-то случилось - нажатие на кнопку мыши или перемещение; сбрасывается при прочтении) + int 0x40 +red_win: + call draw_window ;первоначально необходимо нарисовать окно +still: ;основной обработчик + mov eax,10 ;Ожидать события + int 0x40 ;ожидать событие в течение 2 миллисекунд + + cmp al,0x1 ;если изменилось положение окна + jz red_win + cmp al,0x3 ;если нажата кнопка то перейти + jz button + mouse_check_boxes check_boxes,check_boxes_end ;проверка чек бокса + jmp still ;если ничего из перечисленного то снова в цикл +button: + mov eax,17 ;получить идентификатор нажатой клавиши + int 0x40 + test ah,ah ;если в ah 0, то перейти на обработчик событий still + jz still + or eax,-1 ;в eax,-1 - 5 ,байтов у нас же только 3 выйти + int 0x40 ;далее выполняется выход из программы + +;>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +draw_window: ;рисование окна приложения + mov eax,12 ;в регистр внести значение = 12 + mov ebx,1 ;присвоить 1 + int 0x40 + + xor eax,eax ;обнулить eax + mov ebx,50*65536+180 ;[координата по оси x]*65536 + [размер по оси x] + mov ecx,30*65536+100 ;[координата по оси y]*65536 + [размер по оси y] + mov edx,0x03AABBCC ;0xXYRRGGBB Y =3 - вывод рамки, используя скрин + mov esi,0x805080DD ;0xXYRRGGBB - цвет заголовка + mov edi,0x005080DD ;0x00RRGGBB - цвет рамки + int 0x40 ;нарисовать окно приложения + + add eax,4 ;если предполагается использовать скалярный процессор, то можно использовать данню инструкцию + mov ebx,8*65536+8 ; [координата по оси x]*65536 + [координата по оси y] mov ecx,0x10DDEEFF ; 0xX0RRGGBB, где RR, GG, BB задают цвет текста + mov edx,hed ; указатель на начало строки + mov esi,i_end - hed ; длина строки, должна быть не больше 255 + int 0x40 ;вывести текст + + draw_check_boxes check_boxes,check_boxes_end ;рисование чекбоксов + + add eax,8 ;Функция 12 - начать/закончить перерисовку окна. + mov ebx,2 ;Подфункция 2 - закончить перерисовку окна. + int 0x40 + ret + +;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +;DATA данные +;Формат данных чек бокса: +;10 - координата чек бокса по х +;30 - координата чек бокса по у +;0xffffff - цвет внутри чек бокса +;0 - цвет рамки чек бокса +;0 - цвет текста надписи +;ch_text.1 - указатель на начало строки +;ch_text.e1-ch_text.1 - длина строки +; +check_boxes: +ch1 check_box 10,30,0xffffff,0,0,ch_text.1,ch_text.e1-ch_text.1 +ch2 check_box 10,45,0xffffff,0,0,ch_text.2,ch_text.e2-ch_text.2 +ch3 check_box 10,60,0xffffff,0,0,ch_text.3,ch_text.e3-ch_text.3 +check_boxes_end: + +ch_text: ; Сопровождающий текст для чек боксов +.1 db 'Check_Box #1' +.e1: +.2 db 'Check_Box #2' +.e2: +.3 db 'Check_Box #3' +.e3: + +hed db 'Checkbox [22.08.2006]' ;заголовок приложения +i_end: ;конец кода \ No newline at end of file