-
Notifications
You must be signed in to change notification settings - Fork 1
/
button.asm
639 lines (569 loc) · 16.9 KB
/
button.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
.386
.model flat, stdcall
option casemap:none
include button.inc
include windows.inc
include gdi32.inc
include util.inc
include paint.inc
.data
nButtonListCnt DWORD 0
bIfInitButtonData DWORD 0
szDefaultButtonText BYTE "button",0
szDefaultButtonClick BYTE "Button Clicked: %d", 0dh, 0ah, 0
szDefaultButtonHover BYTE "Button Hovered: %d", 0dh, 0ah, 0
szDefaultButtonUpdate BYTE "Button Update : %d", 0dh, 0ah, 0
.data?
arrayButtonList BUTTONDATA MAXBTNCNT DUP(<?>) ; 存储BUTTONDATA内存池
arrayPaintOrder DWORD MAXBTNCNT DUP(?) ; 用于排序临时存储
.code
; 初始化
InitButtonData PROC uses ebx ecx edi
lea edi, arrayButtonList
mov ebx, MAXBTNCNT
mov ecx, 0
.WHILE ecx < ebx
assume edi: ptr BUTTONDATA
mov eax, BTNS_UNUSED
mov [edi].status, ax
mov eax, sizeof BUTTONDATA
add edi, eax
inc ecx
.ENDW
xor eax, eax
ret
InitButtonData ENDP
; 获取一个可以存贮数据的空位
GetAvilaibleButtonData PROC uses ebx ecx edx edi
.IF ! bIfInitButtonData
invoke InitButtonData
mov eax, 1
mov bIfInitButtonData, eax
.ENDIF
lea edi, arrayButtonList
mov ebx, nButtonListCnt
mov ecx, 0
.WHILE ecx < ebx
assume edi: ptr BUTTONDATA
.IF [edi].status == BTNS_UNUSED
.break
.ENDIF
add edi, sizeof BUTTONDATA
inc ecx
.ENDW
.IF ecx == ebx
inc ebx
mov nButtonListCnt, ebx
.ENDIF
mov eax, edi
ret
GetAvilaibleButtonData ENDP
; 注册BUTTON。相当于创建BUTTON,会自动寻找内存位置存储数据,并被PaintAllButton管理
RegisterButton PROC uses ebx edi esi pRect: ptr RECT, pPaint:DWORD, pClickEvent:DWORD, pHoverEvent:DWORD, pUpdateEvent:DWORD
invoke GetAvilaibleButtonData
mov esi, eax
mov edi, pRect
assume edi: ptr RECT
assume esi: ptr BUTTONDATA
mov eax, 0
mov [esi].depth, eax
mov eax, [edi].left
mov [esi].left, eax
mov eax, [edi].right
mov [esi].right, eax
mov eax, [edi].top
mov [esi].top, eax
mov eax, [edi].bottom
mov [esi].bottom, eax
mov eax, pPaint
mov [esi].pPaint, eax
mov eax, pClickEvent
mov [esi].pClickEvent, eax
mov eax, pHoverEvent
mov [esi].pHoverEvent, eax
mov eax, pUpdateEvent
mov [esi].pUpdateEvent, eax
mov [esi].status, BTNS_WAIT
mov [esi].isActive, BTNI_RUNNING
.IF [esi].pPaint == NULL
mov eax, ButtonDefaultPaint
mov [esi].pPaint, eax
.ENDIF
.IF [esi].pClickEvent == NULL
mov eax, ButtonDefaultClick
mov [esi].pClickEvent, eax
.ENDIF
.IF [esi].pHoverEvent == NULL
mov eax, ButtonDefaultHover
mov [esi].pHoverEvent, eax
.ENDIF
.IF [esi].pUpdateEvent == NULL
mov eax, ButtonDefaultUpdate
mov [esi].pUpdateEvent, eax
.ENDIF
mov eax, esi
ret
RegisterButton ENDP
GetButtonCenteri PROC uses ebx esi edi pButton: ptr BUTTONDATA
mov edi, pButton
assume edi: PTR BUTTONDATA
mov eax, [edi].left
add eax, [edi].right
shr eax, 1
mov edx, [edi].top
add edx, [edi].bottom
shr edx, 1
ret
GetButtonCenteri ENDP
; 绘制单个按钮
PaintButton PROC uses ebx hDc:DWORD, pButton: ptr BUTTONDATA
mov eax, pButton
assume eax: ptr BUTTONDATA
mov bx, [eax].isActive
and bx, BTNI_DISABLE_PAINT
.IF bx
ret
.ENDIF
push pButton
push hDc
mov eax, [eax].pPaint
call eax
xor eax, eax
ret
PaintButton ENDP
; 绘制所有注册过的按钮
PaintAllButton PROC uses ebx ecx edi hDc:DWORD
mov ecx, nButtonListCnt
lea ebx, arrayPaintOrder
mov eax, nButtonListCnt
dec eax
shl eax, 2
add ebx, eax
mov edi, [ebx]
assume edi: ptr BUTTONDATA
@@: push ecx
.IF [edi].status != BTNS_UNUSED
invoke PaintButton, hDc, edi
.ENDIF
pop ecx
sub ebx, sizeof DWORD
mov edi, [ebx]
loop @b
xor eax, eax
ret
PaintAllButton ENDP
ButtonDefaultPaint PROC uses ebx edi esi hDc: DWORD, pButton: ptr BUTTONDATA
local @oldPen, @oldBrush, @stRect:RECT
mov edi, pButton
assume edi: ptr BUTTONDATA
invoke GetStockObject, BLACK_PEN
invoke SelectObject, hDc, eax
mov @oldPen, eax
invoke GetStockObject, GRAY_BRUSH
mov bx, [edi].status
and bx, BTNS_HOVER
.IF bx
invoke GetStockObject, LTGRAY_BRUSH
.ENDIF
mov bx, [edi].status
and bx, BTNS_CLICK
.IF bx
invoke GetStockObject, DKGRAY_BRUSH
.ENDIF
invoke SelectObject, hDc, eax
mov @oldBrush, eax
invoke GetButtonRect, pButton, addr @stRect
invoke PaintRect, hDc, addr @stRect
invoke TextOut, hDc, addr szDefaultButtonText, -1, pButton, \
DT_SINGLELINE or DT_CENTER or DT_VCENTER
invoke SelectObject, hDc, @oldPen
invoke SelectObject, hDc, @oldBrush
xor eax, eax
ret
ButtonDefaultPaint ENDP
ButtonBitmapPaint PROC uses ebx edi esi hdc:DWORD, pButton: ptr BUTTONDATA
local @oldPen, @oldBrush, @stRect:RECT
;ocal @colorAdjustment:COLORADJUSTMENT, @oldColorAdjustment:COLORADJUSTMENT
mov edi, pButton
assume edi: ptr BUTTONDATA
invoke GetButtonRect, pButton, addr @stRect
push eax
mov eax, @stRect.top
sub eax, @stRect.bottom
.IF eax <= 1
pop eax
ret
.ENDIF
pop eax
;invoke GetColorAdjustment, hdc, addr @colorAdjustment
;invoke memcpy, addr @oldColorAdjustment, addr @colorAdjustment, sizeof COLORADJUSTMENT
;lea esi, @colorAdjustment
;assume esi: ptr COLORADJUSTMENT
;invoke SetColorAdjustment, hdc, addr @colorAdjustment
invoke PaintBitmapTransEx, hdc, [edi].aParam, addr @stRect, STRETCH_XY
;invoke SetColorAdjustment, hdc, addr @oldColorAdjustment
push edi
mov bx, [edi].status
and bx, BTNS_CLICK
.IF bx
;mov ax, -50
;mov [esi].caBrightness, ax
invoke SetPen, hdc, PS_SOLID, 2, 00111111h
mov @oldPen, eax
invoke GetStockObject, NULL_BRUSH
invoke SelectObject, hdc, eax
mov @oldBrush, eax
invoke PaintRoundRect, hdc, addr @stRect, 10
invoke SelectObject, hdc, @oldBrush
invoke SelectObject, hdc, @oldPen
invoke DeleteObject, eax
.ELSE
mov bx, [edi].status
and bx, BTNS_HOVER
.IF bx
;mov ax, 50
;mov [esi].caBrightness, ax
invoke SetPen, hdc, PS_SOLID, 2, 00ffffffh
mov @oldPen, eax
invoke GetStockObject, NULL_BRUSH
invoke SelectObject, hdc, eax
mov @oldBrush, eax
invoke PaintRoundRect, hdc, addr @stRect, 10
invoke SelectObject, hdc, @oldBrush
invoke SelectObject, hdc, @oldPen
invoke DeleteObject, eax
.ENDIF
.ENDIF
pop edi
xor eax, eax
ret
ButtonBitmapPaint ENDP
ButtonDefaultClick PROC uses ebx edi esi pButton: ptr BUTTONDATA
; invoke printf, offset szDefaultButtonClick, pButton
ret
ButtonDefaultClick ENDP
ButtonDefaultHover PROC uses ebx edi esi pButton: ptr BUTTONDATA
; invoke printf, offset szDefaultButtonHover, pButton
ret
ButtonDefaultHover ENDP
ButtonDefaultUpdate PROC uses ebx edi esi cnt:DWORD, pButton: ptr BUTTONDATA
;invoke printf, offset szDefaultButtonUpdate, cnt
ret
ButtonDefaultUpdate ENDP
GetButtonDefuatPainter proc
mov eax, ButtonDefaultPaint
ret
GetButtonDefuatPainter ENDP
GetButtonRect proc uses ebx ecx pButton: ptr BUTTONDATA, pRect: ptr RECT
mov ecx, pButton
assume ecx: ptr BUTTONDATA
mov ebx, pRect
assume ebx: ptr RECT
mov eax, [ecx].left
mov [ebx].left, eax
mov eax, [ecx].right
mov [ebx].right, eax
mov eax, [ecx].top
mov [ebx].top, eax
mov eax, [ecx].bottom
mov [ebx].bottom, eax
xor eax, eax
assume ebx: DWORD
ret
GetButtonRect ENDP
DeleteButton proc uses esi pButton:ptr BUTTONDATA
mov esi, pButton
assume esi: ptr BUTTONDATA
mov [esi].status, BTNS_UNUSED
mov [esi].isActive, 00ffh
xor eax, eax
ret
DeleteButton ENDP
MoveButton proc uses edx eax pButton: ptr BUTTONDATA, x:DWORD, y:DWORD
mov edx, pButton
assume edx: ptr BUTTONDATA
mov eax, [edx].left
add eax, x
mov [edx].left, eax
mov eax, [edx].right
add eax, x
mov [edx].right, eax
mov eax, [edx].top
add eax, y
mov [edx].top, eax
mov eax, [edx].bottom
add eax, y
mov [edx].bottom, eax
ret
MoveButton endp
SetButtonSize PROC uses ebx edi esi pButton:ptr BUTTONDATA, w:DWORD, h:DWORD
mov edi, pButton
assume edi: ptr BUTTONDATA
mov eax, [edi].left
add eax, w
mov [edi].right, eax ;fixed bug
mov eax, [edi].top
add eax, h
mov [edi].bottom, eax
mov eax, pButton
ret
SetButtonSize endp
GetButtonSize PROC uses ebx edi esi pButton: ptr BUTTONDATA, pPoint: ptr D_POINT
mov edi, pButton
assume edi: ptr BUTTONDATA
mov esi, pPoint
assume esi: ptr D_POINT
mov ebx, [edi].right
sub ebx, [edi].left
mov [esi].x, ebx
mov ebx, [edi].bottom
sub ebx, [edi].top
mov [esi].y, ebx
ret
GetButtonSize ENDP
MoveButtonTo proc uses edx eax pButton: ptr BUTTONDATA, x:DWORD, y:DWORD
mov edx, pButton
assume edx: ptr BUTTONDATA
mov eax, x
sub eax, [edx].left
mov x, eax
mov eax, y
sub eax, [edx].top
mov y, eax
invoke MoveButton, pButton, x, y
ret
MoveButtonTo endp
MoveButtonCenterTo PROC uses edx eax pButton: ptr BUTTONDATA, x:DWORD, y:DWORD
local @wh:D_POINT
mov edx, pButton
assume edx: ptr BUTTONDATA
invoke GetButtonSize, pButton, addr @wh
mov eax, @wh.x
shr eax, 1
sub eax, x
neg eax
mov @wh.x, eax
mov eax, @wh.y
shr eax, 1
sub eax, y
neg eax
mov @wh.y, eax
invoke MoveButtonTo, pButton, @wh.x, @wh.y
ret
MoveButtonCenterTo ENDP
InButtonRange proc uses ebx edi pButton:ptr BUTTONDATA, x:DWORD, y:DWORD
xor eax, eax
mov ebx, x
mov edi, pButton
assume edi:ptr BUTTONDATA
.IF (ebx > [edi].left) && (ebx <= [edi].right)
add eax,1
.ENDIF
mov ebx, y
.IF (ebx > [edi].top) && (ebx <= [edi].bottom)
add eax,2
.ENDIF
push eax
pop eax
.IF (eax == 3)
shr eax, 1
.ELSE
xor eax, eax
.ENDIF
ret
InButtonRange ENDP
SendClickInfo proc uses ebx edi esi x:DWORD, y:DWORD
local @cnt
mov ecx, nButtonListCnt
lea ebx, arrayPaintOrder
mov edi, [ebx]
assume edi: ptr BUTTONDATA
mov eax, 0
mov @cnt, eax
@@: push ecx
push ebx
invoke InButtonRange, edi, x, y
mov dx, [edi].isActive
and dx, BTNI_DISABLE_CLICK
.IF !dx
mov ebx, @cnt
.IF eax && !ebx
push edi
call [edi].pClickEvent
mov dx, [edi].status
or dx, BTNS_CLICK
mov [edi].status, dx
mov eax, @cnt
inc eax
mov @cnt, eax
.ELSE
mov dx, BTNS_HOVER
not dx
and dx, [edi].status
mov [edi].status, dx
.ENDIF
.ENDIF
pop ebx
pop ecx
add ebx, sizeof DWORD
mov edi, [ebx]
loop @b
mov eax, @cnt
ret
SendClickInfo ENDP
SendHoverInfo proc uses ebx edi x:DWORD, y:DWORD
local @cnt
mov ecx, nButtonListCnt
lea ebx, arrayPaintOrder
mov edi, [ebx]
assume edi: ptr BUTTONDATA
mov eax, 0
mov @cnt, eax
@@: push ecx
push ebx
invoke InButtonRange, edi, x, y
mov dx, [edi].isActive
and dx, BTNI_DISABLE_HOVER
.IF !dx
mov ebx, @cnt
.IF eax && !ebx
push edi
call [edi].pHoverEvent
mov dx, [edi].status
or dx, BTNS_HOVER
mov [edi].status, dx
mov eax, @cnt
inc eax
mov @cnt, eax
.ELSE
mov dx, BTNS_HOVER
not dx
and dx, [edi].status
mov [edi].status, dx
.ENDIF
.ENDIF
pop ebx
pop ecx
add ebx, sizeof DWORD
mov edi, [ebx]
loop @b
mov eax, @cnt
ret
SendHoverInfo ENDP
SendUpdateInfo proc uses ebx edi cnt:DWORD
local @cnt
xor ecx, ecx
mov ebx, nButtonListCnt
mov edi, offset arrayButtonList
assume edi: ptr BUTTONDATA
xor eax, eax
mov @cnt, eax
.WHILE ecx < ebx
push ecx
push ebx
mov dx, [edi].isActive
and dx, BTNI_DISABLE_UPDATE
.IF !dx
push edi
push cnt
call [edi].pUpdateEvent
.ENDIF
pop ebx
pop ecx
add edi, sizeof BUTTONDATA
inc ecx
.ENDW
mov eax, @cnt
ret
SendUpdateInfo ENDP
ClearClick proc uses ebx edi
xor ecx, ecx
mov ebx, nButtonListCnt
mov edi, offset arrayButtonList
assume edi: ptr BUTTONDATA
.WHILE ecx < ebx
mov dx, BTNS_CLICK
not dx
and dx, [edi].status
mov [edi].status, dx
add edi, sizeof BUTTONDATA
inc ecx
.ENDW
mov eax, 0
ret
ClearClick ENDP
CompareByDepth PROC C uses ebx esi edi pbuttonAptr: DWORD, pbuttonBptr: DWORD
mov esi, pbuttonAptr
mov esi, DWORD ptr [esi]
mov edi, pbuttonBptr
mov edi, DWORD ptr [edi]
assume esi: PTR BUTTONDATA
assume edi: PTR BUTTONDATA
mov eax, [esi].depth
mov ebx, [edi].depth
assume eax: SDWORD
assume ebx: SDWORD
.IF eax < ebx
mov eax, -1
.ELSEIF eax > ebx
mov eax, 1
.ELSE
mov eax, [esi].bottom
mov ebx, [edi].bottom
.IF eax > ebx
mov eax, -1
.ELSEIF eax < ebx
mov eax, 1
.ELSE
.IF esi > edi
mov eax, -1
.ELSEIF esi < edi
mov eax, 1
.ELSE
mov eax, 0
.ENDIF
.ENDIF
.ENDIF
ret
CompareByDepth ENDP
SetButtonDepth PROC uses edi pButton: ptr BUTTONDATA, depth:DWORD
mov edi, pButton
assume edi: ptr BUTTONDATA
mov eax, depth
mov [edi].depth, eax
mov eax, pButton
ret
SetButtonDepth ENDP
GetButtonDepth PROC pButton: ptr BUTTONDATA
mov edi, pButton
assume edi: ptr BUTTONDATA
mov eax, [edi].depth
ret
GetButtonDepth ENDP
SortButtons PROC uses ebx esi edi
lea edi, arrayButtonList
mov ecx, nButtonListCnt
mov esi, edi
lea ebx, arrayPaintOrder
@@: mov [ebx], esi
add esi, sizeof BUTTONDATA
add ebx, sizeof DWORD
loop @B
mov ecx, nButtonListCnt
invoke qsort, offset arrayPaintOrder , ecx, sizeof DWORD, CompareByDepth
ret
SortButtons ENDP
BindButtonToBitmap PROC uses ebx esi edi pButton:ptr BUTTONDATA, BitmapID:DWORD
local @point:D_POINT
invoke GetBitmapSize,BitmapID, addr @point
mov edi, pButton
assume edi:ptr BUTTONDATA
invoke SetButtonSize, edi, @point.x, @point.y
mov eax, BitmapID
mov [edi].aParam, eax
mov eax, ButtonBitmapPaint
mov [edi].pPaint, eax
mov eax, pButton
ret
BindButtonToBitmap ENDP
end