Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
205 heavyiron 1
;Эффективное программирование в KOLIBRI
2
;Оптимизированный компонент CheckBox (Исходный вариант от Maxxxx32)
3
;Оптимизирован вывод строки надписи для CheckBox'a + теперь, при проверке не происходит подсчет кол-ва символов в строке
4
;Оптимизация команд - отказался от сохранения регистров в стеке.
5
;17.07.2006 произведена оптимизация, при установке чек бокса в положение включено последующие чек боксы в тот же промежуток времени не проверяются
6
;  - Теплов Алексей  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
}