-
Notifications
You must be signed in to change notification settings - Fork 3
/
Docking.asm
1127 lines (1029 loc) · 31.4 KB
/
Docking.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
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
XEDGE EQU 2
YEDGE EQU 2
;Constants for fState
CLOSEBUTTONPRESSED EQU 1
USERSIZING EQU 2
USERDOCKINGUNDOCKING EQU 3
BrushColor EQU 0C0C0C0H
.DATA
szDockClass DB "DockWindow",0
.DATA?
hActiveDock DWORD ?
PEDockData DOCKDATA <> ;Project Explorer
POutDockData DOCKDATA <> ;Out Parent
TBDockData DOCKDATA <>
RCOptionsDockData DOCKDATA <>
hDragCursor DWORD ?
.CODE
EnableAllDockWindows Proc Uses ESI fEnable:DWORD
.If pDWBlock
XOR ECX,ECX
MOV EAX,pDWBlock
@@:
PUSH EAX
PUSH ECX
MOV ESI,[EAX+ECX]
Invoke EnableWindow,ESI,fEnable
Invoke GetParent,ESI
.If EAX!=WinAsmHandles.hMain
Invoke EnableWindow,EAX,fEnable
.EndIf
POP ECX
POP EAX
ADD ECX,4
.If ECX<DWBlockSize
JMP @B
.EndIf
.EndIf
RET
EnableAllDockWindows EndP
InvalidateAllDockWindows Proc; fEnable:DWORD
.If pDWBlock
XOR ECX,ECX
MOV EAX,pDWBlock
@@:
PUSH EAX
PUSH ECX
MOV ESI,[EAX+ECX]
Invoke InvalidateRect,ESI,NULL,FALSE
Invoke GetParent,ESI
.If EAX!=WinAsmHandles.hMain
Invoke InvalidateRect,EAX,NULL,FALSE
Invoke UpdateWindow,EAX
.EndIf
POP ECX
POP EAX
ADD ECX,4
.If ECX<DWBlockSize
JMP @B
.EndIf
.EndIf
RET
InvalidateAllDockWindows EndP
MoveFloatingWindow Proc Uses EBX lpWindowData:DWORD, hParent:HWND
MOV EBX, lpWindowData
;Look here! I am always moving the parent
Invoke MoveWindow,hParent,[EBX].DOCKDATA.FocusRect.left,[EBX].DOCKDATA.FocusRect.top,[EBX].DOCKDATA.NoDock.dWidth,[EBX].DOCKDATA.NoDock.dHeight,TRUE
Invoke UpdateWindow,hParent
RET
MoveFloatingWindow EndP
DockWndProc Proc Uses EBX hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
Local Rect :RECT
Local ps :PAINTSTRUCT
Local hDC :HDC
Local Point :POINT
;Local lf :LOGFONT
.If uMsg==WM_SHOWWINDOW
Invoke GetParent,hWnd
.If EAX !=WinAsmHandles.hMain
.If wParam
Invoke ShowWindow,EAX,SW_SHOW
Invoke UpdateWindow,hWnd
.Else
Invoke ShowWindow,EAX,SW_HIDE
.EndIf
.EndIf
;.ElseIf uMsg==WM_SETFOCUS
; Invoke SetFocus,WinAsmHandles.hMain
.ElseIf uMsg == WM_NOTIFY
MOV EAX,lParam
.If [EAX].NMHDR.code==TTN_NEEDTEXT
Invoke SetWindowPos,[EAX].NMHDR.hwndFrom,HWND_TOP,0,0,0,0,SWP_NOACTIVATE OR SWP_NOMOVE or SWP_NOSIZE or SWP_NOOWNERZORDER
.EndIf
.ElseIf uMsg==WM_WINDOWPOSCHANGED ;I need to check this AFTER the window is shown or hidden
Invoke GetParent,hWnd
.If EAX==WinAsmHandles.hMain
MOV EBX,lParam
MOV EDX,[EBX].WINDOWPOS.flags
AND EDX,SWP_SHOWWINDOW or SWP_HIDEWINDOW
.If EDX==SWP_HIDEWINDOW || EDX==SWP_SHOWWINDOW
Invoke ClientResize
;Invoke UpdateWindow,hWnd
.EndIf
.EndIf
.ElseIf uMsg==WM_PAINT
Invoke GetWindowLong,hWnd,GWL_STYLE
AND EAX,WS_POPUP
.If !EAX
Invoke BeginPaint,hWnd,ADDR ps
;Invoke GetDC,hWnd
MOV hDC,EAX
Invoke GetClientRect,hWnd,Addr Rect
MOV Rect.left,XEDGE
SUB Rect.right,XEDGE
MOV EAX,YEDGE
MOV Rect.top,EAX
ADD EAX,12 ;I want the caption's height to be 12 pixels
MOV Rect.bottom,EAX
Invoke GetWindowLong,hWnd,GWL_STYLE
AND EAX,0FFFFh
.If EAX==STYLE_GRADIENTTITLE
Invoke GetForegroundWindow
PUSH EAX
Invoke GetParent,EAX
POP ECX
.If EAX==WinAsmHandles.hMain || ECX==WinAsmHandles.hMain
Invoke DrawCaption,hWnd,hDC,ADDR Rect, DC_GRADIENT OR DC_TEXT or DC_ACTIVE
.Else
Invoke DrawCaption,hWnd,hDC,ADDR Rect,DC_GRADIENT OR DC_TEXT
.EndIf
.ElseIf EAX==STYLE_TWOLINESTITLE
PUSH Rect.bottom
PUSH Rect.right
SUB Rect.right,16;3 ;i.e The x button will be 10 pixels wide
PUSH Rect.top
ADD Rect.top,3
MOV EAX,Rect.top
ADD EAX,2
MOV Rect.bottom,EAX
Invoke DrawEdge,hDC,ADDR Rect,BDR_RAISEDINNER,BF_RECT
ADD Rect.top,4
MOV EAX,Rect.top
ADD EAX,2
MOV Rect.bottom,EAX
Invoke DrawEdge,hDC,ADDR Rect,BDR_RAISEDINNER,BF_RECT
POP Rect.top
POP Rect.right
POP Rect.bottom
.Else ;STYLE_ONELINETITLE
PUSH Rect.bottom
PUSH Rect.right
SUB Rect.right,16;3 ;i.e The x button will be 10 pixels wide
PUSH Rect.top
ADD Rect.top,5
MOV EAX,Rect.top
ADD EAX,2
MOV Rect.bottom,EAX
Invoke DrawEdge,hDC,ADDR Rect,BDR_RAISEDINNER,BF_RECT
POP Rect.top
POP Rect.right
POP Rect.bottom
.EndIf
INC Rect.top
DEC Rect.bottom
DEC Rect.right ;i.e Just to be one pixel left from the caption
MOV EAX,Rect.right
SUB EAX,10
MOV Rect.left,EAX ;i.e The x button will be 10 pixels wide
;Draw Close Button
Invoke GetWindowLong,hWnd,0
.If DOCKDATA.fState[EAX]==CLOSEBUTTONPRESSED
Invoke DrawFrameControl, hDC, ADDR Rect, DFC_CAPTION, DFCS_CAPTIONCLOSE or DFCS_PUSHED; or DFCS_FLAT
.Else
Invoke DrawFrameControl, hDC, ADDR Rect, DFC_CAPTION, DFCS_CAPTIONCLOSE; or DFCS_FLAT
.EndIf
;Invoke ReleaseDC,hWnd,hDC
Invoke EndPaint,hWnd,ADDR ps
.EndIf
.ElseIf uMsg == WM_COMMAND
HIWORD wParam
.If EAX == 0; || 1 ; 0 is a menu, 1 is an accelerator. Toolbar messages act like menu messages...
Invoke GetWindowLong,hWnd,GWL_STYLE
MOV EBX,EAX
AND EBX,0FFFF0000h
LOWORD wParam
.If EAX>=IDM_STYLE_GRADIENTTITLE && EAX<=IDM_STYLE_ONELINETITLE ;Because if menu or toolbar is placed on the docking windows-->the style will be changed unnecessarily!!!
.If EAX == IDM_STYLE_GRADIENTTITLE
OR EBX,STYLE_GRADIENTTITLE
.ElseIf EAX==IDM_STYLE_TWOLINESTITLE
OR EBX,STYLE_TWOLINESTITLE
.ElseIf EAX==IDM_STYLE_ONELINETITLE
OR EBX,STYLE_ONELINETITLE
.EndIf
Invoke SetWindowLong,hWnd,GWL_STYLE,EBX
Invoke InvalidateRect,hWnd,NULL,TRUE
.EndIf
.EndIf
.ElseIf uMsg==WM_CONTEXTMENU
Invoke GetCapture
MOV EBX,EAX
Invoke GetParent,EAX
.If EBX!=hWnd && EAX!=hWnd;in case while user moving the focus rectangle presses the right button ---> do not show context menu.
.If lParam==0FFFFFFFFh
Invoke GetWindowRect,hWnd,ADDR Rect
MOV EAX,Rect.left
MOV Point.x,EAX
MOV EAX,Rect.top
MOV Point.y,EAX
JMP ShowIt
.Else
MOV EAX,lParam
AND EAX,0FFFFh
MOV Point.x,EAX
MOV EAX,lParam
SHR EAX,16
MOV Point.y,EAX
.EndIf
Invoke ScreenToClient,hWnd,ADDR Point
Invoke SendMessage,hWnd,WAM_GETCLIENTRECT,0,ADDR Rect
Invoke PtInRect,ADDR Rect,Point.x,Point.y
.If !EAX ;i.e. not in "client" area
Invoke ClientToScreen,hWnd,ADDR Point
ShowIt:
PUSH EDI
Invoke GetWindowLong,hWnd,GWL_STYLE
AND EAX,0FFFFh
.If EAX==STYLE_GRADIENTTITLE
MOV EDI,0
.ElseIf EAX==STYLE_TWOLINESTITLE
MOV EDI,1
.Else;If EAX==STYLE_ONELINETITLE
MOV EDI,2
.EndIf
Invoke CreatePopupMenu
MOV EBX,EAX
MOV ECX,MF_STRING
.If !EDI
OR ECX,MF_CHECKED
.EndIf
Invoke AppendMenu,EBX,ECX,IDM_STYLE_GRADIENTTITLE,Offset szGradient ;"Gradient"
MOV ECX,MF_STRING
.If EDI==1
OR ECX,MF_CHECKED
.EndIf
Invoke AppendMenu,EBX,ECX,IDM_STYLE_TWOLINESTITLE,Offset szDoubleLine ;"Double Line"
MOV ECX,MF_STRING
.If EDI==2
OR ECX,MF_CHECKED
.EndIf
Invoke AppendMenu,EBX,ECX,IDM_STYLE_ONELINETITLE,Offset szSingleLine ;"Single Line"
Invoke TrackPopupMenu,EBX,TPM_LEFTALIGN or TPM_RIGHTBUTTON,Point.x,Point.y,0,hWnd,0
Invoke DestroyMenu,EBX
POP EDI
XOR EAX,EAX
RET
.EndIf
.EndIf
.ElseIf uMsg==WM_LBUTTONDOWN
Invoke KillTimer,WinAsmHandles.hMain,200
Invoke GetWindowLong,hWnd,0
MOV EBX,EAX
LOWORD lParam
MOV Point.x,EAX
HIWORD lParam
MOV Point.y,EAX
Invoke GetClientRect,hWnd,ADDR Rect
MOV Rect.left,XEDGE
SUB Rect.right,XEDGE
SUB Rect.right,11 ;i.e. exclude x button width
MOV EAX,YEDGE
MOV Rect.top,EAX
ADD EAX,13 ;I want the caption's height to be 13 pixels
MOV Rect.bottom,EAX
;Now Rect holds the caption area
Invoke PtInRect,ADDR Rect,Point.x,Point.y
.If EAX ;User pressed caption
MOV EAX,hWnd
.If EAX==WinAsmHandles.hProjExplorer || EAX==WinAsmHandles.hOutParent
MOV hActiveDock,EAX
.EndIf
.If pDWBlock
MOV ECX,4
MOV EAX,pDWBlock
@@:
MOV EDX,DWORD PTR [EAX+ECX-4]
.If EDX==hWnd
.If ECX<DWBlockSize
OnceMore:
PUSH DWORD PTR [EAX+ECX]
POP DWORD PTR [EAX+ECX-4] ;.ie. we move the handle one position above
ADD ECX,4
.If ECX<DWBlockSize
JMP OnceMore
.Else
PUSH hWnd
POP DWORD PTR [EAX+ECX-4] ;.ie. we move the handle one position above
JMP Done
.EndIf
.Else
PUSH hWnd
POP DWORD PTR [EAX+ECX-4] ;.ie. we move the handle one position above
JMP Done
.EndIf
.EndIf
.If ECX<DWBlockSize
ADD ECX,4
JMP @B
.EndIf
.EndIf
Done:
Invoke SetCapture,hWnd
Invoke LoadCursor,hInstance,107;IDC_DRAGCURSOR
MOV hDragCursor,EAX
Invoke SetCursor,EAX
MOV DOCKDATA.fState[EBX],USERDOCKINGUNDOCKING
PUSH EDI
Invoke GetParent,hWnd
.If EAX==WinAsmHandles.hMain
MOV EDI,hWnd
.Else ;i.e. floating
MOV EDI,EAX
.EndIf
;Invoke GetWindowRect,hWnd,ADDR DOCKDATA.FocusRect[EBX]
Invoke GetWindowRect,EDI,ADDR [EBX].DOCKDATA.FocusRect
;-----------------------------------------------------
;This is needed ONLY for the NoDock Drawing of focus Rectangle
MOV EAX,[EBX].DOCKDATA.FocusRect.right
SUB EAX,[EBX].DOCKDATA.FocusRect.left
Invoke MulDiv,Point.x,[EBX].DOCKDATA.NoDock.dWidth,EAX
MOV DOCKDATA.MousePos.x[EBX],EAX
MOV EAX,Point.y
MOV DOCKDATA.MousePos.y[EBX],EAX
.If EDI!=hWnd ;i.e. floating
Invoke GetSystemMetrics,SM_CXSIZEFRAME
ADD DOCKDATA.MousePos.x[EBX],EAX
Invoke GetSystemMetrics,SM_CYSIZEFRAME
ADD DOCKDATA.MousePos.y[EBX],EAX
.EndIf
;-----------------------------------------------------
POP EDI
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
.Else
Invoke GetClientRect,hWnd,ADDR Rect
.If DOCKDATA.fDockedTo[EBX]==RIGHTDOCK
.If Point.x<XEDGE
MOV DOCKDATA.fState[EBX],USERSIZING
.Else
MOV DOCKDATA.fState[EBX],NULL
.EndIf
.ElseIf DOCKDATA.fDockedTo[EBX]==LEFTDOCK
MOV ECX,Rect.right
SUB ECX,XEDGE
.If Point.x>=ECX
MOV DOCKDATA.fState[EBX],USERSIZING
.Else
MOV DOCKDATA.fState[EBX],NULL
.EndIf
.ElseIf DOCKDATA.fDockedTo[EBX]==TOPDOCK
MOV ECX, Rect.bottom
SUB ECX,YEDGE
.If Point.y>=ECX
MOV DOCKDATA.fState[EBX],USERSIZING
.Else
MOV DOCKDATA.fState[EBX],NULL
.EndIf
.ElseIf DOCKDATA.fDockedTo[EBX]==BOTTOMDOCK
.If Point.y<YEDGE ;e.g. If edge is 5 --> show size from 0 to 4
MOV DOCKDATA.fState[EBX],USERSIZING
.Else
MOV DOCKDATA.fState[EBX],NULL
.EndIf
.Else
MOV DOCKDATA.fState[EBX],NULL
.EndIf
.If DOCKDATA.fState[EBX]==USERSIZING
Invoke SetCapture,hWnd
Invoke GetWindowRect,hClient,ADDR Rect
.If DOCKDATA.fDockedTo[EBX]==RIGHTDOCK
ADD Rect.left,8*XEDGE
PUSH Rect.left
Invoke GetWindowRect,hWnd,ADDR Rect
POP Rect.left
SUB Rect.right,8*XEDGE
Invoke LoadCursor,NULL,IDC_SIZEWE
.ElseIf DOCKDATA.fDockedTo[EBX]==LEFTDOCK
SUB Rect.right,8*XEDGE
PUSH Rect.right
Invoke GetWindowRect,hWnd,ADDR Rect
POP Rect.right
ADD Rect.left,8*XEDGE
Invoke LoadCursor,NULL,IDC_SIZEWE
.ElseIf DOCKDATA.fDockedTo[EBX]==TOPDOCK
SUB Rect.bottom,8*YEDGE
PUSH Rect.bottom
Invoke GetWindowRect,hWnd,ADDR Rect
POP Rect.bottom
ADD Rect.top,8*YEDGE
Invoke LoadCursor,NULL,IDC_SIZENS
.ElseIf DOCKDATA.fDockedTo[EBX]==BOTTOMDOCK
ADD Rect.top,8*YEDGE
PUSH Rect.top
Invoke GetWindowRect,hWnd,ADDR Rect
POP Rect.top
SUB Rect.bottom,8*YEDGE
Invoke LoadCursor,NULL,IDC_SIZENS
.EndIf
Invoke SetCursor,EAX
Invoke RtlMoveMemory,ADDR DOCKDATA.MousePos[EBX],ADDR Point,SizeOf POINT
Invoke GetWindowRect,hWnd,ADDR DOCKDATA.FocusRect[EBX]
;CALL DrawRectangle
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
Invoke ClipCursor,ADDR Rect
.Else
Invoke GetClientRect,hWnd,ADDR Rect
MOV Rect.left,XEDGE
SUB Rect.right,XEDGE
SUB Rect.right,11 ;i.e. exclude x button width
MOV EAX,YEDGE
MOV Rect.top,EAX
ADD EAX,13 ;I want the caption's height to be 13 pixels
MOV Rect.bottom,EAX
M2M Rect.left,Rect.right ; Now I am checking for x button
ADD Rect.right,11
Invoke PtInRect,ADDR Rect,Point.x,Point.y
.If EAX ;User pressed x button
Invoke SetCapture,hWnd
MOV DOCKDATA.fState[EBX],CLOSEBUTTONPRESSED
Invoke InvalidateRect,hWnd,NULL,FALSE
.EndIf
.EndIf
.EndIf
.ElseIf uMsg==WM_LBUTTONUP
Invoke SetTimer,WinAsmHandles.hMain,200,200,NULL
Invoke GetCapture
.If EAX==hWnd
Invoke GetWindowLong,hWnd,0
MOV EBX,EAX
.If DOCKDATA.fState[EBX]==CLOSEBUTTONPRESSED
Invoke ReleaseCapture
LOWORD lParam
MOV Point.x,EAX
HIWORD lParam
MOV Point.y,EAX
Invoke GetClientRect,hWnd,ADDR Rect
SUB Rect.right,XEDGE
MOV ECX,Rect.right
SUB ECX,11
MOV Rect.left,ECX
MOV EAX,YEDGE
MOV Rect.top,EAX
ADD EAX,13 ;I always need caption height 13 pixels
MOV Rect.bottom,EAX
Invoke PtInRect,ADDR Rect,Point.x,Point.y
.If EAX ;User relesed mouse in x button area
Invoke GetParent,hWnd
.If EAX==WinAsmHandles.hMain
Invoke ShowWindow,hWnd,SW_HIDE
.Else
Invoke ShowWindow,EAX,SW_HIDE
Invoke ShowWindow,hWnd,SW_HIDE
.EndIf
Invoke ClientResize
.Else
Invoke InvalidateRect,hWnd,NULL,FALSE ;Draw unpresed state
.EndIf
.Else
;CALL DrawRectangle
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
Invoke ReleaseCapture
.If DOCKDATA.fState[EBX]==USERDOCKINGUNDOCKING && DOCKDATA.fDockedTo[EBX] == NODOCK && DOCKDATA.fDockTo[EBX] == NODOCK
MOV DOCKDATA.fDockedTo[EBX],NODOCK
Invoke GetParent,hWnd
Invoke MoveFloatingWindow,EBX,EAX
.Else
;Invoke LockWindowUpdate,hClient
Invoke ClientResize
;Invoke LockWindowUpdate,0
.EndIf
Invoke DestroyCursor,hDragCursor ;If User is Docking/Undocking
;Invoke ReleaseCapture
;Needed for User Sizing
Invoke ClipCursor,NULL
.EndIf
MOV DOCKDATA.fState[EBX],NULL
.EndIf
.ElseIf uMsg==WM_MOUSEMOVE
Invoke GetCapture
.If EAX==hWnd
Invoke GetWindowLong,hWnd,0
MOV EBX,EAX
.If [EBX].DOCKDATA.fState==USERDOCKINGUNDOCKING
LOWORD lParam
MOV Point.x,EAX
HIWORD lParam
MOV Point.y,EAX
.If Point.x>7FFFh ;x and y of mouse move are 16-bit-->make them 32-bit
OR Point.x,0FFFF0000h
.EndIf
.If Point.y>7FFFh ;x and y of mouse move are 16-bit-->make them 32-bit
OR Point.y,0FFFF0000h
.EndIf
Invoke ClientToScreen,hWnd,ADDR Point
;Now Point is where the mouse is in Screen coordinates
MOV EAX,wParam
AND EAX,MK_CONTROL
.If EAX==MK_CONTROL ;If user is pressing control-->do not dock (Thanks andrew_k)
CALL NoDock
RET
.EndIf
Invoke WindowFromPoint,Point.x,Point.y
PUSH EAX
Invoke GetParent,EAX
MOV ECX,EAX
POP EAX
.If EAX==hWnd || ECX ==hWnd
Invoke GetWindowRect,hClient,ADDR Rect
.If [EBX].DOCKDATA.fDockedTo == LEFTDOCK
CALL DockToLeft
.ElseIf [EBX].DOCKDATA.fDockedTo == RIGHTDOCK
CALL DockToRight
.ElseIf [EBX].DOCKDATA.fDockedTo == TOPDOCK
CALL DockToTop
.ElseIf [EBX].DOCKDATA.fDockedTo == BOTTOMDOCK
CALL DockToBottom
.Else
CALL NoDock
.EndIf
.Else
Invoke GetWindowRect,hClient,ADDR Rect
SUB Rect.left,21
.If Rect.left>7FFFFFFFh
MOV Rect.left,0
.EndIf
SUB Rect.top,21
.If Rect.top>7FFFFFFFh
MOV Rect.top,0
.EndIf
ADD Rect.right,21
ADD Rect.bottom,21
MOV EAX,Point.x
MOV ECX,Point.y
.If EAX>Rect.left && EAX <Rect.right && ECX>Rect.top && ECX<Rect.bottom
Invoke GetWindowRect,hClient,ADDR Rect
MOV EAX,Rect.left
ADD EAX,20
MOV ECX,Rect.left
SUB ECX,20
.If ECX>7FFFFFFFh
MOV ECX,0
.EndIf
.If Point.x>=ECX && Point.x<=EAX ;Dock to the left
CALL DockToLeft
.Else
MOV EAX,Rect.right
ADD EAX,20
MOV ECX,Rect.right
SUB ECX,20
.If Point.x>=ECX && Point.x<=EAX ;Dock to the right
CALL DockToRight
.Else
MOV EAX,Rect.top
ADD EAX,20
MOV ECX,Rect.top
SUB ECX,20
.If ECX>7FFFFFFFh
MOV ECX,0
.EndIf
.If Point.y>=ECX && Point.y<=EAX ;Dock to the top
CALL DockToTop
.Else
MOV EAX,Rect.bottom
ADD EAX,20
MOV ECX,Rect.bottom
SUB ECX,20
.If Point.y>=ECX && Point.y<=EAX ;Dock to the bottom
CALL DockToBottom
.Else
CALL NoDock
.EndIf
.EndIf
.EndIf
.EndIf
.Else
Invoke GetWindowRect,hClient,ADDR Rect
CALL NoDock
.EndIf
.EndIf
.ElseIf [EBX].DOCKDATA.fState==USERSIZING
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
.If DOCKDATA.fDockedTo[EBX]==RIGHTDOCK || DOCKDATA.fDockedTo[EBX]==LEFTDOCK
Invoke LoadCursor,NULL,IDC_SIZEWE
.Else
Invoke LoadCursor,NULL,IDC_SIZENS
.EndIf
Invoke SetCursor,EAX
LOWORD lParam
MOV Point.x,EAX
HIWORD lParam
MOV Point.y,EAX
.If Point.x>7FFFh ;x and y of mouse move are 16-bit-->make them 32-bit
OR Point.x,0FFFF0000h
.EndIf
.If Point.y>7FFFh ;x and y of mouse move are 16-bit-->make them 32-bit
OR Point.y,0FFFF0000h
.EndIf
MOV ECX,Point.x
MOV EAX,DOCKDATA.MousePos.x[EBX]
SUB ECX,EAX
MOV EAX,DOCKDATA.MousePos.y[EBX]
MOV EDX,Point.y
SUB EDX,EAX
.If DOCKDATA.fDockedTo[EBX]==RIGHTDOCK
ADD DOCKDATA.FocusRect.left[EBX],ECX
.ElseIf DOCKDATA.fDockedTo[EBX]==LEFTDOCK
ADD DOCKDATA.FocusRect.right[EBX],ECX
.ElseIf DOCKDATA.fDockedTo[EBX]==TOPDOCK
ADD DOCKDATA.FocusRect.bottom[EBX],EDX
.ElseIf DOCKDATA.fDockedTo[EBX]==BOTTOMDOCK
ADD DOCKDATA.FocusRect.top[EBX],EDX
.EndIf
;CALL DrawRectangle
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
Invoke RtlMoveMemory,ADDR DOCKDATA.MousePos[EBX],ADDR Point,SizeOf POINT
.EndIf
;We haven't captured mouse yet
.Else ;Here I need to check if mouse is over the edge and WHICH EDGE
LOWORD lParam
MOV Point.x,EAX
HIWORD lParam
MOV Point.y,EAX
Invoke GetWindowLong,hWnd,0
MOV EBX,EAX
Invoke GetClientRect,hWnd,ADDR Rect
.If DOCKDATA.fDockedTo[EBX]==RIGHTDOCK
.If Point.x<XEDGE ;e.g. If edge is 5 --> show size from 0 to 4
Invoke LoadCursor,NULL,IDC_SIZEWE
Invoke SetCursor,EAX
;MOV DOCKDATA.fState[EBX],USERSIZING
;.Else
;MOV DOCKDATA.fState[EBX],NULL
.EndIf
.ElseIf DOCKDATA.fDockedTo[EBX]==LEFTDOCK
MOV ECX,Rect.right
SUB ECX,XEDGE
.If Point.x>=ECX
Invoke LoadCursor,NULL,IDC_SIZEWE
Invoke SetCursor,EAX
;MOV DOCKDATA.fState[EBX],USERSIZING
;.Else
;MOV DOCKDATA.fState[EBX],NULL
.EndIf
.ElseIf DOCKDATA.fDockedTo[EBX]==TOPDOCK
MOV ECX, Rect.bottom
SUB ECX,YEDGE
.If Point.y>=ECX
Invoke LoadCursor,NULL,IDC_SIZENS
Invoke SetCursor,EAX
;MOV DOCKDATA.fState[EBX],USERSIZING
;.Else
;MOV DOCKDATA.fState[EBX],NULL
.EndIf
.ElseIf DOCKDATA.fDockedTo[EBX]==BOTTOMDOCK
.If Point.y<YEDGE ;e.g. If edge is 5 --> show size from 0 to 4
Invoke LoadCursor,NULL,IDC_SIZENS
Invoke SetCursor,EAX
;MOV DOCKDATA.fState[EBX],USERSIZING
;.Else
;MOV DOCKDATA.fState[EBX],NULL
.EndIf
.EndIf
.EndIf
.ElseIf uMsg==WM_SIZE
Invoke GetWindowLong,hWnd,GWL_STYLE
AND EAX,WS_POPUP
.If EAX ;ie this is a float window
Invoke GetWindow,hWnd,GW_CHILD
.If EAX
PUSH EDI
MOV EDI,EAX
Invoke GetClientRect,hWnd,ADDR Rect
;Make its child Docking window exaclty equal to the client area
Invoke MoveWindow,EDI,Rect.left,Rect.top,Rect.right,Rect.bottom,TRUE
Invoke GetWindowLong,hWnd,0
MOV EBX,EAX
Invoke GetWindowRect,hWnd,ADDR [EBX].DOCKDATA.FocusRect
MOV EAX,[EBX].DOCKDATA.FocusRect.right
SUB EAX,[EBX].DOCKDATA.FocusRect.left
MOV DOCKDATA.NoDock.dWidth[EBX],EAX
MOV EAX,[EBX].DOCKDATA.FocusRect.bottom
SUB EAX,[EBX].DOCKDATA.FocusRect.top
MOV DOCKDATA.NoDock.dHeight[EBX],EAX
; Invoke GetWindowRect,EDI,ADDR [EBX].DOCKDATA.FocusRect
; Invoke GetWindowRect,hWnd,ADDR Rect
; MOV EAX,Rect.right
; SUB EAX,Rect.left
; MOV DOCKDATA.NoDock.dWidth[EBX],EAX
; MOV EAX,Rect.bottom
; SUB EAX,Rect.top
; MOV DOCKDATA.NoDock.dHeight[EBX],EAX
POP EDI
.EndIf
.EndIf
.ElseIf uMsg==WM_MOVE
Invoke GetWindowLong,hWnd,GWL_STYLE
AND EAX,WS_POPUP
.If EAX ;ie this is a float window
Invoke GetWindowLong,hWnd,0
.If EAX && DOCKDATA.fDockedTo[EAX]==NODOCK
MOV EBX,EAX
LEA EDX,Rect
Invoke GetWindowRect,hWnd,EDX
M2M DOCKDATA.NoDock.dLeft[EBX],Rect.left
M2M DOCKDATA.NoDock.dTop[EBX],Rect.top
.EndIf
.EndIf
.ElseIf uMsg==WM_LBUTTONDBLCLK
Invoke GetWindowLong,hWnd,0
.If EAX && [EAX].DOCKDATA.fDockedTo!=NODOCK
MOV EBX,EAX
MOV EAX,[EBX].DOCKDATA.NoDock.dLeft
MOV [EBX].DOCKDATA.FocusRect.left,EAX
ADD EAX,[EBX].DOCKDATA.NoDock.dWidth
MOV [EBX].DOCKDATA.FocusRect.right,EAX
MOV EAX,[EBX].DOCKDATA.NoDock.dTop
MOV [EBX].DOCKDATA.FocusRect.top,EAX
ADD EAX,[EBX].DOCKDATA.NoDock.dHeight
MOV [EBX].DOCKDATA.FocusRect.bottom,EAX
MOV DOCKDATA.fDockTo[EBX],NODOCK
Invoke ClientResize
.EndIf
.ElseIf uMsg==WAM_GETCLIENTRECT
Invoke GetClientRect,hWnd,lParam;ADDR Rect
MOV EAX,lParam
ADD [EAX].RECT.left,XEDGE
SUB [EAX].RECT.right,XEDGE;2*XEDGE
ADD [EAX].RECT.top,YEDGE+14
SUB [EAX].RECT.bottom,YEDGE;2*YEDGE+14
.ElseIf uMsg==WAM_DESTROYDOCKINGWINDOW
.If pDWBlock
MOV ECX,4
MOV EAX,pDWBlock
@@:
MOV EDX,DWORD PTR [EAX+ECX-4]
.If EDX==hWnd
.If ECX<DWBlockSize
OnceMoree:
PUSH DWORD PTR [EAX+ECX]
POP DWORD PTR [EAX+ECX-4] ;.ie. we move the handle one position above
ADD ECX,4
.If ECX<DWBlockSize
JMP OnceMoree
.Else
PUSH hWnd
POP DWORD PTR [EAX+ECX-4] ;.ie. we move the handle one position above
JMP Donee
.EndIf
.Else
PUSH hWnd
POP DWORD PTR [EAX+ECX-4] ;.ie. we move the handle one position above
JMP Donee
.EndIf
.EndIf
.If ECX<DWBlockSize
ADD ECX,4
JMP @B
.EndIf
.EndIf
Donee:
;Now hWnd is last in the pDWBlock
;Therefore:
SUB DWBlockSize,4
Invoke GetParent,hWnd
.If EAX==WinAsmHandles.hMain
MOV EAX,hWnd
.EndIf
PUSH EAX
Invoke GetWindowLong,EAX,0
MOV [EAX].DOCKDATA.fDockTo,10 ;<---------------Only a flag to test in WM_CLOSE
POP EAX
Invoke DestroyWindow,EAX
Invoke ClientResize
.ElseIf uMsg==WM_CLOSE
Invoke GetWindowLong,hWnd,0
.If [EAX].DOCKDATA.fDockTo!=10 ;This is only set from WAM_DESTROYDOCKINGWINDOW otherwise do NOT destroy docking window
XOR EAX,EAX
RET
.EndIf
.EndIf
Invoke DefWindowProc,hWnd,uMsg,wParam,lParam ;Default message processing
RET
;------------------------------------------------------------------------
DockToTop:
.If DOCKDATA.fDockTo[EBX] != TOPDOCK
MOV DOCKDATA.fDockTo[EBX],TOPDOCK
;Erase existing Focus Rectangle!
;CALL DrawRectangle
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
.If DOCKDATA.fDockedTo[EBX]==TOPDOCK ;i.e Already Docked to Top
Invoke GetWindowRect,hWnd,ADDR DOCKDATA.FocusRect[EBX]
.Else
MOV EAX,Rect.left
MOV DOCKDATA.FocusRect.left[EBX],EAX
MOV EAX,Rect.right
.If DOCKDATA.fDockedTo[EBX]==RIGHTDOCK
ADD EAX,DOCKDATA.DockRightWidth[EBX]
.EndIf
MOV DOCKDATA.FocusRect.right[EBX],EAX
MOV EAX,Rect.bottom
MOV ECX,Rect.top
MOV DOCKDATA.FocusRect.top[EBX],ECX
SUB EAX,ECX
.If DOCKDATA.fDockedTo[EBX]==BOTTOMDOCK
ADD EAX,DOCKDATA.DockBottomHeight[EBX]
.EndIf
.If DOCKDATA.DockTopHeight[EBX]>EAX
ADD ECX,EAX
.Else
ADD ECX,DOCKDATA.DockTopHeight[EBX]
.EndIf
MOV DOCKDATA.FocusRect.bottom[EBX],ECX
.If DOCKDATA.fDockedTo[EBX]==LEFTDOCK ;i.e Already Docked to left
MOV EAX,Rect.left
SUB EAX,DOCKDATA.DockLeftWidth[EBX]
MOV DOCKDATA.FocusRect.left[EBX],EAX
.EndIf
.EndIf
;Draw It!
;CALL DrawRectangle
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
.EndIf
RETN
;------------------------------------------------------------------------
DockToBottom:
.If DOCKDATA.fDockTo[EBX] != BOTTOMDOCK
MOV DOCKDATA.fDockTo[EBX],BOTTOMDOCK
;Erase existing Focus Rectangle!
;CALL DrawRectangle
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
.If DOCKDATA.fDockedTo[EBX]==BOTTOMDOCK ;i.e Already Docked to bottom
Invoke GetWindowRect,hWnd,ADDR DOCKDATA.FocusRect[EBX]
.Else
MOV ECX,Rect.right
MOV EAX,Rect.left
MOV DOCKDATA.FocusRect.left[EBX],EAX
SUB ECX,EAX
ADD EAX,ECX
.If DOCKDATA.fDockedTo[EBX]==RIGHTDOCK
ADD EAX,DOCKDATA.DockRightWidth[EBX]
.EndIf
MOV DOCKDATA.FocusRect.right[EBX],EAX
MOV EAX,Rect.bottom
MOV DOCKDATA.FocusRect.bottom[EBX],EAX
MOV ECX,Rect.top
SUB EAX,ECX ;Client Rectangle height
.If DOCKDATA.fDockedTo[EBX]==TOPDOCK
ADD EAX,DOCKDATA.DockTopHeight[EBX]
.EndIf
.If DOCKDATA.DockBottomHeight[EBX]>EAX
MOV DOCKDATA.FocusRect.top[EBX],ECX
.Else
MOV ECX,Rect.bottom
SUB ECX,DOCKDATA.DockBottomHeight[EBX]
MOV DOCKDATA.FocusRect.top[EBX],ECX
.EndIf
.If DOCKDATA.fDockedTo[EBX]==LEFTDOCK ;i.e Already Docked to left
MOV EAX,Rect.left
SUB EAX,DOCKDATA.DockLeftWidth[EBX]
MOV DOCKDATA.FocusRect.left[EBX],EAX
.EndIf
.EndIf
;Draw It!
;CALL DrawRectangle
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
.EndIf
RETN
;------------------------------------------------------------------------
DockToLeft:
.If DOCKDATA.fDockTo[EBX] != LEFTDOCK
MOV DOCKDATA.fDockTo[EBX],LEFTDOCK
;Erase existing Focus Rectangle!
;CALL DrawRectangle
Invoke DrawRectangle,0,ADDR DOCKDATA.FocusRect[EBX]
.If DOCKDATA.fDockedTo[EBX]==LEFTDOCK ;i.e Already Docked to left
Invoke GetWindowRect,hWnd,ADDR DOCKDATA.FocusRect[EBX]
.Else
MOV EAX,Rect.right
MOV ECX,Rect.left
MOV DOCKDATA.FocusRect.left[EBX],ECX
SUB EAX,ECX ;Client Width
.If DOCKDATA.fDockedTo[EBX]==RIGHTDOCK
ADD EAX,DOCKDATA.DockRightWidth[EBX]
.EndIf
.If DOCKDATA.DockLeftWidth[EBX]>EAX
ADD ECX,EAX
.Else
ADD ECX,DOCKDATA.DockLeftWidth[EBX]
.EndIf
MOV DOCKDATA.FocusRect.right[EBX],ECX
.If DOCKDATA.fDockedTo[EBX]==TOPDOCK ;i.e Already Docked to top
MOV EAX,Rect.top
SUB EAX,DOCKDATA.DockTopHeight[EBX]
MOV DOCKDATA.FocusRect.top[EBX],EAX
MOV EAX,Rect.bottom
MOV DOCKDATA.FocusRect.bottom[EBX],EAX
.ElseIf DOCKDATA.fDockedTo[EBX]==BOTTOMDOCK
MOV EAX,Rect.top
MOV DOCKDATA.FocusRect.top[EBX],EAX
MOV EAX,Rect.bottom
ADD EAX, DOCKDATA.DockBottomHeight[EBX]
MOV DOCKDATA.FocusRect.bottom[EBX],EAX
.Else
MOV EAX,Rect.top