204 lines
10 KiB
FASM
204 lines
10 KiB
FASM
;Оптимизированный компонент CheckBox (Исходный вариант от Maxxxx32)
|
||
;Оптимизирован вывод строки надписи для CheckBox'a + теперь, при проверке не происходит подсчет кол-ва символов в строке
|
||
;Оптимизация команд - отказался от сохранения регистров в стеке.
|
||
;21.02.2007 добавил код от Heavyiron, дописал макросы для использования системных цветов
|
||
;19.02.2007 общее улучшение кода, уменьшение размера и использование системных цветов для отображения checkbox
|
||
;17.07.2006 произведена оптимизация, при установке чек бокса в положение включено последующие чек боксы в тот же промежуток времени не проверяются
|
||
;22.08.2006 произведена оптимизация команд, приняты во внимание замечания DIAMOND'а.
|
||
;<Lrz> - Теплов Алексей www.lrz.land.ru
|
||
|
||
macro version_ch ;для совместимости со старыми версиями checkbox все цвета задаются ручками
|
||
{
|
||
ch_struc_size=24
|
||
ch_left equ [edi] ;координата начала рисования по х
|
||
ch_top equ [edi+2] ;координата начала рисования по у
|
||
ch_color equ [edi+4]
|
||
ch_border_color equ [edi+8] ; or [edi+4] ;цвет рамки checkbox ее можно задать самостоятельно
|
||
ch_text_color equ [edi+12];[edi+4] ;цвет текста
|
||
ch_text_ptr equ [edi+16] ;указатель на начало текстовой строки
|
||
ch_text_length equ [edi+20] ;длина надписи (2^64 такой длины может быть текст)
|
||
ch_flags equ [edi+22] ;флаги
|
||
}
|
||
|
||
macro version_ch1 ;продвинутая версия, использует цвета скина.
|
||
{
|
||
ch_struc_size=12
|
||
ch_left equ [edi] ;координата начала рисования по х
|
||
ch_top equ [edi+2] ;координата начала рисования по у
|
||
ch_color equ [sc.work] ;
|
||
ch_border_color equ [sc.work_graph] ; or [edi+4] ;цвет рамки checkbox ее можно задать самостоятельно
|
||
ch_text_color equ [sc.work_text];[edi+4] ;цвет текста
|
||
ch_text_ptr equ [edi+4] ;указатель на начало текстовой строки
|
||
ch_text_length equ [edi+8] ;длина надписи (2^64 такой длины может быть текст)
|
||
ch_flags equ [edi+10] ;флаги
|
||
}
|
||
|
||
macro use_check_box
|
||
{
|
||
ch_text_margin=4 ;расстояние от прямоугольника чек бокса до надписи
|
||
ch_size=11 ;размер квадрата чек бокса
|
||
check_box:
|
||
.draw:
|
||
pusha ;сохраним все регистры
|
||
mov eax,13
|
||
mov ebx,ch_left
|
||
shl ebx,16
|
||
add ebx,ch_size
|
||
mov ecx,ch_top
|
||
shl ecx,16
|
||
add ecx,ch_size
|
||
mov edx,ch_border_color
|
||
int 0x40 ;рисуем рамку
|
||
|
||
mov edx,ch_color
|
||
add ebx,1 shl 16 - 2
|
||
add ecx,1 shl 16 - 2
|
||
int 0x40 ;закрашиваем внутренности чекбокса
|
||
|
||
test word 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+1) ;добавим значение длины стороны -9+1
|
||
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 word ch_flags,2 ;извлечение значения заданного бита в флаг cf и изменение его значения на нулевое.
|
||
popa ;если ничего не произошло, то восстановим значения регистров из стека
|
||
ret ;выход
|
||
@@:
|
||
bts word 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 word ch_flags,1 ;извлечение значения заданного бита в флаг cf и изменение его значения на 1.
|
||
jc @f ;CF=1 то перейти на нижнюю @@
|
||
|
||
call .draw_ch ;отобразить включенный чек бокс
|
||
mov dword [esp+24],1 ;дальнейшая проверка чек боксов бесмыслена, по этому в стек, где располагается ecx поместитм 0
|
||
jmp .mouse_end ;выйти
|
||
@@:
|
||
btr word ch_flags,1 ;извлечение значения заданного бита в флаг cf и изменение его значения на нулевое.
|
||
call .clear_ch ;выключить чек бокс т.е. на месте закрашенного прямоугольника отобразить цвет фона.
|
||
.mouse_end:
|
||
popa ;восстановить регистры из стека
|
||
ret ;выйти
|
||
}
|
||
|
||
struc check_box1 left,top,text,text_length,flags
|
||
{ ;структура параметров для чек бокса
|
||
.left: dw left ;+0 положение по х
|
||
.top: dw top ;+2 положение по у
|
||
.text: dd text ;+16 адрес в коде программы где расположен текстр
|
||
.text_length: dw text_length ;+20 длина текста
|
||
.flags: dw flags+0 ;+22 флаги
|
||
}
|
||
struc check_box left,top,color,border_color,text_color,text,text_length,flags
|
||
{ ;структура параметров для чек бокса
|
||
.left: dw left ;+0 ;положение по х
|
||
.top: dw top ;положение по у
|
||
.color: dd color ;цвет внутри чекбокса
|
||
.border_color: dd border_color ;цвет рамки
|
||
.text_color: dd text_color ;цвет надписи
|
||
.text: dd text ;адрес в коде программы где расположен текст
|
||
.text_length: dw text_length ;длина текста
|
||
.flags: dw flags+0 ;+22
|
||
}
|
||
ch_flag_en=10b
|
||
|
||
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 на верхнюю @@
|
||
}
|
||
;Если нужно отобразить один чекер
|
||
macro draw_check_box start ;рисовать чек боксы
|
||
{
|
||
mov edi,start ;Указатель на начало данных чек боксов т.е. на начало данных первого чекбокса
|
||
call check_box.draw ;Отобразить чек бокс
|
||
}
|
||
macro mouse_check_box start ;установка чек боксов, в зависимости от события
|
||
{
|
||
mov edi,start ; Указатель на начало данных чек боксов т.е. на начало данных первого чекбокса
|
||
call check_box.mouse ;проверка мышки и обработка событий
|
||
} |