- Revert 47615. Please fix actual sysreg instead of adding inconsistency between...
[reactos.git] / rosapps / templates / imagesoft / tooldock.c
1 #include <precomp.h>
2
3 static const TCHAR szToolDockWndClass[] = TEXT("ImageSoftToolDockWndClass");
4
5 typedef struct _TOOLDOCKWND_INIT
6 {
7 PTOOLBAR_DOCKS TbDocks;
8 PDOCKBAR_ITEM Item;
9 } TOOLDOCKWND_INIT, *PTOOLDOCKWND_INIT;
10
11 static UINT
12 TbdCalculateInsertIndex(PTOOLBAR_DOCKS TbDocks,
13 DOCK_POSITION Position,
14 POINT pt)
15 {
16 RECT rcRebar;
17 UINT Ret = 0;
18
19 GetWindowRect(TbDocks->hRebar[Position],
20 &rcRebar);
21
22 switch (Position)
23 {
24 case TOP_DOCK:
25 case BOTTOM_DOCK:
26 if (pt.y > rcRebar.top + ((rcRebar.bottom - rcRebar.top) / 2))
27 Ret = (UINT)-1;
28 break;
29
30 case LEFT_DOCK:
31 case RIGHT_DOCK:
32 if (pt.x > rcRebar.left + ((rcRebar.right - rcRebar.left) / 2))
33 Ret = (UINT)-1;
34 break;
35
36 default:
37 break;
38 }
39
40 return Ret;
41 }
42
43 INT
44 TbdAdjustUpdateClientRect(PTOOLBAR_DOCKS TbDocks,
45 PRECT rcClient)
46 {
47 INT i, DocksVisible = 0;
48
49 for (i = 0; i < DOCKS_COUNT; i++)
50 {
51 if (TbDocks->hRebar[i] != NULL)
52 {
53 DocksVisible++;
54 }
55 }
56
57 if (DocksVisible != 0)
58 {
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;
63 }
64
65 TbDocks->rcClient = *rcClient;
66
67 return DocksVisible;
68 }
69
70 HDWP
71 TbdDeferDocks(HDWP hWinPosInfo,
72 PTOOLBAR_DOCKS TbDocks)
73 {
74 LONG cx, cy;
75 HDWP hRet = hWinPosInfo;
76
77 cx = TbDocks->rcClient.right - TbDocks->rcClient.left;
78 cy = TbDocks->rcClient.bottom - TbDocks->rcClient.top;
79
80 /* Top dock */
81 if (TbDocks->hRebar[TOP_DOCK] != NULL)
82 {
83 hRet = DeferWindowPos(hRet,
84 TbDocks->hRebar[TOP_DOCK],
85 NULL,
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,
90 SWP_NOZORDER);
91 if (hRet == NULL)
92 return NULL;
93 }
94
95 /* Left dock */
96 if (TbDocks->hRebar[LEFT_DOCK] != NULL)
97 {
98 hRet = DeferWindowPos(hRet,
99 TbDocks->hRebar[LEFT_DOCK],
100 NULL,
101 TbDocks->rcClient.left - TbDocks->rcRebar[LEFT_DOCK].right,
102 TbDocks->rcClient.top,
103 TbDocks->rcRebar[LEFT_DOCK].right,
104 cy,
105 SWP_NOZORDER);
106 if (hRet == NULL)
107 return NULL;
108 }
109
110 /* Right dock */
111 if (TbDocks->hRebar[RIGHT_DOCK] != NULL)
112 {
113 hRet = DeferWindowPos(hRet,
114 TbDocks->hRebar[RIGHT_DOCK],
115 NULL,
116 TbDocks->rcClient.right,
117 TbDocks->rcClient.top,
118 TbDocks->rcRebar[RIGHT_DOCK].right,
119 cy,
120 SWP_NOZORDER);
121 if (hRet == NULL)
122 return NULL;
123 }
124
125 /* Bottom dock */
126 if (TbDocks->hRebar[BOTTOM_DOCK] != NULL)
127 {
128 hRet = DeferWindowPos(hRet,
129 TbDocks->hRebar[BOTTOM_DOCK],
130 NULL,
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,
135 SWP_NOZORDER);
136 if (hRet == NULL)
137 return NULL;
138 }
139
140 return hRet;
141 }
142
143 static PDOCKBAR_ITEM
144 TbnDockbarItemFromBandId(PTOOLBAR_DOCKS TbDocks,
145 DOCK_POSITION Position,
146 UINT uBand)
147 {
148 REBARBANDINFO rbi = {0};
149
150 rbi.cbSize = sizeof(rbi);
151 rbi.fMask = RBBIM_LPARAM;
152
153 if (SendMessage(TbDocks->hRebar[Position],
154 RB_GETBANDINFO,
155 (WPARAM)uBand,
156 (LPARAM)&rbi))
157 {
158 return (PDOCKBAR_ITEM)rbi.lParam;
159 }
160
161 return NULL;
162 }
163
164 static VOID
165 TbnRebarChangeSize(PTOOLBAR_DOCKS TbDocks,
166 DOCK_POSITION Position)
167 {
168 LONG cRebar;
169
170 TbDocks->rcRebar[Position].left = 0;
171 TbDocks->rcRebar[Position].top = 0;
172
173 cRebar = (LONG)SendMessage(TbDocks->hRebar[Position],
174 RB_GETBARHEIGHT,
175 0,
176 0);
177
178 switch (Position)
179 {
180 case TOP_DOCK:
181 case BOTTOM_DOCK:
182 TbDocks->rcRebar[Position].bottom = cRebar;
183 break;
184
185 case LEFT_DOCK:
186 case RIGHT_DOCK:
187 TbDocks->rcRebar[Position].right = cRebar;
188 break;
189
190 default:
191 break;
192 }
193
194 if (TbDocks->ParentResize != NULL)
195 {
196 RECT rcClient = {0};
197
198 GetClientRect(TbDocks->hParent,
199 &rcClient);
200
201 TbDocks->ParentResize(TbDocks->Context,
202 rcClient.right - rcClient.left,
203 rcClient.bottom - rcClient.top);
204 }
205 }
206
207 static VOID
208 TbnRebarChevronPushed(PTOOLBAR_DOCKS TbDocks,
209 DOCK_POSITION Position,
210 LPNMREBARCHEVRON lpnm)
211 {
212 PDOCKBAR_ITEM Item;
213
214 Item = TbnDockbarItemFromBandId(TbDocks,
215 Position,
216 lpnm->uBand);
217
218 if (Item != NULL && Item->Callbacks->ChevronPushed)
219 {
220 Item->Callbacks->ChevronPushed(TbDocks,
221 &Item->DockBar,
222 Item->Context,
223 Item->hWndClient,
224 lpnm);
225 }
226 }
227
228 static LRESULT
229 TbnRebarBeginDrag(PTOOLBAR_DOCKS TbDocks,
230 DOCK_POSITION Position,
231 LPNMREBAR lpnmrb)
232 {
233 PDOCKBAR_ITEM Item;
234
235 Item = TbnDockbarItemFromBandId(TbDocks,
236 Position,
237 lpnmrb->uBand);
238
239 if (Item != NULL)
240 {
241 TbDocks->Dragging = Item;
242 TbDocks->DraggingBandId = lpnmrb->wID;
243 return FALSE;
244 }
245
246 return TRUE;
247 }
248
249 static VOID
250 TbnRebarEndDrag(PTOOLBAR_DOCKS TbDocks,
251 DOCK_POSITION Position,
252 LPNMREBAR lpnmrb)
253 {
254 PDOCKBAR_ITEM Item;
255
256 Item = TbnDockbarItemFromBandId(TbDocks,
257 Position,
258 lpnmrb->uBand);
259
260 if (Item != NULL)
261 {
262 /* Nothing to do */
263 }
264 }
265
266 BOOL
267 TbdDockBarIdFromClientWindow(PTOOLBAR_DOCKS TbDocks,
268 HWND hWndClient,
269 UINT *Id)
270 {
271 PDOCKBAR_ITEM Item;
272 BOOL Ret = FALSE;
273
274 Item = TbDocks->Items;
275 while (Item != NULL)
276 {
277 if (Item->hWndClient == hWndClient)
278 {
279 *Id = Item->DockBar.BarId;
280 Ret = TRUE;
281 break;
282 }
283
284 Item = Item->Next;
285 }
286
287 return Ret;
288 }
289
290 BOOL
291 TbdHandleNotifications(PTOOLBAR_DOCKS TbDocks,
292 LPNMHDR pnmh,
293 LRESULT *Result)
294 {
295 BOOL Handled = FALSE;
296
297 if (pnmh->hwndFrom != NULL)
298 {
299 DOCK_POSITION Position;
300
301 for (Position = TOP_DOCK; Position < NO_DOCK; Position++)
302 {
303 if (pnmh->hwndFrom == TbDocks->hRebar[Position])
304 {
305 switch (pnmh->code)
306 {
307 case RBN_HEIGHTCHANGE:
308 {
309 TbnRebarChangeSize(TbDocks,
310 Position);
311 break;
312 }
313
314 case RBN_BEGINDRAG:
315 {
316 *Result = TbnRebarBeginDrag(TbDocks,
317 Position,
318 (LPNMREBAR)pnmh);
319 break;
320 }
321
322 case RBN_ENDDRAG:
323 {
324 TbnRebarEndDrag(TbDocks,
325 Position,
326 (LPNMREBAR)pnmh);
327 break;
328 }
329
330 case RBN_CHEVRONPUSHED:
331 {
332 TbnRebarChevronPushed(TbDocks,
333 Position,
334 (LPNMREBARCHEVRON)pnmh);
335 break;
336 }
337 }
338
339 Handled = TRUE;
340 break;
341 }
342 }
343 }
344
345 return Handled;
346 }
347
348 static BOOL
349 TbdCreateToolbarWnd(PTOOLBAR_DOCKS TbDocks,
350 PDOCKBAR_ITEM Item,
351 DOCK_POSITION PrevPosition,
352 UINT PrevBandIndex,
353 LPREBARBANDINFO rbi,
354 POINT pt,
355 HWND hRebar,
356 UINT uBand,
357 BOOL Drag)
358 {
359 LPCTSTR lpCaption = NULL;
360 TOOLDOCKWND_INIT Init;
361 HWND hToolbar;
362
363 Init.TbDocks = TbDocks;
364 Init.Item = Item;
365
366 if (rbi->fMask & RBBIM_TEXT)
367 {
368 lpCaption = rbi->lpText;
369 }
370
371 Item->Callbacks->DockBand(TbDocks,
372 &Item->DockBar,
373 Item->Context,
374 PrevPosition,
375 NO_DOCK,
376 rbi);
377
378 if (rbi->fMask & RBBIM_CHILD)
379 Item->hWndClient = rbi->hwndChild;
380 else
381 Item->hWndClient = NULL;
382
383
384 if ((rbi->fMask & (RBBIM_CHILDSIZE | RBBIM_SIZE)) == (RBBIM_CHILDSIZE | RBBIM_SIZE))
385 {
386 RECT rcWnd;
387 static const DWORD dwStyle = WS_POPUPWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DLGFRAME;
388 static const DWORD dwExStyle = WS_EX_TOOLWINDOW;
389
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;
394
395 if (AdjustWindowRectEx(&rcWnd,
396 dwStyle,
397 FALSE,
398 dwExStyle))
399 {
400 hToolbar = CreateWindowEx(dwExStyle,
401 szToolDockWndClass,
402 lpCaption,
403 dwStyle,
404 rcWnd.left,
405 rcWnd.top,
406 rcWnd.right - rcWnd.left,
407 rcWnd.bottom - rcWnd.top,
408 TbDocks->hParent,
409 NULL,
410 hInstance,
411 &Init);
412 if (hToolbar != NULL)
413 {
414 RECT rcClient;
415
416 if (uBand != (UINT)-1)
417 {
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 */
422 SendMessage(hRebar,
423 RB_DELETEBAND,
424 (WPARAM)uBand,
425 0);
426 }
427
428 if (Item->hWndClient != NULL)
429 {
430 GetClientRect(hToolbar,
431 &rcClient);
432
433 SetParent(Item->hWndClient,
434 hToolbar);
435
436 SetWindowPos(Item->hWndClient,
437 NULL,
438 0,
439 0,
440 rcClient.right,
441 rcClient.bottom,
442 SWP_NOZORDER);
443
444 SetWindowPos(Item->hWndClient,
445 HWND_TOP,
446 0,
447 0,
448 0,
449 0,
450 SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
451 }
452
453 SetWindowPos(hToolbar,
454 HWND_TOP,
455 0,
456 0,
457 0,
458 0,
459 SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
460
461 if (Drag)
462 {
463 SetCursor(LoadCursor(NULL, IDC_ARROW));
464 SendMessage(hToolbar,
465 WM_NCLBUTTONDOWN,
466 HTCAPTION,
467 MAKELPARAM(pt.x,
468 pt.y));
469 }
470
471 return TRUE;
472 }
473 }
474 }
475
476 return FALSE;
477 }
478
479 static BOOL
480 TdbInsertToolbar(PTOOLBAR_DOCKS TbDocks,
481 PDOCKBAR_ITEM Item,
482 DOCK_POSITION Position)
483 {
484 LPTSTR lpCaption = NULL;
485 REBARBANDINFO rbi = {0};
486 BOOL Ret = FALSE;
487
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;
493
494 if (Item->DockBar.DisplayTextId != 0)
495 {
496 if (AllocAndLoadString(&lpCaption,
497 hInstance,
498 Item->DockBar.DisplayTextId))
499 {
500 rbi.fMask |= RBBIM_TEXT;
501 rbi.lpText = lpCaption;
502 }
503 }
504
505 if (Item->hWndClient != NULL)
506 {
507 rbi.fMask |= RBBIM_CHILD;
508 rbi.hwndChild = Item->hWndClient;
509 }
510
511 switch (Item->DockBar.Position)
512 {
513 case NO_DOCK:
514 {
515 POINT pt = {0};
516
517 /* FIXME - calculate size */
518 Ret = TbdCreateToolbarWnd(TbDocks,
519 Item,
520 Item->DockBar.Position,
521 (UINT)-1,
522 &rbi,
523 pt,
524 NULL,
525 (UINT)-1,
526 FALSE);
527 break;
528 }
529
530 default:
531 {
532 UINT Index = -1;
533 BOOL AddBand = TRUE;
534
535 if (Item->Callbacks->InsertBand != NULL)
536 {
537 AddBand = Item->Callbacks->InsertBand(TbDocks,
538 &Item->DockBar,
539 Item->Context,
540 &Index,
541 &rbi);
542 }
543
544 if (AddBand)
545 {
546 Item->Callbacks->DockBand(TbDocks,
547 &Item->DockBar,
548 Item->Context,
549 NO_DOCK,
550 Item->DockBar.Position,
551 &rbi);
552
553 if (rbi.fMask & RBBIM_CHILD)
554 Item->hWndClient = rbi.hwndChild;
555 else
556 Item->hWndClient = NULL;
557
558 Ret = SendMessage(TbDocks->hRebar[Position],
559 RB_INSERTBAND,
560 (WPARAM)Index,
561 (LPARAM)&rbi) != 0;
562 if (Ret)
563 {
564 Item->PrevDock = Position;
565 Item->PrevBandIndex = (UINT)SendMessage(TbDocks->hRebar[Position],
566 RB_IDTOINDEX,
567 (WPARAM)Item->DockBar.BarId,
568 0);
569 }
570 }
571
572 break;
573 }
574 }
575
576 if (lpCaption != NULL)
577 {
578 LocalFree((HLOCAL)lpCaption);
579 }
580
581 return Ret;
582 }
583
584 BOOL
585 TbdAddToolbar(PTOOLBAR_DOCKS TbDocks,
586 const DOCKBAR *Dockbar,
587 PVOID Context,
588 const DOCKBAR_ITEM_CALLBACKS *Callbacks)
589 {
590 PDOCKBAR_ITEM Item;
591 HWND hRebar;
592
593 hRebar = TbDocks->hRebar[Dockbar->Position];
594 if (hRebar != NULL)
595 {
596 Item = HeapAlloc(ProcessHeap,
597 0,
598 sizeof(DOCKBAR_ITEM));
599 if (Item != NULL)
600 {
601 /* Initialize the item */
602 Item->DockBar = *Dockbar;
603 Item->Context = Context;
604 Item->hWndTool = NULL;
605 Item->PrevDock = Dockbar->Position;
606
607 Item->Callbacks = Callbacks;
608
609 /* Create the client control */
610 if (Callbacks->CreateClient != NULL &&
611 !Callbacks->CreateClient(TbDocks,
612 &Item->DockBar,
613 Context,
614 hRebar,
615 &Item->hWndClient))
616 {
617 HeapFree(ProcessHeap,
618 0,
619 Item);
620
621 return FALSE;
622 }
623
624 /* Insert the item into the list */
625 Item->Next = TbDocks->Items;
626 TbDocks->Items = Item;
627
628 return TdbInsertToolbar(TbDocks,
629 Item,
630 Dockbar->Position);
631 }
632 }
633
634 return FALSE;
635 }
636
637 #define GWLP_TBDOCKS 0
638 #define GWLP_DOCKITEM (GWLP_TBDOCKS + sizeof(PTOOLBAR_DOCKS))
639 #define TD_EXTRA_BYTES (GWLP_DOCKITEM + sizeof(PDOCKBAR_ITEM))
640
641 static LRESULT CALLBACK
642 ToolDockWndProc(HWND hwnd,
643 UINT uMsg,
644 WPARAM wParam,
645 LPARAM lParam)
646 {
647 PTOOLBAR_DOCKS TbDocks;
648 PDOCKBAR_ITEM Item;
649 LRESULT Ret = 0;
650
651 /* Get the window context */
652 TbDocks = (PTOOLBAR_DOCKS)GetWindowLongPtr(hwnd,
653 GWLP_TBDOCKS);
654 Item = (PDOCKBAR_ITEM)GetWindowLongPtr(hwnd,
655 GWLP_DOCKITEM);
656
657 if ((TbDocks == NULL || Item == NULL) && uMsg != WM_CREATE)
658 {
659 goto HandleDefaultMessage;
660 }
661
662 switch (uMsg)
663 {
664 case WM_NCACTIVATE:
665 {
666 TbdHandleActivation(TbDocks,
667 hwnd,
668 &wParam,
669 &lParam);
670 goto HandleDefaultMessage;
671 }
672
673 case WM_CREATE:
674 {
675 TbDocks = ((PTOOLDOCKWND_INIT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->TbDocks;
676 Item = ((PTOOLDOCKWND_INIT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->Item;
677 Item->hWndTool = hwnd;
678
679 SetWindowLongPtr(hwnd,
680 GWLP_TBDOCKS,
681 (LONG_PTR)TbDocks);
682 SetWindowLongPtr(hwnd,
683 GWLP_DOCKITEM,
684 (LONG_PTR)Item);
685
686 Ret = TRUE;
687 break;
688 }
689
690 case WM_DESTROY:
691 {
692 Item->hWndTool = NULL;
693
694 SetWindowLongPtr(hwnd,
695 GWLP_USERDATA,
696 0);
697 SetWindowLongPtr(hwnd,
698 GWLP_DOCKITEM,
699 0);
700 break;
701 }
702
703 default:
704 {
705 HandleDefaultMessage:
706 Ret = DefWindowProc(hwnd,
707 uMsg,
708 wParam,
709 lParam);
710 break;
711 }
712 }
713
714 return Ret;
715 }
716
717 static LRESULT CALLBACK
718 RebarSubclassProc(HWND hWnd,
719 UINT uMsg,
720 WPARAM wParam,
721 LPARAM lParam,
722 UINT_PTR uIdSubclass,
723 DWORD_PTR dwRefData)
724 {
725 LRESULT Ret;
726
727 Ret = DefSubclassProc(hWnd,
728 uMsg,
729 wParam,
730 lParam);
731
732 if (uMsg == WM_MOUSEMOVE && (wParam & MK_LBUTTON))
733 {
734 DOCK_POSITION Position, DragTo = NO_DOCK;
735 RECT rcClient;
736 POINT pt;
737 PTOOLBAR_DOCKS TbDocks = (PTOOLBAR_DOCKS)dwRefData;
738 SIZE szTearOff;
739
740 szTearOff.cx = GetSystemMetrics(SM_CXCURSOR);
741 szTearOff.cy = GetSystemMetrics(SM_CYCURSOR);
742
743 /*
744 * Check if we're dragging and if it's time to remove the band
745 */
746 if (TbDocks->Dragging != NULL && GetCapture() == hWnd)
747 {
748 GetClientRect(hWnd,
749 &rcClient);
750 InflateRect(&rcClient,
751 szTearOff.cx,
752 szTearOff.cy);
753
754 pt.x = GET_X_LPARAM(lParam);
755 pt.y = GET_Y_LPARAM(lParam);
756
757 if (!PtInRect(&rcClient,
758 pt))
759 {
760 REBARBANDINFO rbi;
761 UINT uBand;
762 RECT rc;
763
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);
772
773 uBand = (UINT)SendMessage(hWnd,
774 RB_IDTOINDEX,
775 (WPARAM)TbDocks->DraggingBandId,
776 0);
777
778 if (uBand != (UINT)-1 &&
779 SendMessage(hWnd,
780 RB_GETBANDINFO,
781 (WPARAM)uBand,
782 (LPARAM)&rbi))
783 {
784 MapWindowPoints(hWnd,
785 HWND_DESKTOP,
786 &pt,
787 1);
788
789 /* Check if the user is trying to drag it into another dock */
790 for (Position = TOP_DOCK; Position < NO_DOCK; Position++)
791 {
792 if (TbDocks->hRebar[Position] != NULL &&
793 TbDocks->hRebar[Position] != hWnd &&
794 GetWindowRect(TbDocks->hRebar[Position],
795 &rc))
796 {
797 InflateRect(&rc,
798 szTearOff.cx,
799 szTearOff.cy);
800
801 if (PtInRect(&rc,
802 pt))
803 {
804 DragTo = Position;
805 break;
806 }
807 }
808 }
809
810 /* Get the current dock */
811 for (Position = TOP_DOCK; Position < NO_DOCK; Position++)
812 {
813 if (TbDocks->hRebar[Position] == hWnd)
814 {
815 break;
816 }
817 }
818
819 ReleaseCapture();
820
821 if (SendMessage(hWnd,
822 RB_SHOWBAND,
823 (WPARAM)uBand,
824 FALSE))
825 {
826 /* Change the parent to the new rebar control */
827 if (TbDocks->Dragging->hWndClient != NULL)
828 {
829 SetWindowPos(TbDocks->Dragging->hWndClient,
830 NULL,
831 0,
832 0,
833 0,
834 0,
835 SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER);
836
837 SetParent(TbDocks->Dragging->hWndClient,
838 TbDocks->hRebar[DragTo]);
839
840 SetWindowPos(TbDocks->Dragging->hWndClient,
841 NULL,
842 0,
843 0,
844 0,
845 0,
846 SWP_NOSIZE | SWP_NOZORDER);
847 }
848
849 if (DragTo == NO_DOCK)
850 {
851 if (!TbdCreateToolbarWnd(TbDocks,
852 TbDocks->Dragging,
853 Position,
854 uBand,
855 &rbi,
856 pt,
857 hWnd,
858 uBand,
859 TRUE))
860 {
861 goto MoveFailed;
862 }
863 }
864 else
865 {
866 BOOL Moved = FALSE;
867
868 /* Remove the band from the current rebar control */
869 if (SendMessage(hWnd,
870 RB_DELETEBAND,
871 (WPARAM)uBand,
872 0))
873 {
874 UINT uIndex;
875
876 /* Calculate where to insert the new bar */
877 uIndex = TbdCalculateInsertIndex(TbDocks,
878 DragTo,
879 pt);
880
881 SetActiveWindow(TbDocks->hRebar[DragTo]);
882
883 TbDocks->Dragging->Callbacks->DockBand(TbDocks,
884 &TbDocks->Dragging->DockBar,
885 TbDocks->Dragging->Context,
886 Position,
887 DragTo,
888 &rbi);
889
890 if (rbi.fMask & RBBIM_CHILD)
891 TbDocks->Dragging->hWndClient = rbi.hwndChild;
892 else
893 TbDocks->Dragging->hWndClient = NULL;
894
895 /* Insert the toolbar into the new rebar */
896 rbi.fMask |= RBBIM_STYLE;
897 rbi.fStyle |= RBBS_HIDDEN;
898 if (SendMessage(TbDocks->hRebar[DragTo],
899 RB_INSERTBAND,
900 (WPARAM)uIndex,
901 (LPARAM)&rbi))
902 {
903 uBand = (UINT)SendMessage(TbDocks->hRebar[DragTo],
904 RB_IDTOINDEX,
905 (WPARAM)TbDocks->DraggingBandId,
906 0);
907
908 SendMessage(TbDocks->hRebar[DragTo],
909 RB_SHOWBAND,
910 (WPARAM)uBand,
911 TRUE);
912
913 /* Simulate a mouse click to continue dragging */
914 if (uBand != (UINT)-1 &&
915 TbDocks->Dragging->hWndClient != NULL &&
916 GetWindowRect(TbDocks->Dragging->hWndClient,
917 &rc))
918 {
919 switch (DragTo)
920 {
921 case LEFT_DOCK:
922 case RIGHT_DOCK:
923 pt.x = rc.left + ((rc.right - rc.left) / 2);
924 pt.y = rc.top - 1;
925 break;
926
927 default:
928 pt.x = rc.left - 1;
929 pt.y = rc.top + ((rc.bottom - rc.top) / 2);
930 break;
931 }
932
933 MapWindowPoints(HWND_DESKTOP,
934 TbDocks->hRebar[DragTo],
935 &pt,
936 1);
937
938 SetCursor(LoadCursor(NULL, IDC_SIZEALL));
939
940 SendMessage(TbDocks->hRebar[DragTo],
941 WM_LBUTTONDOWN,
942 wParam,
943 MAKELPARAM(pt.x,
944 pt.y));
945
946 Moved = TRUE;
947 }
948 }
949 }
950
951 if (!Moved)
952 {
953 MoveFailed:
954 TbDocks->Dragging = NULL;
955
956 SendMessage(hWnd,
957 RB_SHOWBAND,
958 (WPARAM)uBand,
959 TRUE);
960 }
961 }
962 }
963 }
964 }
965 }
966 }
967
968 return Ret;
969 }
970
971 VOID
972 TbdHandleEnabling(PTOOLBAR_DOCKS TbDocks,
973 HWND hWnd,
974 BOOL Enable)
975 {
976 PDOCKBAR_ITEM Item;
977
978 Item = TbDocks->Items;
979 while (Item != NULL)
980 {
981 if (Item->hWndTool != NULL &&
982 Item->hWndTool != hWnd)
983 {
984 EnableWindow(Item->hWndTool,
985 Enable);
986 }
987 Item = Item->Next;
988 }
989 }
990
991 VOID
992 TbdHandleActivation(PTOOLBAR_DOCKS TbDocks,
993 HWND hWnd,
994 WPARAM *wParam,
995 LPARAM *lParam)
996 {
997 BOOL SynchronizeSiblings = TRUE;
998 BOOL KeepActive = *(BOOL*)wParam;
999 HWND hWndActivate = *(HWND*)lParam;
1000 PDOCKBAR_ITEM Item;
1001
1002 Item = TbDocks->Items;
1003 while (Item != NULL)
1004 {
1005 if (Item->hWndTool != NULL &&
1006 Item->hWndTool == hWndActivate)
1007 {
1008 KeepActive = TRUE;
1009 SynchronizeSiblings = FALSE;
1010 break;
1011 }
1012 Item = Item->Next;
1013 }
1014
1015 if (hWndActivate != (HWND)-1)
1016 {
1017 if (SynchronizeSiblings)
1018 {
1019 Item = TbDocks->Items;
1020 while (Item != NULL)
1021 {
1022 if (Item->hWndTool != NULL &&
1023 Item->hWndTool != hWnd &&
1024 Item->hWndTool != hWndActivate)
1025 {
1026 SendMessage(Item->hWndTool,
1027 WM_NCACTIVATE,
1028 (WPARAM)KeepActive,
1029 (LPARAM)-1);
1030 }
1031 Item = Item->Next;
1032 }
1033 }
1034 }
1035 else
1036 *lParam = 0;
1037
1038 *wParam = (WPARAM)KeepActive;
1039 }
1040
1041 VOID
1042 TbdShowFloatingToolbars(PTOOLBAR_DOCKS TbDocks,
1043 BOOL Show)
1044 {
1045 PDOCKBAR_ITEM Item;
1046
1047 Item = TbDocks->Items;
1048 while (Item != NULL)
1049 {
1050 if (Item->hWndTool != NULL)
1051 {
1052 if ((Show && !IsWindowVisible(Item->hWndTool)) ||
1053 (!Show && IsWindowVisible(Item->hWndTool)))
1054 {
1055 ShowWindow(Item->hWndTool,
1056 (Show ? SW_SHOW : SW_HIDE));
1057 }
1058 }
1059 Item = Item->Next;
1060 }
1061 }
1062
1063 VOID
1064 TbdInitializeDocks(PTOOLBAR_DOCKS TbDocks,
1065 HWND hWndParent,
1066 PVOID Context,
1067 PDOCKBAR_PARENTRESIZE ParentResizeProc)
1068 {
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;
1072
1073 DOCK_POSITION Position;
1074
1075 TbDocks->hParent = hWndParent;
1076 TbDocks->Context = Context;
1077 TbDocks->ParentResize = ParentResizeProc;
1078
1079 for (Position = TOP_DOCK; Position < NO_DOCK; Position++)
1080 {
1081 switch (Position)
1082 {
1083 case LEFT_DOCK:
1084 case RIGHT_DOCK:
1085 rbStyle |= CCS_VERT;
1086 break;
1087 default:
1088 rbStyle &= ~CCS_VERT;
1089 break;
1090 }
1091
1092 TbDocks->hRebar[Position] = CreateWindowEx(WS_EX_TOOLWINDOW,
1093 REBARCLASSNAME,
1094 NULL,
1095 rbStyle,
1096 0,
1097 0,
1098 0,
1099 0,
1100 TbDocks->hParent,
1101 NULL,
1102 hInstance,
1103 NULL);
1104
1105 if (TbDocks->hRebar[Position] != NULL)
1106 {
1107 SetWindowSubclass(TbDocks->hRebar[Position],
1108 RebarSubclassProc,
1109 1,
1110 (DWORD_PTR)TbDocks);
1111 }
1112 }
1113 }
1114
1115 BOOL
1116 TbdInitImpl(VOID)
1117 {
1118 WNDCLASSEX wc = {0};
1119
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,
1126 IDC_ARROW);
1127 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1128 wc.lpszClassName = szToolDockWndClass;
1129
1130 return RegisterClassEx(&wc) != (ATOM)0;
1131 }
1132
1133 VOID
1134 TbdUninitImpl(VOID)
1135 {
1136 UnregisterClass(szToolDockWndClass,
1137 hInstance);
1138 }