;Последная модификация 03.10.2010 ;файл создан 13.02.2009 На код применена GPL2 лицензия ;Макрос для системной библиотеки box_lib.obj ;Checkbox macro use_checkbox_draw { check_box_draw: pushad ;сохраним все регистры mov ebp,dword [esp+36] ;загружаем указатель на структуру, указатель мы передаем в стеке ; mov ebx,ch_left_s ; mov ecx,ch_top_s ; mov edx,dword ch_border_color ; mov eax,13 ; mcall ;рисуем рамку mcall 13,ch_left_s,ch_top_s,ch_border_color ;рисуем рамку чек бокса, фактически рисуем прямоугольник и закрашиваем фон внутри цветом рамки бокса mov edx,dword ch_color ;загружаем цвет фона add ebx,1 shl 16 - 2 add ecx,1 shl 16 - 2 mcall ;закрашиваем внутренности чекбокса фоном test dword ch_flags,2 ;достать значение бита из переменной и поместить в флаг CF jz @f ;в если CF=1, то выполним следующую процедуру иначе перейти на нижнюю @@ call check_box_draw_ch ;нарисовать включенный чек бокс @@: ;---------------------------- ;расчет куда будет произведен вывод текста ;---------------------------- ; mov ebx,dword ch_left_s ;загрузить значение (х shl 16 + длинна) для чек бокса ; add ebx,dword ch_text_margin ;добавим размер стороны и расстояние на котором начнется вывод текста ; shl ebx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) ; add ebx,dword ch_left_s ;cкорректируем позицию Х. Т.е. сейчас в верхней части ebx у нас точка начала вывода текста по Х ; mov eax,word ch_top_s ;загрузим значение по (y shl 16 + длинна) для чек бокса ; shl eax,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) ; add eax,dword ch_top_s ;cкорректируем позицию Х. Т.е. сейчас в верхней части ebx у нас точка начала вывода текста по Y ; Оптимизация для ЦП mov ebx,dword ch_left_s ;загрузить значение (х shl 16 + длинна) для чек бокса mov eax,dword ch_top_s ;загрузим значение по (y shl 16 + длинна) для чек бокса add ebx,dword ch_text_margin ;добавим размер стороны и расстояние на котором начнется вывод текста shl eax,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) shl ebx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) add eax,dword ch_top_s ;cкорректируем позицию Х. Т.е. сейчас в верхней части ebx у нас точка начала вывода текста по Y add ebx,dword ch_left_s ;cкорректируем позицию Х. Т.е. сейчас в верхней части ebx у нас точка начала вывода текста по Х shr eax,16 ;для y поместим в младшую часть mov bx,ax ;внесем смещение для y mov ecx,dword ch_text_color ;загрузим цвет надписи + flags mov edx,dword ch_text_ptr ;укажем адрес от куда нужно выводить строку mov eax,4 ;внесем в eax значение вывода надписи на канву mcall ;Вывод popad ;восстановить значения регистров из стека ret 4 ;выйдем из процедуры и удалим из стека указатель на структуру (4 байта) check_box_clear_ch: ;очистка чек бокса mov edx,dword ch_color ;цвет внутри чек бокса jmp @f ;безусловный прыжок на нижнюю метку @@ check_box_draw_ch: ;нарисовать включенный чек бокс mov edx,dword ch_border_color ;загрузить цвет @@: ; movzx ebx,word ch_left ;загрузить координату по х ; mov eax,dword ch_size ; mov di,ax ; shr eax,2 ; push ax ; ; push ax ; add ebx,eax ; shl ebx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) ; pop ax ; lea eax,[eax*2] ; sub bp,ax ;сохраним регистр bx в регистре указателя базы ; mov bx,bp ; movzx ecx,word ch_top ;загрузить координату по у ; pop ax ; add cx,ax ; shl ecx,16 ;сдвинем на 16 разрядов в лево (умножим на 65536) ; mov cx,bp ;загрузим значения регистра указателя базы в cx ; mov eax,13 ;в eax - значения функции для вывода полосы т.е. по сути прямоугольника, который отображает включенный компонент чек бокс ; mcall ;вывод mov ebx,dword ch_left_s mov ecx,dword ch_top_s add ebx,1 shl 16 - 4 add ecx,1 shl 16 - 4 mcall 13 ret } macro use_checkbox_mouse { ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Обработчик mouse ; При попадании мышки + нажата клавиша в область checkbox состояние бокса должно менятся активный - не активный. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; check_box_mouse: ;обработка мыши pushad mov ebp,dword [esp+36] ;загружаем указатель на структуру, указатель мы передаем в стеке mcall 37,2 ;проверяем состояние клавиш мышки. Было ли событие нажатая клавиша на мышке. test eax,eax ;проверка если у нас в eax=0, то установим флаг и выйдем jnz @f ;перейти на нижнюю метку @@, если в eax не 0. ; and dword ch_flags,eax ;извлечение значения заданного бита в флаг cf и изменение его значения на нулевое. jmp .check_box_mouse_end ;обработка закончилась ; Да событие: нажатие клавиши мышки произошло. @@: mcall 37,1 ;получить координаты курсора относительно окна ;на выходе в eax x shl 16 + y ;сравнение верхней точки по Y mov ecx,dword ch_top_s ;y shl 16 +длинна по y mov ebx,ecx shr ebx,16 ;bx = координата по y cmp ax,bx jb .check_box_mouse_end ;указатель мышки меньше начальной координаты по y чем координата по Y у бокса ;сравнение нижней точки по Y add cx,bx ;сложим длинну по y и координату верхней точки по y поличим координату нижней точки по Y cmp ax,cx ja .check_box_mouse_end ;указатель мышки больше конечной координаты по y чем координата по Y у бокса ;сравнение по начальной точке Х mov ecx,dword ch_left_s ;загрузить значение (х shl 16 + длинна) для чек бокса mov ebx,ecx shr ebx,16 ;bx = координата по X cmp ax,bx jb .check_box_mouse_end ;указатель мышки меньше начальной координаты по X чем координата по X у бокса ;сравнение конечной точки по X add bx,cx ;сложим длинну по y и координату верхней точки по y поличим координату нижней точки по Y add ebx,dword ch_text_margin ;добавим размер стороны и расстояние на котором начнется вывод текста mov ecx,dword ch_text_ptr ;укажем адрес строки с терминируещим 0 push eax ;подсчет длинны строки и увеличение прямогольника в котором срабатывает щелчок мышки lodsb test al,al jz .ex_loop @@: add bx,6 ;ширина символа lodsb test al,al jnz @b .ex_loop: pop eax cmp ax,bx ja .check_box_mouse_end ;указатель мышки больше конечной координаты по y чем координата по Y у бокса ;если все проверки были успешно пройдены мы обязаны поменять состояние бокса btc dword ch_flags,2 ;перенос 2-го бита в cf и инверсия его jc .enable_box ;если CF=1 то отобразим включенный бокс и выйдем push dword .check_box_mouse_end ;фокус -покус, вернемся после вызова check_box_clear_ch на метку check_box_mouse_end jmp check_box_clear_ch ;выключить чек бокс т.е. на месте закрашенного прямоугольника отобразить цвет фона. .enable_box: call check_box_draw_ch ;отобразить включенный чек бокс ; bts dword ch_flags,2 ;проверка флага т.е. перенос в cf значение бита и установка бита в состояние включено ; jc check_box_mouse_end ;если CF=1 то перейти в конец т.е. это выход ; mov esi,dword ch_text_length ;загрузить кол-во символов в текстовой строке ;Умножение на 6 Быстрое умножение можно воспользоваться любым мз методов, но на старых Процессорах (386,486,P1)быстрее будет с инструкцией Lea ; lea esi,[eax*3] ; shl esi,1 ; imul esi,6 ; или можно и так умножить на 6 ; add esi,dword ch_text_margin ;добавить 3 - расстояние от чек бокса до надписи ; mov eax,37 ;получим координаты мышки ; mov ebx,1 ;добавить 1 ; mcall ;получить координаты курсора относительно окна ; movzx ebx,word ch_top ;загрузить в bx значение координаты у ; cmp ax,bx ;сравнить с с координатой курсора ; jl check_box_mouse_end ;SF <> OF если меньше ; add ebx,dword ch_size ;добавить размер ; cmp ax,bx ;сравнить ; jg check_box_mouse_end ;ZF = 0 и SF = OF если больше ; shr eax,16 ;разделим на 65536 или просто сдвинем биты на 16 значений ; movzx ebx,word ch_left ;произведем аналогичное сравнение ; cmp ax,bx ;сравнить регистры ; jl check_box_mouse_end ;если меньше ; add ebx,dword ch_size ;добавить длину стороны прямоугольника ; add ebx,esi ;Учесть в значении по х еще и длину надписи к чекбоксу ; cmp ax,bx ;стравнить регистры ; jg check_box_mouse_end ;если больше ; bts dword ch_flags,1 ;извлечение значения заданного бита в флаг cf и изменение его значения на 1. ; jc @f ;CF=1 то перейти на нижнюю @@ ; call check_box_draw_ch ;отобразить включенный чек бокс ; mov dword [esp+24],1 ;дальнейшая проверка чек боксов бесмыслена, по этому в стек, где располагается ecx поместитм 0 ; jmp check_box_mouse_end ;выйти ;@@: ; btr word ch_flags,1 ;извлечение значения заданного бита в флаг cf и изменение его значения на нулевое. ; call check_box_clear_ch ;выключить чек бокс т.е. на месте закрашенного прямоугольника отобразить цвет фона. .check_box_mouse_end: popad ;восстановить регистры из стека ret 4 ;выйти }