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
,
464 MAKEINTRESOURCE(IDC_ARROW
)));
465 SendMessage(hToolbar
,
481 TdbInsertToolbar(PTOOLBAR_DOCKS TbDocks
,
483 DOCK_POSITION Position
)
485 LPTSTR lpCaption
= NULL
;
486 REBARBANDINFO rbi
= {0};
489 rbi
.cbSize
= sizeof(rbi
);
490 rbi
.fMask
= RBBIM_ID
| RBBIM_STYLE
| RBBIM_LPARAM
;
491 rbi
.wID
= Item
->DockBar
.BarId
;
492 rbi
.fStyle
= RBBS_GRIPPERALWAYS
;
493 rbi
.lParam
= (LPARAM
)Item
;
495 if (Item
->DockBar
.DisplayTextId
!= 0)
497 if (AllocAndLoadString(&lpCaption
,
499 Item
->DockBar
.DisplayTextId
))
501 rbi
.fMask
|= RBBIM_TEXT
;
502 rbi
.lpText
= lpCaption
;
506 if (Item
->hWndClient
!= NULL
)
508 rbi
.fMask
|= RBBIM_CHILD
;
509 rbi
.hwndChild
= Item
->hWndClient
;
512 switch (Item
->DockBar
.Position
)
518 /* FIXME - calculate size */
519 Ret
= TbdCreateToolbarWnd(TbDocks
,
521 Item
->DockBar
.Position
,
536 if (Item
->Callbacks
->InsertBand
!= NULL
)
538 AddBand
= Item
->Callbacks
->InsertBand(TbDocks
,
547 Item
->Callbacks
->DockBand(TbDocks
,
551 Item
->DockBar
.Position
,
554 if (rbi
.fMask
& RBBIM_CHILD
)
555 Item
->hWndClient
= rbi
.hwndChild
;
557 Item
->hWndClient
= NULL
;
559 Ret
= SendMessage(TbDocks
->hRebar
[Position
],
565 Item
->PrevDock
= Position
;
566 Item
->PrevBandIndex
= (UINT
)SendMessage(TbDocks
->hRebar
[Position
],
568 (WPARAM
)Item
->DockBar
.BarId
,
577 if (lpCaption
!= NULL
)
579 LocalFree((HLOCAL
)lpCaption
);
586 TbdAddToolbar(PTOOLBAR_DOCKS TbDocks
,
587 const DOCKBAR
*Dockbar
,
589 const DOCKBAR_ITEM_CALLBACKS
*Callbacks
)
594 hRebar
= TbDocks
->hRebar
[Dockbar
->Position
];
597 Item
= HeapAlloc(ProcessHeap
,
599 sizeof(DOCKBAR_ITEM
));
602 /* Initialize the item */
603 Item
->DockBar
= *Dockbar
;
604 Item
->Context
= Context
;
605 Item
->hWndTool
= NULL
;
606 Item
->PrevDock
= Dockbar
->Position
;
608 Item
->Callbacks
= Callbacks
;
610 /* Create the client control */
611 if (Callbacks
->CreateClient
!= NULL
&&
612 !Callbacks
->CreateClient(TbDocks
,
618 HeapFree(ProcessHeap
,
625 /* Insert the item into the list */
626 Item
->Next
= TbDocks
->Items
;
627 TbDocks
->Items
= Item
;
629 return TdbInsertToolbar(TbDocks
,
638 #define GWLP_TBDOCKS 0
639 #define GWLP_DOCKITEM (GWLP_TBDOCKS + sizeof(PTOOLBAR_DOCKS))
640 #define TD_EXTRA_BYTES (GWLP_DOCKITEM + sizeof(PDOCKBAR_ITEM))
642 static LRESULT CALLBACK
643 ToolDockWndProc(HWND hwnd
,
648 PTOOLBAR_DOCKS TbDocks
;
652 /* Get the window context */
653 TbDocks
= (PTOOLBAR_DOCKS
)GetWindowLongPtr(hwnd
,
655 Item
= (PDOCKBAR_ITEM
)GetWindowLongPtr(hwnd
,
658 if ((TbDocks
== NULL
|| Item
== NULL
) && uMsg
!= WM_CREATE
)
660 goto HandleDefaultMessage
;
667 TbdHandleActivation(TbDocks
,
671 goto HandleDefaultMessage
;
676 TbDocks
= ((PTOOLDOCKWND_INIT
)(((LPCREATESTRUCT
)lParam
)->lpCreateParams
))->TbDocks
;
677 Item
= ((PTOOLDOCKWND_INIT
)(((LPCREATESTRUCT
)lParam
)->lpCreateParams
))->Item
;
678 Item
->hWndTool
= hwnd
;
680 SetWindowLongPtr(hwnd
,
683 SetWindowLongPtr(hwnd
,
693 Item
->hWndTool
= NULL
;
695 SetWindowLongPtr(hwnd
,
698 SetWindowLongPtr(hwnd
,
706 HandleDefaultMessage
:
707 Ret
= DefWindowProc(hwnd
,
718 static LRESULT CALLBACK
719 RebarSubclassProc(HWND hWnd
,
723 UINT_PTR uIdSubclass
,
728 Ret
= DefSubclassProc(hWnd
,
733 if (uMsg
== WM_MOUSEMOVE
&& (wParam
& MK_LBUTTON
))
735 DOCK_POSITION Position
, DragTo
= NO_DOCK
;
738 PTOOLBAR_DOCKS TbDocks
= (PTOOLBAR_DOCKS
)dwRefData
;
741 szTearOff
.cx
= GetSystemMetrics(SM_CXCURSOR
);
742 szTearOff
.cy
= GetSystemMetrics(SM_CYCURSOR
);
745 * Check if we're dragging and if it's time to remove the band
747 if (TbDocks
->Dragging
!= NULL
&& GetCapture() == hWnd
)
751 InflateRect(&rcClient
,
755 pt
.x
= GET_X_LPARAM(lParam
);
756 pt
.y
= GET_Y_LPARAM(lParam
);
758 if (!PtInRect(&rcClient
,
765 /* Save all rebar band information, don't query RBBIM_HEADERSIZE because it
766 seems to cause problems with toolbars*/
767 rbi
.cbSize
= sizeof(rbi
);
768 rbi
.fMask
= RBBIM_BACKGROUND
| RBBIM_CHILD
| RBBIM_CHILDSIZE
| RBBIM_COLORS
|
769 RBBIM_IDEALSIZE
| RBBIM_ID
| RBBIM_IMAGE
| RBBIM_LPARAM
| RBBIM_SIZE
|
770 RBBIM_STYLE
| RBBIM_TEXT
;
771 rbi
.lpText
= TbDocks
->szTempText
;
772 rbi
.cch
= sizeof(TbDocks
->szTempText
);
774 uBand
= (UINT
)SendMessage(hWnd
,
776 (WPARAM
)TbDocks
->DraggingBandId
,
779 if (uBand
!= (UINT
)-1 &&
785 MapWindowPoints(hWnd
,
790 /* Check if the user is trying to drag it into another dock */
791 for (Position
= TOP_DOCK
; Position
< NO_DOCK
; Position
++)
793 if (TbDocks
->hRebar
[Position
] != NULL
&&
794 TbDocks
->hRebar
[Position
] != hWnd
&&
795 GetWindowRect(TbDocks
->hRebar
[Position
],
811 /* Get the current dock */
812 for (Position
= TOP_DOCK
; Position
< NO_DOCK
; Position
++)
814 if (TbDocks
->hRebar
[Position
] == hWnd
)
822 if (SendMessage(hWnd
,
827 /* Change the parent to the new rebar control */
828 if (TbDocks
->Dragging
->hWndClient
!= NULL
)
830 SetWindowPos(TbDocks
->Dragging
->hWndClient
,
836 SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOZORDER
);
838 SetParent(TbDocks
->Dragging
->hWndClient
,
839 TbDocks
->hRebar
[DragTo
]);
841 SetWindowPos(TbDocks
->Dragging
->hWndClient
,
847 SWP_NOSIZE
| SWP_NOZORDER
);
850 if (DragTo
== NO_DOCK
)
852 if (!TbdCreateToolbarWnd(TbDocks
,
869 /* Remove the band from the current rebar control */
870 if (SendMessage(hWnd
,
877 /* Calculate where to insert the new bar */
878 uIndex
= TbdCalculateInsertIndex(TbDocks
,
882 SetActiveWindow(TbDocks
->hRebar
[DragTo
]);
884 TbDocks
->Dragging
->Callbacks
->DockBand(TbDocks
,
885 &TbDocks
->Dragging
->DockBar
,
886 TbDocks
->Dragging
->Context
,
891 if (rbi
.fMask
& RBBIM_CHILD
)
892 TbDocks
->Dragging
->hWndClient
= rbi
.hwndChild
;
894 TbDocks
->Dragging
->hWndClient
= NULL
;
896 /* Insert the toolbar into the new rebar */
897 rbi
.fMask
|= RBBIM_STYLE
;
898 rbi
.fStyle
|= RBBS_HIDDEN
;
899 if (SendMessage(TbDocks
->hRebar
[DragTo
],
904 uBand
= (UINT
)SendMessage(TbDocks
->hRebar
[DragTo
],
906 (WPARAM
)TbDocks
->DraggingBandId
,
909 SendMessage(TbDocks
->hRebar
[DragTo
],
914 /* Simulate a mouse click to continue dragging */
915 if (uBand
!= (UINT
)-1 &&
916 TbDocks
->Dragging
->hWndClient
!= NULL
&&
917 GetWindowRect(TbDocks
->Dragging
->hWndClient
,
924 pt
.x
= rc
.left
+ ((rc
.right
- rc
.left
) / 2);
930 pt
.y
= rc
.top
+ ((rc
.bottom
- rc
.top
) / 2);
934 MapWindowPoints(HWND_DESKTOP
,
935 TbDocks
->hRebar
[DragTo
],
939 SetCursor(LoadCursor(NULL
,
940 MAKEINTRESOURCE(IDC_SIZEALL
)));
942 SendMessage(TbDocks
->hRebar
[DragTo
],
956 TbDocks
->Dragging
= NULL
;
974 TbdHandleEnabling(PTOOLBAR_DOCKS TbDocks
,
980 Item
= TbDocks
->Items
;
983 if (Item
->hWndTool
!= NULL
&&
984 Item
->hWndTool
!= hWnd
)
986 EnableWindow(Item
->hWndTool
,
994 TbdHandleActivation(PTOOLBAR_DOCKS TbDocks
,
999 BOOL SynchronizeSiblings
= TRUE
;
1000 BOOL KeepActive
= *(BOOL
*)wParam
;
1001 HWND hWndActivate
= *(HWND
*)lParam
;
1004 Item
= TbDocks
->Items
;
1005 while (Item
!= NULL
)
1007 if (Item
->hWndTool
!= NULL
&&
1008 Item
->hWndTool
== hWndActivate
)
1011 SynchronizeSiblings
= FALSE
;
1017 if (hWndActivate
!= (HWND
)-1)
1019 if (SynchronizeSiblings
)
1021 Item
= TbDocks
->Items
;
1022 while (Item
!= NULL
)
1024 if (Item
->hWndTool
!= NULL
&&
1025 Item
->hWndTool
!= hWnd
&&
1026 Item
->hWndTool
!= hWndActivate
)
1028 SendMessage(Item
->hWndTool
,
1040 *wParam
= (WPARAM
)KeepActive
;
1044 TbdShowFloatingToolbars(PTOOLBAR_DOCKS TbDocks
,
1049 Item
= TbDocks
->Items
;
1050 while (Item
!= NULL
)
1052 if (Item
->hWndTool
!= NULL
)
1054 if ((Show
&& !IsWindowVisible(Item
->hWndTool
)) ||
1055 (!Show
&& IsWindowVisible(Item
->hWndTool
)))
1057 ShowWindow(Item
->hWndTool
,
1058 (Show
? SW_SHOW
: SW_HIDE
));
1066 TbdInitializeDocks(PTOOLBAR_DOCKS TbDocks
,
1069 PDOCKBAR_PARENTRESIZE ParentResizeProc
)
1071 DWORD rbStyle
= WS_CHILD
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
1072 CCS_NODIVIDER
| CCS_NOPARENTALIGN
| CCS_NOMOVEY
| CCS_NOMOVEX
|
1073 RBS_VARHEIGHT
| RBS_AUTOSIZE
;
1075 DOCK_POSITION Position
;
1077 TbDocks
->hParent
= hWndParent
;
1078 TbDocks
->Context
= Context
;
1079 TbDocks
->ParentResize
= ParentResizeProc
;
1081 for (Position
= TOP_DOCK
; Position
< NO_DOCK
; Position
++)
1087 rbStyle
|= CCS_VERT
;
1090 rbStyle
&= ~CCS_VERT
;
1094 TbDocks
->hRebar
[Position
] = CreateWindowEx(WS_EX_TOOLWINDOW
,
1107 if (TbDocks
->hRebar
[Position
] != NULL
)
1109 SetWindowSubclass(TbDocks
->hRebar
[Position
],
1112 (DWORD_PTR
)TbDocks
);
1120 WNDCLASSEX wc
= {0};
1122 wc
.cbSize
= sizeof(WNDCLASSEX
);
1123 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1124 wc
.lpfnWndProc
= ToolDockWndProc
;
1125 wc
.cbWndExtra
= TD_EXTRA_BYTES
;
1126 wc
.hInstance
= hInstance
;
1127 wc
.hCursor
= LoadCursor(NULL
,
1129 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1130 wc
.lpszClassName
= szToolDockWndClass
;
1132 return RegisterClassEx(&wc
) != (ATOM
)0;
1138 UnregisterClass(szToolDockWndClass
,