Subversion Repositories Kolibri OS

Rev

Rev 360 | Go to most recent revision | Details | Last modification | View Log | RSS feed

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