3 static const TCHAR szToolDockWndClass
[] = TEXT("ImageSoftToolDockWndClass");
5 typedef struct _TOOLDOCKWND_INIT
7 PTOOLBAR_DOCKS TbDocks
;
9 } TOOLDOCKWND_INIT
, *PTOOLDOCKWND_INIT
;
12 TbdCalculateInsertIndex(PTOOLBAR_DOCKS TbDocks
,
13 DOCK_POSITION Position
,
19 GetWindowRect(TbDocks
->hRebar
[Position
],
26 if (pt
.y
> rcRebar
.top
+ ((rcRebar
.bottom
- rcRebar
.top
) / 2))
32 if (pt
.x
> rcRebar
.left
+ ((rcRebar
.right
- rcRebar
.left
) / 2))
44 TbdAdjustUpdateClientRect(PTOOLBAR_DOCKS TbDocks
,
47 INT i
, DocksVisible
= 0;
49 for (i
= 0; i
< DOCKS_COUNT
; i
++)
51 if (TbDocks
->hRebar
[i
] != NULL
)
57 if (DocksVisible
!= 0)
59 rcClient
->top
+= TbDocks
->rcRebar
[TOP_DOCK
].bottom
;
60 rcClient
->left
+= TbDocks
->rcRebar
[LEFT_DOCK
].right
;
61 rcClient
->right
-= TbDocks
->rcRebar
[RIGHT_DOCK
].right
;
62 rcClient
->bottom
-= TbDocks
->rcRebar
[BOTTOM_DOCK
].bottom
;
65 TbDocks
->rcClient
= *rcClient
;
71 TbdDeferDocks(HDWP hWinPosInfo
,
72 PTOOLBAR_DOCKS TbDocks
)
75 HDWP hRet
= hWinPosInfo
;
77 cx
= TbDocks
->rcClient
.right
- TbDocks
->rcClient
.left
;
78 cy
= TbDocks
->rcClient
.bottom
- TbDocks
->rcClient
.top
;
81 if (TbDocks
->hRebar
[TOP_DOCK
] != NULL
)
83 hRet
= DeferWindowPos(hRet
,
84 TbDocks
->hRebar
[TOP_DOCK
],
86 TbDocks
->rcClient
.left
- TbDocks
->rcRebar
[LEFT_DOCK
].right
,
87 TbDocks
->rcClient
.top
- TbDocks
->rcRebar
[TOP_DOCK
].bottom
,
88 cx
+ TbDocks
->rcRebar
[LEFT_DOCK
].right
+ TbDocks
->rcRebar
[RIGHT_DOCK
].right
,
89 TbDocks
->rcRebar
[TOP_DOCK
].bottom
,
96 if (TbDocks
->hRebar
[LEFT_DOCK
] != NULL
)
98 hRet
= DeferWindowPos(hRet
,
99 TbDocks
->hRebar
[LEFT_DOCK
],
101 TbDocks
->rcClient
.left
- TbDocks
->rcRebar
[LEFT_DOCK
].right
,
102 TbDocks
->rcClient
.top
,
103 TbDocks
->rcRebar
[LEFT_DOCK
].right
,
111 if (TbDocks
->hRebar
[RIGHT_DOCK
] != NULL
)
113 hRet
= DeferWindowPos(hRet
,
114 TbDocks
->hRebar
[RIGHT_DOCK
],
116 TbDocks
->rcClient
.right
,
117 TbDocks
->rcClient
.top
,
118 TbDocks
->rcRebar
[RIGHT_DOCK
].right
,
126 if (TbDocks
->hRebar
[BOTTOM_DOCK
] != NULL
)
128 hRet
= DeferWindowPos(hRet
,
129 TbDocks
->hRebar
[BOTTOM_DOCK
],
131 TbDocks
->rcClient
.left
- TbDocks
->rcRebar
[LEFT_DOCK
].right
,
132 TbDocks
->rcClient
.bottom
,
133 cx
+ TbDocks
->rcRebar
[LEFT_DOCK
].right
+ TbDocks
->rcRebar
[RIGHT_DOCK
].right
,
134 TbDocks
->rcRebar
[BOTTOM_DOCK
].bottom
,
144 TbnDockbarItemFromBandId(PTOOLBAR_DOCKS TbDocks
,
145 DOCK_POSITION Position
,
148 REBARBANDINFO rbi
= {0};
150 rbi
.cbSize
= sizeof(rbi
);
151 rbi
.fMask
= RBBIM_LPARAM
;
153 if (SendMessage(TbDocks
->hRebar
[Position
],
158 return (PDOCKBAR_ITEM
)rbi
.lParam
;
165 TbnRebarChangeSize(PTOOLBAR_DOCKS TbDocks
,
166 DOCK_POSITION Position
)
170 TbDocks
->rcRebar
[Position
].left
= 0;
171 TbDocks
->rcRebar
[Position
].top
= 0;
173 cRebar
= (LONG
)SendMessage(TbDocks
->hRebar
[Position
],
182 TbDocks
->rcRebar
[Position
].bottom
= cRebar
;
187 TbDocks
->rcRebar
[Position
].right
= cRebar
;
194 if (TbDocks
->ParentResize
!= NULL
)
198 GetClientRect(TbDocks
->hParent
,
201 TbDocks
->ParentResize(TbDocks
->Context
,
202 rcClient
.right
- rcClient
.left
,
203 rcClient
.bottom
- rcClient
.top
);
208 TbnRebarChevronPushed(PTOOLBAR_DOCKS TbDocks
,
209 DOCK_POSITION Position
,
210 LPNMREBARCHEVRON lpnm
)
214 Item
= TbnDockbarItemFromBandId(TbDocks
,
218 if (Item
!= NULL
&& Item
->Callbacks
->ChevronPushed
)
220 Item
->Callbacks
->ChevronPushed(TbDocks
,
229 TbnRebarBeginDrag(PTOOLBAR_DOCKS TbDocks
,
230 DOCK_POSITION Position
,
235 Item
= TbnDockbarItemFromBandId(TbDocks
,
241 TbDocks
->Dragging
= Item
;
242 TbDocks
->DraggingBandId
= lpnmrb
->wID
;
250 TbnRebarEndDrag(PTOOLBAR_DOCKS TbDocks
,
251 DOCK_POSITION Position
,
256 Item
= TbnDockbarItemFromBandId(TbDocks
,
267 TbdDockBarIdFromClientWindow(PTOOLBAR_DOCKS TbDocks
,
274 Item
= TbDocks
->Items
;
277 if (Item
->hWndClient
== hWndClient
)
279 *Id
= Item
->DockBar
.BarId
;
291 TbdHandleNotifications(PTOOLBAR_DOCKS TbDocks
,
295 BOOL Handled
= FALSE
;
297 if (pnmh
->hwndFrom
!= NULL
)
299 DOCK_POSITION Position
;
301 for (Position
= TOP_DOCK
; Position
< NO_DOCK
; Position
++)
303 if (pnmh
->hwndFrom
== TbDocks
->hRebar
[Position
])
307 case RBN_HEIGHTCHANGE
:
309 TbnRebarChangeSize(TbDocks
,
316 *Result
= TbnRebarBeginDrag(TbDocks
,
324 TbnRebarEndDrag(TbDocks
,
330 case RBN_CHEVRONPUSHED
:
332 TbnRebarChevronPushed(TbDocks
,
334 (LPNMREBARCHEVRON
)pnmh
);
349 TbdCreateToolbarWnd(PTOOLBAR_DOCKS TbDocks
,
351 DOCK_POSITION PrevPosition
,
359 LPCTSTR lpCaption
= NULL
;
360 TOOLDOCKWND_INIT Init
;
363 Init
.TbDocks
= TbDocks
;
366 if (rbi
->fMask
& RBBIM_TEXT
)
368 lpCaption
= rbi
->lpText
;
371 Item
->Callbacks
->DockBand(TbDocks
,
378 if (rbi
->fMask
& RBBIM_CHILD
)
379 Item
->hWndClient
= rbi
->hwndChild
;
381 Item
->hWndClient
= NULL
;
384 if ((rbi
->fMask
& (RBBIM_CHILDSIZE
| RBBIM_SIZE
)) == (RBBIM_CHILDSIZE
| RBBIM_SIZE
))
387 static const DWORD dwStyle
= WS_POPUPWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_DLGFRAME
;
388 static const DWORD dwExStyle
= WS_EX_TOOLWINDOW
;
390 rcWnd
.left
= pt
.x
- GetSystemMetrics(SM_CXFIXEDFRAME
) - (GetSystemMetrics(SM_CYSMCAPTION
) / 2);
391 rcWnd
.top
= pt
.y
+ GetSystemMetrics(SM_CYFIXEDFRAME
) + (GetSystemMetrics(SM_CYSMCAPTION
) / 2);
392 rcWnd
.right
= rcWnd
.left
+ rbi
->cx
;
393 rcWnd
.bottom
= rcWnd
.top
+ rbi
->cyMinChild
;
395 if (AdjustWindowRectEx(&rcWnd
,
400 hToolbar
= CreateWindowEx(dwExStyle
,
406 rcWnd
.right
- rcWnd
.left
,
407 rcWnd
.bottom
- rcWnd
.top
,
412 if (hToolbar
!= NULL
)
416 if (uBand
!= (UINT
)-1)
418 /* delete the band before showing the client window,
419 otherwise deleting the band will cause the client
420 window to be hidden, regardless of whether the band
421 was hidden before being deleted or not */
428 if (Item
->hWndClient
!= NULL
)
430 GetClientRect(hToolbar
,
433 SetParent(Item
->hWndClient
,
436 SetWindowPos(Item
->hWndClient
,
444 SetWindowPos(Item
->hWndClient
,
450 SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
453 SetWindowPos(hToolbar
,
459 SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
463 SetCursor(LoadCursor(NULL
, IDC_ARROW
));
464 SendMessage(hToolbar
,
480 TdbInsertToolbar(PTOOLBAR_DOCKS TbDocks
,
482 DOCK_POSITION Position
)
484 LPTSTR lpCaption
= NULL
;
485 REBARBANDINFO rbi
= {0};
488 rbi
.cbSize
= sizeof(rbi
);
489 rbi
.fMask
= RBBIM_ID
| RBBIM_STYLE
| RBBIM_LPARAM
;
490 rbi
.wID
= Item
->DockBar
.BarId
;
491 rbi
.fStyle
= RBBS_GRIPPERALWAYS
;
492 rbi
.lParam
= (LPARAM
)Item
;
494 if (Item
->DockBar
.DisplayTextId
!= 0)
496 if (AllocAndLoadString(&lpCaption
,
498 Item
->DockBar
.DisplayTextId
))
500 rbi
.fMask
|= RBBIM_TEXT
;
501 rbi
.lpText
= lpCaption
;
505 if (Item
->hWndClient
!= NULL
)
507 rbi
.fMask
|= RBBIM_CHILD
;
508 rbi
.hwndChild
= Item
->hWndClient
;
511 switch (Item
->DockBar
.Position
)
517 /* FIXME - calculate size */
518 Ret
= TbdCreateToolbarWnd(TbDocks
,
520 Item
->DockBar
.Position
,
535 if (Item
->Callbacks
->InsertBand
!= NULL
)
537 AddBand
= Item
->Callbacks
->InsertBand(TbDocks
,
546 Item
->Callbacks
->DockBand(TbDocks
,
550 Item
->DockBar
.Position
,
553 if (rbi
.fMask
& RBBIM_CHILD
)
554 Item
->hWndClient
= rbi
.hwndChild
;
556 Item
->hWndClient
= NULL
;
558 Ret
= SendMessage(TbDocks
->hRebar
[Position
],
564 Item
->PrevDock
= Position
;
565 Item
->PrevBandIndex
= (UINT
)SendMessage(TbDocks
->hRebar
[Position
],
567 (WPARAM
)Item
->DockBar
.BarId
,
576 if (lpCaption
!= NULL
)
578 LocalFree((HLOCAL
)lpCaption
);
585 TbdAddToolbar(PTOOLBAR_DOCKS TbDocks
,
586 const DOCKBAR
*Dockbar
,
588 const DOCKBAR_ITEM_CALLBACKS
*Callbacks
)
593 hRebar
= TbDocks
->hRebar
[Dockbar
->Position
];
596 Item
= HeapAlloc(ProcessHeap
,
598 sizeof(DOCKBAR_ITEM
));
601 /* Initialize the item */
602 Item
->DockBar
= *Dockbar
;
603 Item
->Context
= Context
;
604 Item
->hWndTool
= NULL
;
605 Item
->PrevDock
= Dockbar
->Position
;
607 Item
->Callbacks
= Callbacks
;
609 /* Create the client control */
610 if (Callbacks
->CreateClient
!= NULL
&&
611 !Callbacks
->CreateClient(TbDocks
,
617 HeapFree(ProcessHeap
,
624 /* Insert the item into the list */
625 Item
->Next
= TbDocks
->Items
;
626 TbDocks
->Items
= Item
;
628 return TdbInsertToolbar(TbDocks
,
637 #define GWLP_TBDOCKS 0
638 #define GWLP_DOCKITEM (GWLP_TBDOCKS + sizeof(PTOOLBAR_DOCKS))
639 #define TD_EXTRA_BYTES (GWLP_DOCKITEM + sizeof(PDOCKBAR_ITEM))
641 static LRESULT CALLBACK
642 ToolDockWndProc(HWND hwnd
,
647 PTOOLBAR_DOCKS TbDocks
;
651 /* Get the window context */
652 TbDocks
= (PTOOLBAR_DOCKS
)GetWindowLongPtr(hwnd
,
654 Item
= (PDOCKBAR_ITEM
)GetWindowLongPtr(hwnd
,
657 if ((TbDocks
== NULL
|| Item
== NULL
) && uMsg
!= WM_CREATE
)
659 goto HandleDefaultMessage
;
666 TbdHandleActivation(TbDocks
,
670 goto HandleDefaultMessage
;
675 TbDocks
= ((PTOOLDOCKWND_INIT
)(((LPCREATESTRUCT
)lParam
)->lpCreateParams
))->TbDocks
;
676 Item
= ((PTOOLDOCKWND_INIT
)(((LPCREATESTRUCT
)lParam
)->lpCreateParams
))->Item
;
677 Item
->hWndTool
= hwnd
;
679 SetWindowLongPtr(hwnd
,
682 SetWindowLongPtr(hwnd
,
692 Item
->hWndTool
= NULL
;
694 SetWindowLongPtr(hwnd
,
697 SetWindowLongPtr(hwnd
,
705 HandleDefaultMessage
:
706 Ret
= DefWindowProc(hwnd
,
717 static LRESULT CALLBACK
718 RebarSubclassProc(HWND hWnd
,
722 UINT_PTR uIdSubclass
,
727 Ret
= DefSubclassProc(hWnd
,
732 if (uMsg
== WM_MOUSEMOVE
&& (wParam
& MK_LBUTTON
))
734 DOCK_POSITION Position
, DragTo
= NO_DOCK
;
737 PTOOLBAR_DOCKS TbDocks
= (PTOOLBAR_DOCKS
)dwRefData
;
740 szTearOff
.cx
= GetSystemMetrics(SM_CXCURSOR
);
741 szTearOff
.cy
= GetSystemMetrics(SM_CYCURSOR
);
744 * Check if we're dragging and if it's time to remove the band
746 if (TbDocks
->Dragging
!= NULL
&& GetCapture() == hWnd
)
750 InflateRect(&rcClient
,
754 pt
.x
= GET_X_LPARAM(lParam
);
755 pt
.y
= GET_Y_LPARAM(lParam
);
757 if (!PtInRect(&rcClient
,
764 /* Save all rebar band information, don't query RBBIM_HEADERSIZE because it
765 seems to cause problems with toolbars*/
766 rbi
.cbSize
= sizeof(rbi
);
767 rbi
.fMask
= RBBIM_BACKGROUND
| RBBIM_CHILD
| RBBIM_CHILDSIZE
| RBBIM_COLORS
|
768 RBBIM_IDEALSIZE
| RBBIM_ID
| RBBIM_IMAGE
| RBBIM_LPARAM
| RBBIM_SIZE
|
769 RBBIM_STYLE
| RBBIM_TEXT
;
770 rbi
.lpText
= TbDocks
->szTempText
;
771 rbi
.cch
= sizeof(TbDocks
->szTempText
);
773 uBand
= (UINT
)SendMessage(hWnd
,
775 (WPARAM
)TbDocks
->DraggingBandId
,
778 if (uBand
!= (UINT
)-1 &&
784 MapWindowPoints(hWnd
,
789 /* Check if the user is trying to drag it into another dock */
790 for (Position
= TOP_DOCK
; Position
< NO_DOCK
; Position
++)
792 if (TbDocks
->hRebar
[Position
] != NULL
&&
793 TbDocks
->hRebar
[Position
] != hWnd
&&
794 GetWindowRect(TbDocks
->hRebar
[Position
],
810 /* Get the current dock */
811 for (Position
= TOP_DOCK
; Position
< NO_DOCK
; Position
++)
813 if (TbDocks
->hRebar
[Position
] == hWnd
)
821 if (SendMessage(hWnd
,
826 /* Change the parent to the new rebar control */
827 if (TbDocks
->Dragging
->hWndClient
!= NULL
)
829 SetWindowPos(TbDocks
->Dragging
->hWndClient
,
835 SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
);
837 SetParent(TbDocks
->Dragging
->hWndClient
,
838 TbDocks
->hRebar
[DragTo
]);
840 SetWindowPos(TbDocks
->Dragging
->hWndClient
,
846 SWP_NOSIZE
| SWP_NOZORDER
);
849 if (DragTo
== NO_DOCK
)
851 if (!TbdCreateToolbarWnd(TbDocks
,
868 /* Remove the band from the current rebar control */
869 if (SendMessage(hWnd
,
876 /* Calculate where to insert the new bar */
877 uIndex
= TbdCalculateInsertIndex(TbDocks
,
881 SetActiveWindow(TbDocks
->hRebar
[DragTo
]);
883 TbDocks
->Dragging
->Callbacks
->DockBand(TbDocks
,
884 &TbDocks
->Dragging
->DockBar
,
885 TbDocks
->Dragging
->Context
,
890 if (rbi
.fMask
& RBBIM_CHILD
)
891 TbDocks
->Dragging
->hWndClient
= rbi
.hwndChild
;
893 TbDocks
->Dragging
->hWndClient
= NULL
;
895 /* Insert the toolbar into the new rebar */
896 rbi
.fMask
|= RBBIM_STYLE
;
897 rbi
.fStyle
|= RBBS_HIDDEN
;
898 if (SendMessage(TbDocks
->hRebar
[DragTo
],
903 uBand
= (UINT
)SendMessage(TbDocks
->hRebar
[DragTo
],
905 (WPARAM
)TbDocks
->DraggingBandId
,
908 SendMessage(TbDocks
->hRebar
[DragTo
],
913 /* Simulate a mouse click to continue dragging */
914 if (uBand
!= (UINT
)-1 &&
915 TbDocks
->Dragging
->hWndClient
!= NULL
&&
916 GetWindowRect(TbDocks
->Dragging
->hWndClient
,
923 pt
.x
= rc
.left
+ ((rc
.right
- rc
.left
) / 2);
929 pt
.y
= rc
.top
+ ((rc
.bottom
- rc
.top
) / 2);
933 MapWindowPoints(HWND_DESKTOP
,
934 TbDocks
->hRebar
[DragTo
],
938 SetCursor(LoadCursor(NULL
, IDC_SIZEALL
));
940 SendMessage(TbDocks
->hRebar
[DragTo
],
954 TbDocks
->Dragging
= NULL
;
972 TbdHandleEnabling(PTOOLBAR_DOCKS TbDocks
,
978 Item
= TbDocks
->Items
;
981 if (Item
->hWndTool
!= NULL
&&
982 Item
->hWndTool
!= hWnd
)
984 EnableWindow(Item
->hWndTool
,
992 TbdHandleActivation(PTOOLBAR_DOCKS TbDocks
,
997 BOOL SynchronizeSiblings
= TRUE
;
998 BOOL KeepActive
= *(BOOL
*)wParam
;
999 HWND hWndActivate
= *(HWND
*)lParam
;
1002 Item
= TbDocks
->Items
;
1003 while (Item
!= NULL
)
1005 if (Item
->hWndTool
!= NULL
&&
1006 Item
->hWndTool
== hWndActivate
)
1009 SynchronizeSiblings
= FALSE
;
1015 if (hWndActivate
!= (HWND
)-1)
1017 if (SynchronizeSiblings
)
1019 Item
= TbDocks
->Items
;
1020 while (Item
!= NULL
)
1022 if (Item
->hWndTool
!= NULL
&&
1023 Item
->hWndTool
!= hWnd
&&
1024 Item
->hWndTool
!= hWndActivate
)
1026 SendMessage(Item
->hWndTool
,
1038 *wParam
= (WPARAM
)KeepActive
;
1042 TbdShowFloatingToolbars(PTOOLBAR_DOCKS TbDocks
,
1047 Item
= TbDocks
->Items
;
1048 while (Item
!= NULL
)
1050 if (Item
->hWndTool
!= NULL
)
1052 if ((Show
&& !IsWindowVisible(Item
->hWndTool
)) ||
1053 (!Show
&& IsWindowVisible(Item
->hWndTool
)))
1055 ShowWindow(Item
->hWndTool
,
1056 (Show
? SW_SHOW
: SW_HIDE
));
1064 TbdInitializeDocks(PTOOLBAR_DOCKS TbDocks
,
1067 PDOCKBAR_PARENTRESIZE ParentResizeProc
)
1069 DWORD rbStyle
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
1070 CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NOMOVEY
| CCS_NOMOVEX
|
1071 RBS_VARHEIGHT
| RBS_AUTOSIZE
;
1073 DOCK_POSITION Position
;
1075 TbDocks
->hParent
= hWndParent
;
1076 TbDocks
->Context
= Context
;
1077 TbDocks
->ParentResize
= ParentResizeProc
;
1079 for (Position
= TOP_DOCK
; Position
< NO_DOCK
; Position
++)
1085 rbStyle
|= CCS_VERT
;
1088 rbStyle
&= ~CCS_VERT
;
1092 TbDocks
->hRebar
[Position
] = CreateWindowEx(WS_EX_TOOLWINDOW
,
1105 if (TbDocks
->hRebar
[Position
] != NULL
)
1107 SetWindowSubclass(TbDocks
->hRebar
[Position
],
1110 (DWORD_PTR
)TbDocks
);
1118 WNDCLASSEX wc
= {0};
1120 wc
.cbSize
= sizeof(WNDCLASSEX
);
1121 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1122 wc
.lpfnWndProc
= ToolDockWndProc
;
1123 wc
.cbWndExtra
= TD_EXTRA_BYTES
;
1124 wc
.hInstance
= hInstance
;
1125 wc
.hCursor
= LoadCursor(NULL
,
1127 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1128 wc
.lpszClassName
= szToolDockWndClass
;
1130 return RegisterClassEx(&wc
) != (ATOM
)0;
1136 UnregisterClass(szToolDockWndClass
,