-revert janderwalds change until because it breaks the gcc 4.x build
[reactos.git] / reactos / base / applications / 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,
464 MAKEINTRESOURCE(IDC_ARROW)));
465 SendMessage(hToolbar,
466 WM_NCLBUTTONDOWN,
467 HTCAPTION,
468 MAKELPARAM(pt.x,
469 pt.y));
470 }
471
472 return TRUE;
473 }
474 }
475 }
476
477 return FALSE;
478 }
479
480 static BOOL
481 TdbInsertToolbar(PTOOLBAR_DOCKS TbDocks,
482 PDOCKBAR_ITEM Item,
483 DOCK_POSITION Position)
484 {
485 LPTSTR lpCaption = NULL;
486 REBARBANDINFO rbi = {0};
487 BOOL Ret = FALSE;
488
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;
494
495 if (Item->DockBar.DisplayTextId != 0)
496 {
497 if (AllocAndLoadString(&lpCaption,
498 hInstance,
499 Item->DockBar.DisplayTextId))
500 {
501 rbi.fMask |= RBBIM_TEXT;
502 rbi.lpText = lpCaption;
503 }
504 }
505
506 if (Item->hWndClient != NULL)
507 {
508 rbi.fMask |= RBBIM_CHILD;
509 rbi.hwndChild = Item->hWndClient;
510 }
511
512 switch (Item->DockBar.Position)
513 {
514 case NO_DOCK:
515 {
516 POINT pt = {0};
517
518 /* FIXME - calculate size */
519 Ret = TbdCreateToolbarWnd(TbDocks,
520 Item,
521 Item->DockBar.Position,
522 (UINT)-1,
523 &rbi,
524 pt,
525 NULL,
526 (UINT)-1,
527 FALSE);
528 break;
529 }
530
531 default:
532 {
533 UINT Index = -1;
534 BOOL AddBand = TRUE;
535
536 if (Item->Callbacks->InsertBand != NULL)
537 {
538 AddBand = Item->Callbacks->InsertBand(TbDocks,
539 &Item->DockBar,
540 Item->Context,
541 &Index,
542 &rbi);
543 }
544
545 if (AddBand)
546 {
547 Item->Callbacks->DockBand(TbDocks,
548 &Item->DockBar,
549 Item->Context,
550 NO_DOCK,
551 Item->DockBar.Position,
552 &rbi);
553
554 if (rbi.fMask & RBBIM_CHILD)
555 Item->hWndClient = rbi.hwndChild;
556 else
557 Item->hWndClient = NULL;
558
559 Ret = SendMessage(TbDocks->hRebar[Position],
560 RB_INSERTBAND,
561 (WPARAM)Index,
562 (LPARAM)&rbi) != 0;
563 if (Ret)
564 {
565 Item->PrevDock = Position;
566 Item->PrevBandIndex = (UINT)SendMessage(TbDocks->hRebar[Position],
567 RB_IDTOINDEX,
568 (WPARAM)Item->DockBar.BarId,
569 0);
570 }
571 }
572
573 break;
574 }
575 }
576
577 if (lpCaption != NULL)
578 {
579 LocalFree((HLOCAL)lpCaption);
580 }
581
582 return Ret;
583 }
584
585 BOOL
586 TbdAddToolbar(PTOOLBAR_DOCKS TbDocks,
587 const DOCKBAR *Dockbar,
588 PVOID Context,
589 const DOCKBAR_ITEM_CALLBACKS *Callbacks)
590 {
591 PDOCKBAR_ITEM Item;
592 HWND hRebar;
593
594 hRebar = TbDocks->hRebar[Dockbar->Position];
595 if (hRebar != NULL)
596 {
597 Item = HeapAlloc(ProcessHeap,
598 0,
599 sizeof(DOCKBAR_ITEM));
600 if (Item != NULL)
601 {
602 /* Initialize the item */
603 Item->DockBar = *Dockbar;
604 Item->Context = Context;
605 Item->hWndTool = NULL;
606 Item->PrevDock = Dockbar->Position;
607
608 Item->Callbacks = Callbacks;
609
610 /* Create the client control */
611 if (Callbacks->CreateClient != NULL &&
612 !Callbacks->CreateClient(TbDocks,
613 &Item->DockBar,
614 Context,
615 hRebar,
616 &Item->hWndClient))
617 {
618 HeapFree(ProcessHeap,
619 0,
620 Item);
621
622 return FALSE;
623 }
624
625 /* Insert the item into the list */
626 Item->Next = TbDocks->Items;
627 TbDocks->Items = Item;
628
629 return TdbInsertToolbar(TbDocks,
630 Item,
631 Dockbar->Position);
632 }
633 }
634
635 return FALSE;
636 }
637
638 #define GWLP_TBDOCKS 0
639 #define GWLP_DOCKITEM (GWLP_TBDOCKS + sizeof(PTOOLBAR_DOCKS))
640 #define TD_EXTRA_BYTES (GWLP_DOCKITEM + sizeof(PDOCKBAR_ITEM))
641
642 static LRESULT CALLBACK
643 ToolDockWndProc(HWND hwnd,
644 UINT uMsg,
645 WPARAM wParam,
646 LPARAM lParam)
647 {
648 PTOOLBAR_DOCKS TbDocks;
649 PDOCKBAR_ITEM Item;
650 LRESULT Ret = 0;
651
652 /* Get the window context */
653 TbDocks = (PTOOLBAR_DOCKS)GetWindowLongPtr(hwnd,
654 GWLP_TBDOCKS);
655 Item = (PDOCKBAR_ITEM)GetWindowLongPtr(hwnd,
656 GWLP_DOCKITEM);
657
658 if ((TbDocks == NULL || Item == NULL) && uMsg != WM_CREATE)
659 {
660 goto HandleDefaultMessage;
661 }
662
663 switch (uMsg)
664 {
665 case WM_NCACTIVATE:
666 {
667 TbdHandleActivation(TbDocks,
668 hwnd,
669 &wParam,
670 &lParam);
671 goto HandleDefaultMessage;
672 }
673
674 case WM_CREATE:
675 {
676 TbDocks = ((PTOOLDOCKWND_INIT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->TbDocks;
677 Item = ((PTOOLDOCKWND_INIT)(((LPCREATESTRUCT)lParam)->lpCreateParams))->Item;
678 Item->hWndTool = hwnd;
679
680 SetWindowLongPtr(hwnd,
681 GWLP_TBDOCKS,
682 (LONG_PTR)TbDocks);
683 SetWindowLongPtr(hwnd,
684 GWLP_DOCKITEM,
685 (LONG_PTR)Item);
686
687 Ret = TRUE;
688 break;
689 }
690
691 case WM_DESTROY:
692 {
693 Item->hWndTool = NULL;
694
695 SetWindowLongPtr(hwnd,
696 GWLP_USERDATA,
697 0);
698 SetWindowLongPtr(hwnd,
699 GWLP_DOCKITEM,
700 0);
701 break;
702 }
703
704 default:
705 {
706 HandleDefaultMessage:
707 Ret = DefWindowProc(hwnd,
708 uMsg,
709 wParam,
710 lParam);
711 break;
712 }
713 }
714
715 return Ret;
716 }
717
718 static LRESULT CALLBACK
719 RebarSubclassProc(HWND hWnd,
720 UINT uMsg,
721 WPARAM wParam,
722 LPARAM lParam,
723 UINT_PTR uIdSubclass,
724 DWORD_PTR dwRefData)
725 {
726 LRESULT Ret;
727
728 Ret = DefSubclassProc(hWnd,
729 uMsg,
730 wParam,
731 lParam);
732
733 if (uMsg == WM_MOUSEMOVE && (wParam & MK_LBUTTON))
734 {
735 DOCK_POSITION Position, DragTo = NO_DOCK;
736 RECT rcClient;
737 POINT pt;
738 PTOOLBAR_DOCKS TbDocks = (PTOOLBAR_DOCKS)dwRefData;
739 SIZE szTearOff;
740
741 szTearOff.cx = GetSystemMetrics(SM_CXCURSOR);
742 szTearOff.cy = GetSystemMetrics(SM_CYCURSOR);
743
744 /*
745 * Check if we're dragging and if it's time to remove the band
746 */
747 if (TbDocks->Dragging != NULL && GetCapture() == hWnd)
748 {
749 GetClientRect(hWnd,
750 &rcClient);
751 InflateRect(&rcClient,
752 szTearOff.cx,
753 szTearOff.cy);
754
755 pt.x = GET_X_LPARAM(lParam);
756 pt.y = GET_Y_LPARAM(lParam);
757
758 if (!PtInRect(&rcClient,
759 pt))
760 {
761 REBARBANDINFO rbi;
762 UINT uBand;
763 RECT rc;
764
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);
773
774 uBand = (UINT)SendMessage(hWnd,
775 RB_IDTOINDEX,
776 (WPARAM)TbDocks->DraggingBandId,
777 0);
778
779 if (uBand != (UINT)-1 &&
780 SendMessage(hWnd,
781 RB_GETBANDINFO,
782 (WPARAM)uBand,
783 (LPARAM)&rbi))
784 {
785 MapWindowPoints(hWnd,
786 HWND_DESKTOP,
787 &pt,
788 1);
789
790 /* Check if the user is trying to drag it into another dock */
791 for (Position = TOP_DOCK; Position < NO_DOCK; Position++)
792 {
793 if (TbDocks->hRebar[Position] != NULL &&
794 TbDocks->hRebar[Position] != hWnd &&
795 GetWindowRect(TbDocks->hRebar[Position],
796 &rc))
797 {
798 InflateRect(&rc,
799 szTearOff.cx,
800 szTearOff.cy);
801
802 if (PtInRect(&rc,
803 pt))
804 {
805 DragTo = Position;
806 break;
807 }
808 }
809 }
810
811 /* Get the current dock */
812 for (Position = TOP_DOCK; Position < NO_DOCK; Position++)
813 {
814 if (TbDocks->hRebar[Position] == hWnd)
815 {
816 break;
817 }
818 }
819
820 ReleaseCapture();
821
822 if (SendMessage(hWnd,
823 RB_SHOWBAND,
824 (WPARAM)uBand,
825 FALSE))
826 {
827 /* Change the parent to the new rebar control */
828 if (TbDocks->Dragging->hWndClient != NULL)
829 {
830 SetWindowPos(TbDocks->Dragging->hWndClient,
831 NULL,
832 0,
833 0,
834 0,
835 0,
836 SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER);
837
838 SetParent(TbDocks->Dragging->hWndClient,
839 TbDocks->hRebar[DragTo]);
840
841 SetWindowPos(TbDocks->Dragging->hWndClient,
842 NULL,
843 0,
844 0,
845 0,
846 0,
847 SWP_NOSIZE | SWP_NOZORDER);
848 }
849
850 if (DragTo == NO_DOCK)
851 {
852 if (!TbdCreateToolbarWnd(TbDocks,
853 TbDocks->Dragging,
854 Position,
855 uBand,
856 &rbi,
857 pt,
858 hWnd,
859 uBand,
860 TRUE))
861 {
862 goto MoveFailed;
863 }
864 }
865 else
866 {
867 BOOL Moved = FALSE;
868
869 /* Remove the band from the current rebar control */
870 if (SendMessage(hWnd,
871 RB_DELETEBAND,
872 (WPARAM)uBand,
873 0))
874 {
875 UINT uIndex;
876
877 /* Calculate where to insert the new bar */
878 uIndex = TbdCalculateInsertIndex(TbDocks,
879 DragTo,
880 pt);
881
882 SetActiveWindow(TbDocks->hRebar[DragTo]);
883
884 TbDocks->Dragging->Callbacks->DockBand(TbDocks,
885 &TbDocks->Dragging->DockBar,
886 TbDocks->Dragging->Context,
887 Position,
888 DragTo,
889 &rbi);
890
891 if (rbi.fMask & RBBIM_CHILD)
892 TbDocks->Dragging->hWndClient = rbi.hwndChild;
893 else
894 TbDocks->Dragging->hWndClient = NULL;
895
896 /* Insert the toolbar into the new rebar */
897 rbi.fMask |= RBBIM_STYLE;
898 rbi.fStyle |= RBBS_HIDDEN;
899 if (SendMessage(TbDocks->hRebar[DragTo],
900 RB_INSERTBAND,
901 (WPARAM)uIndex,
902 (LPARAM)&rbi))
903 {
904 uBand = (UINT)SendMessage(TbDocks->hRebar[DragTo],
905 RB_IDTOINDEX,
906 (WPARAM)TbDocks->DraggingBandId,
907 0);
908
909 SendMessage(TbDocks->hRebar[DragTo],
910 RB_SHOWBAND,
911 (WPARAM)uBand,
912 TRUE);
913
914 /* Simulate a mouse click to continue dragging */
915 if (uBand != (UINT)-1 &&
916 TbDocks->Dragging->hWndClient != NULL &&
917 GetWindowRect(TbDocks->Dragging->hWndClient,
918 &rc))
919 {
920 switch (DragTo)
921 {
922 case LEFT_DOCK:
923 case RIGHT_DOCK:
924 pt.x = rc.left + ((rc.right - rc.left) / 2);
925 pt.y = rc.top - 1;
926 break;
927
928 default:
929 pt.x = rc.left - 1;
930 pt.y = rc.top + ((rc.bottom - rc.top) / 2);
931 break;
932 }
933
934 MapWindowPoints(HWND_DESKTOP,
935 TbDocks->hRebar[DragTo],
936 &pt,
937 1);
938
939 SetCursor(LoadCursor(NULL,
940 MAKEINTRESOURCE(IDC_SIZEALL)));
941
942 SendMessage(TbDocks->hRebar[DragTo],
943 WM_LBUTTONDOWN,
944 wParam,
945 MAKELPARAM(pt.x,
946 pt.y));
947
948 Moved = TRUE;
949 }
950 }
951 }
952
953 if (!Moved)
954 {
955 MoveFailed:
956 TbDocks->Dragging = NULL;
957
958 SendMessage(hWnd,
959 RB_SHOWBAND,
960 (WPARAM)uBand,
961 TRUE);
962 }
963 }
964 }
965 }
966 }
967 }
968 }
969
970 return Ret;
971 }
972
973 VOID
974 TbdHandleEnabling(PTOOLBAR_DOCKS TbDocks,
975 HWND hWnd,
976 BOOL Enable)
977 {
978 PDOCKBAR_ITEM Item;
979
980 Item = TbDocks->Items;
981 while (Item != NULL)
982 {
983 if (Item->hWndTool != NULL &&
984 Item->hWndTool != hWnd)
985 {
986 EnableWindow(Item->hWndTool,
987 Enable);
988 }
989 Item = Item->Next;
990 }
991 }
992
993 VOID
994 TbdHandleActivation(PTOOLBAR_DOCKS TbDocks,
995 HWND hWnd,
996 WPARAM *wParam,
997 LPARAM *lParam)
998 {
999 BOOL SynchronizeSiblings = TRUE;
1000 BOOL KeepActive = *(BOOL*)wParam;
1001 HWND hWndActivate = *(HWND*)lParam;
1002 PDOCKBAR_ITEM Item;
1003
1004 Item = TbDocks->Items;
1005 while (Item != NULL)
1006 {
1007 if (Item->hWndTool != NULL &&
1008 Item->hWndTool == hWndActivate)
1009 {
1010 KeepActive = TRUE;
1011 SynchronizeSiblings = FALSE;
1012 break;
1013 }
1014 Item = Item->Next;
1015 }
1016
1017 if (hWndActivate != (HWND)-1)
1018 {
1019 if (SynchronizeSiblings)
1020 {
1021 Item = TbDocks->Items;
1022 while (Item != NULL)
1023 {
1024 if (Item->hWndTool != NULL &&
1025 Item->hWndTool != hWnd &&
1026 Item->hWndTool != hWndActivate)
1027 {
1028 SendMessage(Item->hWndTool,
1029 WM_NCACTIVATE,
1030 (WPARAM)KeepActive,
1031 (LPARAM)-1);
1032 }
1033 Item = Item->Next;
1034 }
1035 }
1036 }
1037 else
1038 *lParam = 0;
1039
1040 *wParam = (WPARAM)KeepActive;
1041 }
1042
1043 VOID
1044 TbdShowFloatingToolbars(PTOOLBAR_DOCKS TbDocks,
1045 BOOL Show)
1046 {
1047 PDOCKBAR_ITEM Item;
1048
1049 Item = TbDocks->Items;
1050 while (Item != NULL)
1051 {
1052 if (Item->hWndTool != NULL)
1053 {
1054 if ((Show && !IsWindowVisible(Item->hWndTool)) ||
1055 (!Show && IsWindowVisible(Item->hWndTool)))
1056 {
1057 ShowWindow(Item->hWndTool,
1058 (Show ? SW_SHOW : SW_HIDE));
1059 }
1060 }
1061 Item = Item->Next;
1062 }
1063 }
1064
1065 VOID
1066 TbdInitializeDocks(PTOOLBAR_DOCKS TbDocks,
1067 HWND hWndParent,
1068 PVOID Context,
1069 PDOCKBAR_PARENTRESIZE ParentResizeProc)
1070 {
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;
1074
1075 DOCK_POSITION Position;
1076
1077 TbDocks->hParent = hWndParent;
1078 TbDocks->Context = Context;
1079 TbDocks->ParentResize = ParentResizeProc;
1080
1081 for (Position = TOP_DOCK; Position < NO_DOCK; Position++)
1082 {
1083 switch (Position)
1084 {
1085 case LEFT_DOCK:
1086 case RIGHT_DOCK:
1087 rbStyle |= CCS_VERT;
1088 break;
1089 default:
1090 rbStyle &= ~CCS_VERT;
1091 break;
1092 }
1093
1094 TbDocks->hRebar[Position] = CreateWindowEx(WS_EX_TOOLWINDOW,
1095 REBARCLASSNAME,
1096 NULL,
1097 rbStyle,
1098 0,
1099 0,
1100 0,
1101 0,
1102 TbDocks->hParent,
1103 NULL,
1104 hInstance,
1105 NULL);
1106
1107 if (TbDocks->hRebar[Position] != NULL)
1108 {
1109 SetWindowSubclass(TbDocks->hRebar[Position],
1110 RebarSubclassProc,
1111 1,
1112 (DWORD_PTR)TbDocks);
1113 }
1114 }
1115 }
1116
1117 BOOL
1118 TbdInitImpl(VOID)
1119 {
1120 WNDCLASSEX wc = {0};
1121
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,
1128 IDC_ARROW);
1129 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
1130 wc.lpszClassName = szToolDockWndClass;
1131
1132 return RegisterClassEx(&wc) != (ATOM)0;
1133 }
1134
1135 VOID
1136 TbdUninitImpl(VOID)
1137 {
1138 UnregisterClass(szToolDockWndClass,
1139 hInstance);
1140 }