Commit before breaking everything
[matches/honours.git] / research / transmission_spectroscopy / TOF / Win32++ / include / docking.h
1 // Win32++   Version 7.3\r
2 // Released: 30th November 2011\r
3 //\r
4 //      David Nash\r
5 //      email: [email protected]\r
6 //      url: https://sourceforge.net/projects/win32-framework\r
7 //\r
8 //\r
9 // Copyright (c) 2005-2011  David Nash\r
10 //\r
11 // Permission is hereby granted, free of charge, to\r
12 // any person obtaining a copy of this software and\r
13 // associated documentation files (the "Software"),\r
14 // to deal in the Software without restriction, including\r
15 // without limitation the rights to use, copy, modify,\r
16 // merge, publish, distribute, sublicense, and/or sell\r
17 // copies of the Software, and to permit persons to whom\r
18 // the Software is furnished to do so, subject to the\r
19 // following conditions:\r
20 //\r
21 // The above copyright notice and this permission notice\r
22 // shall be included in all copies or substantial portions\r
23 // of the Software.\r
24 //\r
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF\r
26 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\r
27 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\r
28 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\r
29 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
30 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
31 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
32 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE\r
33 // OR OTHER DEALINGS IN THE SOFTWARE.\r
34 //\r
35 ////////////////////////////////////////////////////////\r
36 \r
37 \r
38 ///////////////////////////////////////////////////////\r
39 // docking.h\r
40 //  Declaration of the CDocker class\r
41 \r
42 #ifndef _WIN32XX_DOCKING_H_\r
43 #define _WIN32XX_DOCKING_H_\r
44 \r
45 \r
46 #include "wincore.h"\r
47 #include "gdi.h"\r
48 #include "toolbar.h"\r
49 #include "tab.h"\r
50 #include "frame.h"\r
51 #include "default_resource.h"\r
52 \r
53 \r
54 // Docking Styles\r
55 #define DS_DOCKED_LEFT                  0x0001  // Dock the child left\r
56 #define DS_DOCKED_RIGHT                 0x0002  // Dock the child right\r
57 #define DS_DOCKED_TOP                   0x0004  // Dock the child top\r
58 #define DS_DOCKED_BOTTOM                0x0008  // Dock the child bottom\r
59 #define DS_NO_DOCKCHILD_LEFT    0x0010  // Prevent a child docking left\r
60 #define DS_NO_DOCKCHILD_RIGHT   0x0020  // Prevent a child docking right\r
61 #define DS_NO_DOCKCHILD_TOP             0x0040  // Prevent a child docking at the top\r
62 #define DS_NO_DOCKCHILD_BOTTOM  0x0080  // Prevent a child docking at the bottom\r
63 #define DS_NO_RESIZE                    0x0100  // Prevent resizing\r
64 #define DS_NO_CAPTION                   0x0200  // Prevent display of caption when docked\r
65 #define DS_NO_CLOSE                             0x0400  // Prevent closing of a docker while docked\r
66 #define DS_NO_UNDOCK                    0x0800  // Prevent undocking and dock closing\r
67 #define DS_CLIENTEDGE                   0x1000  // Has a 3D border when docked\r
68 #define DS_FIXED_RESIZE                 0x2000  // Perfomed a fixed resize instead of a proportional resize on dock children\r
69 #define DS_DOCKED_CONTAINER             0x4000  // Dock a container within a container\r
70 #define DS_DOCKED_LEFTMOST      0x10000 // Leftmost outer docking\r
71 #define DS_DOCKED_RIGHTMOST     0x20000 // Rightmost outer docking\r
72 #define DS_DOCKED_TOPMOST               0x40000 // Topmost outer docking\r
73 #define DS_DOCKED_BOTTOMMOST    0x80000 // Bottommost outer docking\r
74 \r
75 // Required for Dev-C++\r
76 #ifndef TME_NONCLIENT\r
77   #define TME_NONCLIENT 0x00000010\r
78 #endif\r
79 #ifndef TME_LEAVE\r
80   #define TME_LEAVE 0x000000002\r
81 #endif\r
82 #ifndef WM_NCMOUSELEAVE\r
83   #define WM_NCMOUSELEAVE 0x000002A2\r
84 #endif\r
85 \r
86 namespace Win32xx\r
87 {\r
88         // Class declarations\r
89         class CDockContainer;\r
90         class CDocker;\r
91 \r
92         typedef Shared_Ptr<CDocker> DockPtr;\r
93 \r
94         struct ContainerInfo\r
95         {\r
96                 TCHAR szTitle[MAX_MENU_STRING];\r
97                 int iImage;\r
98                 CDockContainer* pContainer;\r
99         };\r
100 \r
101         ///////////////////////////////////////\r
102         // Declaration of the CDockContainer class\r
103         //  A CDockContainer is a CTab window. A CTab has a view window, and optionally a toolbar control.\r
104         //  A top level CDockContainer can contain other CDockContainers. The view for each container\r
105         //  (including the top level container) along with possibly its toolbar, is displayed\r
106         //  within the container parent's view page.\r
107         class CDockContainer : public CTab\r
108         {\r
109         public:\r
110 \r
111                 // Nested class. This is the Wnd for the window displayed over the client area\r
112                 // of the tab control.  The toolbar and view window are child windows of the\r
113                 // viewpage window. Only the ViewPage of the parent CDockContainer is displayed. It's\r
114                 // contents are updated with the view window of the relevant container whenever\r
115                 // a different tab is selected.\r
116                 class CViewPage : public CWnd\r
117                 {\r
118 \r
119                 public:\r
120                         CViewPage() : m_pView(NULL), m_pTab(NULL) {}\r
121                         virtual ~CViewPage() {}\r
122                         virtual CToolBar& GetToolBar() const {return (CToolBar&)m_ToolBar;}\r
123                         virtual CWnd* GetView() const   {return m_pView;}\r
124                         virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);\r
125                         virtual void OnCreate();\r
126                         virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);\r
127                         virtual void PreRegisterClass(WNDCLASS &wc);\r
128                         virtual void RecalcLayout();\r
129                         virtual void SetView(CWnd& wndView);\r
130                         virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
131 \r
132                         CWnd* GetTabCtrl() const { return m_pTab;}\r
133 \r
134                 private:\r
135                         CToolBar m_ToolBar;\r
136                         CString m_strTooltip;\r
137                         CWnd* m_pView;\r
138                         CWnd* m_pTab;\r
139                 };\r
140 \r
141         public:\r
142                 CDockContainer();\r
143                 virtual ~CDockContainer();\r
144                 virtual void AddContainer(CDockContainer* pContainer);\r
145                 virtual void AddToolBarButton(UINT nID, BOOL bEnabled = TRUE);\r
146                 virtual CDockContainer* GetContainerFromIndex(UINT nPage);\r
147                 virtual CDockContainer* GetContainerFromView(CWnd* pView) const;\r
148                 virtual int GetContainerIndex(CDockContainer* pContainer);\r
149                 virtual SIZE GetMaxTabTextSize();\r
150                 virtual CViewPage& GetViewPage() const  { return (CViewPage&)m_ViewPage; }\r
151                 virtual void RecalcLayout();\r
152                 virtual void RemoveContainer(CDockContainer* pWnd);\r
153                 virtual void SelectPage(int nPage);\r
154                 virtual void SetTabSize();\r
155                 virtual void SetupToolBar();\r
156 \r
157                 // Attributes\r
158                 CDockContainer* GetActiveContainer() const {return GetContainerFromView(GetActiveView());}\r
159                 CWnd* GetActiveView() const;\r
160                 std::vector<ContainerInfo>& GetAllContainers() const {return m_pContainerParent->m_vContainerInfo;}\r
161                 CDockContainer* GetContainerParent() const { return m_pContainerParent; }\r
162                 CString& GetDockCaption() const { return (CString&)m_csCaption; }\r
163                 HICON GetTabIcon() const                { return m_hTabIcon; }\r
164                 LPCTSTR GetTabText() const              { return m_strTabText; }\r
165                 virtual CToolBar& GetToolBar() const    { return GetViewPage().GetToolBar(); }\r
166                 CWnd* GetView() const                   { return GetViewPage().GetView(); }\r
167                 void SetActiveContainer(CDockContainer* pContainer);\r
168                 void SetDockCaption(LPCTSTR szCaption) { m_csCaption = szCaption; }\r
169                 void SetTabIcon(HICON hTabIcon) { m_hTabIcon = hTabIcon; }\r
170                 void SetTabIcon(UINT nID_Icon);\r
171                 void SetTabIcon(int i, HICON hIcon) { CTab::SetTabIcon(i, hIcon); }\r
172                 void SetTabText(LPCTSTR szText) { m_strTabText = szText; }\r
173                 void SetTabText(UINT nTab, LPCTSTR szText);\r
174                 void SetView(CWnd& Wnd);\r
175 \r
176         protected:\r
177                 virtual void OnCreate();\r
178                 virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);\r
179                 virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);\r
180                 virtual void OnMouseLeave(WPARAM wParam, LPARAM lParam);\r
181                 virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);\r
182                 virtual void PreCreate(CREATESTRUCT &cs);\r
183                 virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
184 \r
185         private:\r
186                 std::vector<ContainerInfo> m_vContainerInfo;\r
187                 CString m_strTabText;\r
188                 CString m_csCaption;\r
189                 CViewPage m_ViewPage;\r
190                 int m_iCurrentPage;\r
191                 CDockContainer* m_pContainerParent;\r
192                 HICON m_hTabIcon;\r
193                 int m_nTabPressed;\r
194 \r
195         };\r
196 \r
197         typedef struct DRAGPOS\r
198         {\r
199                 NMHDR hdr;\r
200                 POINT ptPos;\r
201                 UINT DockZone;\r
202         } *LPDRAGPOS;\r
203 \r
204 \r
205         /////////////////////////////////////////\r
206         // Declaration of the CDocker class\r
207         //  A CDocker window allows other CDocker windows to be "docked" inside it.\r
208         //  A CDocker can dock on the top, left, right or bottom side of a parent CDocker.\r
209         //  There is no theoretical limit to the number of CDockers within CDockers.\r
210         class CDocker : public CWnd\r
211         {\r
212         public:\r
213                 //  A nested class for the splitter bar that seperates the docked panes.\r
214                 class CDockBar : public CWnd\r
215                 {\r
216                 public:\r
217                         CDockBar();\r
218                         virtual ~CDockBar();\r
219                         virtual void OnDraw(CDC* pDC);\r
220                         virtual void PreCreate(CREATESTRUCT &cs);\r
221                         virtual void PreRegisterClass(WNDCLASS& wc);\r
222                         virtual void SendNotify(UINT nMessageID);\r
223                         virtual void SetColor(COLORREF color);\r
224                         virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
225 \r
226                         CDocker* GetDock()                              {return m_pDock;}\r
227                         int GetWidth()                                  {return m_DockBarWidth;}\r
228                         void SetDock(CDocker* pDock)    {m_pDock = pDock;}\r
229                         void SetWidth(int nWidth)               {m_DockBarWidth = nWidth;}\r
230 \r
231                 private:\r
232                         CDockBar(const CDockBar&);                              // Disable copy construction\r
233                         CDockBar& operator = (const CDockBar&); // Disable assignment operator\r
234 \r
235                         CDocker* m_pDock;\r
236                         DRAGPOS m_DragPos;\r
237                         CBrush m_brBackground;\r
238                         int m_DockBarWidth;\r
239                 };\r
240 \r
241                 //  A nested class for the window inside a CDocker which includes all of this docked client.\r
242                 //  It's the remaining part of the CDocker that doesn't belong to the CDocker's children.\r
243                 //  The Docker's view window is a child window of CDockClient.\r
244                 class CDockClient : public CWnd\r
245                 {\r
246                 public:\r
247                         CDockClient();\r
248                         virtual ~CDockClient() {}\r
249                         virtual void Draw3DBorder(RECT& Rect);\r
250                         virtual void DrawCaption(WPARAM wParam);\r
251                         virtual void DrawCloseButton(CDC& DrawDC, BOOL bFocus);\r
252                         virtual CRect GetCloseRect();\r
253                         virtual void SendNotify(UINT nMessageID);\r
254 \r
255                         CString& GetCaption() const             { return (CString&)m_csCaption; }\r
256                         CWnd* GetView() const                   { return m_pView; }\r
257                         void SetDock(CDocker* pDock)    { m_pDock = pDock;}\r
258                         void SetCaption(LPCTSTR szCaption) { m_csCaption = szCaption; }\r
259                         void SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2);\r
260                         void SetClosePressed()                  { m_IsClosePressed = TRUE; }\r
261                         void SetView(CWnd& Wnd)                 { m_pView = &Wnd; }\r
262 \r
263                 protected:\r
264                         virtual void    OnLButtonDown(WPARAM wParam, LPARAM lParam);\r
265                         virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);\r
266                         virtual void    OnMouseActivate(WPARAM wParam, LPARAM lParam);\r
267                         virtual void    OnMouseMove(WPARAM wParam, LPARAM lParam);\r
268                         virtual void    OnNCCalcSize(WPARAM& wParam, LPARAM& lParam);\r
269                         virtual LRESULT OnNCHitTest(WPARAM wParam, LPARAM lParam);\r
270                         virtual LRESULT OnNCLButtonDown(WPARAM wParam, LPARAM lParam);\r
271                         virtual void    OnNCMouseLeave(WPARAM wParam, LPARAM lParam);\r
272                         virtual LRESULT OnNCMouseMove(WPARAM wParam, LPARAM lParam);\r
273                         virtual LRESULT OnNCPaint(WPARAM wParam, LPARAM lParam);\r
274                         virtual void    OnWindowPosChanged(WPARAM wParam, LPARAM lParam);\r
275                         virtual void    PreRegisterClass(WNDCLASS& wc);\r
276                         virtual void    PreCreate(CREATESTRUCT& cs);\r
277                         virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
278 \r
279                 private:\r
280                         CDockClient(const CDockClient&);                                // Disable copy construction\r
281                         CDockClient& operator = (const CDockClient&); // Disable assignment operator\r
282 \r
283                         CString m_csCaption;\r
284                         CPoint m_Oldpt;\r
285                         CDocker* m_pDock;\r
286                         CWnd* m_pView;\r
287                         BOOL m_IsClosePressed;\r
288                         BOOL m_bOldFocus;\r
289                         BOOL m_bCaptionPressed;\r
290                         BOOL m_IsTracking;\r
291                         COLORREF m_Foregnd1;\r
292                         COLORREF m_Backgnd1;\r
293                         COLORREF m_Foregnd2;\r
294                         COLORREF m_Backgnd2;\r
295                 };\r
296 \r
297                 //  This nested class is used to indicate where a window could dock by\r
298                 //  displaying a blue tinted window.\r
299                 class CDockHint : public CWnd\r
300                 {\r
301                 public:\r
302                         CDockHint();\r
303                         virtual ~CDockHint();\r
304                         virtual RECT CalcHintRectContainer(CDocker* pDockTarget);\r
305                         virtual RECT CalcHintRectInner(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide);\r
306                         virtual RECT CalcHintRectOuter(CDocker* pDockDrag, UINT uDockSide);\r
307                         virtual void DisplayHint(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide);\r
308                         virtual void OnDraw(CDC* pDC);\r
309                         virtual void PreCreate(CREATESTRUCT &cs);\r
310                         virtual void ShowHintWindow(CDocker* pDockTarget, CRect rcHint);\r
311 \r
312                 private:\r
313                         CDockHint(const CDockHint&);                            // Disable copy construction\r
314                         CDockHint& operator = (const CDockHint&); // Disable assignment operator\r
315 \r
316                         CBitmap m_bmBlueTint;\r
317                         UINT m_uDockSideOld;\r
318                 };\r
319 \r
320                 class CTarget : public CWnd\r
321                 {\r
322                 public:\r
323                         CTarget() {}\r
324                         virtual ~CTarget();\r
325                         virtual void OnDraw(CDC* pDC);\r
326                         virtual void PreCreate(CREATESTRUCT &cs);\r
327 \r
328                 protected:\r
329                         CBitmap m_bmImage;\r
330 \r
331                 private:\r
332                         CTarget(const CTarget&);                                // Disable copy construction\r
333                         CTarget& operator = (const CTarget&); // Disable assignment operator\r
334                 };\r
335 \r
336                 class CTargetCentre : public CTarget\r
337                 {\r
338                 public:\r
339                         CTargetCentre();\r
340                         virtual ~CTargetCentre();\r
341                         virtual void OnDraw(CDC* pDC);\r
342                         virtual void OnCreate();\r
343                         virtual BOOL CheckTarget(LPDRAGPOS pDragPos);\r
344                         BOOL IsOverContainer() { return m_bIsOverContainer; }\r
345 \r
346                 private:\r
347                         CTargetCentre(const CTargetCentre&);                            // Disable copy construction\r
348                         CTargetCentre& operator = (const CTargetCentre&); // Disable assignment operator\r
349 \r
350                         BOOL m_bIsOverContainer;\r
351                         CDocker* m_pOldDockTarget;\r
352                 };\r
353 \r
354                 class CTargetLeft : public CTarget\r
355                 {\r
356                 public:\r
357                         CTargetLeft() {m_bmImage.LoadImage(IDW_SDLEFT,0,0,0);}\r
358                         virtual BOOL CheckTarget(LPDRAGPOS pDragPos);\r
359 \r
360                 private:\r
361                         CTargetLeft(const CTargetLeft&);                                // Disable copy construction\r
362                         CTargetLeft& operator = (const CTargetLeft&); // Disable assignment operator\r
363                 };\r
364 \r
365                 class CTargetTop : public CTarget\r
366                 {\r
367                 public:\r
368                         CTargetTop() {m_bmImage.LoadImage(IDW_SDTOP,0,0,0);}\r
369                         virtual BOOL CheckTarget(LPDRAGPOS pDragPos);\r
370                 private:\r
371                         CTargetTop(const CTargetTop&);                          // Disable copy construction\r
372                         CTargetTop& operator = (const CTargetTop&); // Disable assignment operator\r
373                 };\r
374 \r
375                 class CTargetRight : public CTarget\r
376                 {\r
377                 public:\r
378                         CTargetRight() {m_bmImage.LoadImage(IDW_SDRIGHT,0,0,0);}\r
379                         virtual BOOL CheckTarget(LPDRAGPOS pDragPos);\r
380 \r
381                 private:\r
382                         CTargetRight(const CTargetRight&);                              // Disable copy construction\r
383                         CTargetRight& operator = (const CTargetRight&); // Disable assignment operator\r
384                 };\r
385 \r
386                 class CTargetBottom : public CTarget\r
387                 {\r
388                 public:\r
389                         CTargetBottom() {m_bmImage.LoadImage(IDW_SDBOTTOM,0,0,0);}\r
390                         virtual BOOL CheckTarget(LPDRAGPOS pDragPos);\r
391                 };\r
392 \r
393                 friend class CTargetCentre;\r
394                 friend class CTargetLeft;\r
395                 friend class CTargetTop;\r
396                 friend class CTargetRight;\r
397                 friend class CTargetBottom;\r
398                 friend class CDockClient;\r
399                 friend class CDockContainer;\r
400 \r
401         public:\r
402                 // Operations\r
403                 CDocker();\r
404                 virtual ~CDocker();\r
405                 virtual CDocker* AddDockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, int nDockID = 0);\r
406                 virtual CDocker* AddUndockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, RECT rc, int nDockID = 0);\r
407                 virtual void Close();\r
408                 virtual void CloseAllDockers();\r
409                 virtual void Dock(CDocker* pDocker, UINT uDockSide);\r
410                 virtual void DockInContainer(CDocker* pDock, DWORD dwDockStyle);\r
411                 virtual CDockContainer* GetContainer() const;\r
412                 virtual CDocker* GetActiveDocker() const;\r
413                 virtual CDocker* GetDockAncestor() const;\r
414                 virtual CDocker* GetDockFromID(int n_DockID) const;\r
415                 virtual CDocker* GetDockFromPoint(POINT pt) const;\r
416                 virtual CDocker* GetDockFromView(CWnd* pView) const;\r
417                 virtual CDocker* GetTopmostDocker() const;\r
418                 virtual int GetDockSize() const;\r
419                 virtual CTabbedMDI* GetTabbedMDI() const;\r
420                 virtual int GetTextHeight();\r
421                 virtual void Hide();\r
422                 virtual BOOL LoadRegistrySettings(LPCTSTR szRegistryKeyName);\r
423                 virtual void RecalcDockLayout();\r
424                 virtual BOOL SaveRegistrySettings(LPCTSTR szRegistryKeyName);\r
425                 virtual void Undock(CPoint pt, BOOL bShowUndocked = TRUE);\r
426                 virtual void UndockContainer(CDockContainer* pContainer, CPoint pt, BOOL bShowUndocked);\r
427                 virtual BOOL VerifyDockers();\r
428 \r
429                 // Attributes\r
430                 virtual CDockBar& GetDockBar() const {return (CDockBar&)m_DockBar;}\r
431                 virtual CDockClient& GetDockClient() const {return (CDockClient&)m_DockClient;}\r
432                 virtual CDockHint& GetDockHint() const {return m_pDockAncestor->m_DockHint;}\r
433 \r
434 \r
435                 std::vector <DockPtr> & GetAllDockers() const {return GetDockAncestor()->m_vAllDockers;}\r
436                 int GetBarWidth() const {return GetDockBar().GetWidth();}\r
437                 CString& GetCaption() const {return GetDockClient().GetCaption();}\r
438                 std::vector <CDocker*> & GetDockChildren() const {return (std::vector <CDocker*> &)m_vDockChildren;}\r
439                 int GetDockID() const {return m_nDockID;}\r
440                 CDocker* GetDockParent() const {return m_pDockParent;}\r
441                 DWORD GetDockStyle() const {return m_DockStyle;}\r
442                 CWnd* GetView() const {return GetDockClient().GetView();}\r
443                 BOOL IsChildOfDocker(CWnd* pWnd) const;\r
444                 BOOL IsDocked() const;\r
445                 BOOL IsDragAutoResize();\r
446                 BOOL IsRelated(CWnd* pWnd) const;\r
447                 BOOL IsUndocked() const;\r
448                 void SetBarColor(COLORREF color) {GetDockBar().SetColor(color);}\r
449                 void SetBarWidth(int nWidth) {GetDockBar().SetWidth(nWidth);}\r
450                 void SetCaption(LPCTSTR szCaption);\r
451                 void SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2);\r
452                 void SetCaptionHeight(int nHeight);\r
453                 void SetDockStyle(DWORD dwDockStyle);\r
454                 void SetDockSize(int DockSize);\r
455                 void SetDragAutoResize(BOOL bAutoResize);\r
456                 void SetView(CWnd& wndView);\r
457 \r
458         protected:\r
459                 virtual CDocker* NewDockerFromID(int idDock);\r
460                 virtual void OnActivate(WPARAM wParam, LPARAM lParam);\r
461                 virtual void OnCaptionTimer(WPARAM wParam, LPARAM lParam);\r
462                 virtual void OnCreate();\r
463                 virtual void OnDestroy(WPARAM wParam, LPARAM lParam);\r
464                 virtual void OnDockDestroyed(WPARAM wParam, LPARAM lParam);\r
465                 virtual void OnExitSizeMove(WPARAM wParam, LPARAM lParam);\r
466                 virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);\r
467                 virtual void OnSetFocus(WPARAM wParam, LPARAM lParam);\r
468                 virtual void OnSysColorChange(WPARAM wParam, LPARAM lParam);\r
469                 virtual LRESULT OnSysCommand(WPARAM wParam, LPARAM lParam);\r
470                 virtual LRESULT OnWindowPosChanging(WPARAM wParam, LPARAM lParam);\r
471                 virtual void OnWindowPosChanged(WPARAM wParam, LPARAM lParam);\r
472                 virtual void PreCreate(CREATESTRUCT &cs);\r
473                 virtual void PreRegisterClass(WNDCLASS &wc);\r
474                 virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
475 \r
476         private:\r
477                 CDocker(const CDocker&);                                // Disable copy construction\r
478                 CDocker& operator = (const CDocker&);   // Disable assignment operator\r
479                 void CheckAllTargets(LPDRAGPOS pDragPos);\r
480                 void CloseAllTargets();\r
481                 void DockOuter(CDocker* pDocker, DWORD dwDockStyle);\r
482                 void DrawAllCaptions();\r
483                 void DrawHashBar(HWND hBar, POINT Pos);\r
484                 void ConvertToChild(HWND hWndParent);\r
485                 void ConvertToPopup(RECT rc);\r
486                 void MoveDockChildren(CDocker* pDockTarget);\r
487                 void PromoteFirstChild();\r
488                 void RecalcDockChildLayout(CRect rc);\r
489                 void ResizeDockers(LPDRAGPOS pdp);\r
490                 CDocker* SeparateFromDock();\r
491                 void SendNotify(UINT nMessageID);\r
492                 void SetUndockPosition(CPoint pt);\r
493                 std::vector<CDocker*> SortDockers();\r
494 \r
495                 CDockBar                m_DockBar;\r
496                 CDockHint               m_DockHint;\r
497                 CDockClient             m_DockClient;\r
498                 CTargetCentre   m_TargetCentre;\r
499                 CTargetLeft             m_TargetLeft;\r
500                 CTargetTop              m_TargetTop;\r
501                 CTargetRight    m_TargetRight;\r
502                 CPoint                  m_OldPoint;\r
503                 CTargetBottom   m_TargetBottom;\r
504                 CDocker*                m_pDockParent;\r
505                 CDocker*                m_pDockAncestor;\r
506                 CDocker*                m_pDockActive;\r
507 \r
508                 std::vector <CDocker*> m_vDockChildren;\r
509                 std::vector <DockPtr> m_vAllDockers;    // Only used in DockAncestor\r
510 \r
511                 CRect m_rcBar;\r
512                 CRect m_rcChild;\r
513 \r
514                 BOOL m_BlockMove;\r
515                 BOOL m_Undocking;\r
516                 BOOL m_bIsClosing;\r
517                 BOOL m_bIsDragging;\r
518                 BOOL m_bDragAutoResize;\r
519                 int m_DockStartSize;\r
520                 int m_nDockID;\r
521                 int m_nTimerCount;\r
522                 int m_NCHeight;\r
523                 DWORD m_dwDockZone;\r
524                 double m_DockSizeRatio;\r
525                 DWORD m_DockStyle;\r
526                 HWND m_hOldFocus;\r
527 \r
528         }; // class CDocker\r
529 \r
530         struct DockInfo\r
531         {\r
532                 DWORD DockStyle;\r
533                 int DockSize;\r
534                 int DockID;\r
535                 int DockParentID;\r
536                 RECT Rect;\r
537         };\r
538 \r
539 }\r
540 \r
541 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
542 \r
543 namespace Win32xx\r
544 {\r
545 \r
546         /////////////////////////////////////////////////////////////\r
547         // Definitions for the CDockBar class nested within CDocker\r
548         //\r
549         inline CDocker::CDockBar::CDockBar() : m_pDock(NULL), m_DockBarWidth(4)\r
550         {\r
551                 m_brBackground.CreateSolidBrush(RGB(192,192,192));\r
552         }\r
553 \r
554         inline CDocker::CDockBar::~CDockBar()\r
555         {\r
556         }\r
557 \r
558         inline void CDocker::CDockBar::OnDraw(CDC* pDC)\r
559         {\r
560                 CRect rcClient = GetClientRect();\r
561                 ::SelectObject(*pDC, m_brBackground);\r
562                 pDC->PatBlt(0, 0, rcClient.Width(), rcClient.Height(), PATCOPY);\r
563         }\r
564 \r
565         inline void CDocker::CDockBar::PreCreate(CREATESTRUCT &cs)\r
566         {\r
567                 // Create a child window, initially hidden\r
568                 cs.style = WS_CHILD;\r
569         }\r
570 \r
571         inline void CDocker::CDockBar::PreRegisterClass(WNDCLASS& wc)\r
572         {\r
573                 wc.lpszClassName = _T("Win32++ Bar");\r
574                 wc.hbrBackground = m_brBackground;\r
575         }\r
576 \r
577         inline void CDocker::CDockBar::SendNotify(UINT nMessageID)\r
578         {\r
579                 // Send a splitter bar notification to the parent\r
580                 m_DragPos.hdr.code = nMessageID;\r
581                 m_DragPos.hdr.hwndFrom = m_hWnd;\r
582                 m_DragPos.ptPos = GetCursorPos();\r
583                 m_DragPos.ptPos.x += 1;\r
584                 GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&m_DragPos);\r
585         }\r
586 \r
587         inline void CDocker::CDockBar::SetColor(COLORREF color)\r
588         {\r
589                 // Useful colors:\r
590                 // GetSysColor(COLOR_BTNFACE)   // Default Grey\r
591                 // RGB(196, 215, 250)                   // Default Blue\r
592 \r
593                 m_brBackground.CreateSolidBrush(color);\r
594         }\r
595 \r
596         inline LRESULT CDocker::CDockBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
597         {\r
598                 {\r
599                         switch (uMsg)\r
600                         {\r
601                         case WM_SETCURSOR:\r
602                                 {\r
603                                         if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE))\r
604                                         {\r
605                                                 HCURSOR hCursor;\r
606                                                 DWORD dwSide = GetDock()->GetDockStyle() & 0xF;\r
607                                                 if ((dwSide == DS_DOCKED_LEFT) || (dwSide == DS_DOCKED_RIGHT))\r
608                                                         hCursor = LoadCursor(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_SPLITH));\r
609                                                 else\r
610                                                         hCursor = LoadCursor(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_SPLITV));\r
611 \r
612                                                 if (hCursor) SetCursor(hCursor);\r
613                                                 else TRACE(_T("**WARNING** Missing cursor resource for slider bar\n"));\r
614 \r
615                                                 return TRUE;\r
616                                         }\r
617                                         else\r
618                                                 SetCursor(LoadCursor(NULL, IDC_ARROW));\r
619                                 }\r
620                                 break;\r
621 \r
622                         case WM_ERASEBKGND:\r
623                                 return 0;\r
624 \r
625                         case WM_LBUTTONDOWN:\r
626                                 {\r
627                                         if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE))\r
628                                         {\r
629                                                 SendNotify(UWM_BAR_START);\r
630                                                 SetCapture();\r
631                                         }\r
632                                 }\r
633                                 break;\r
634 \r
635                         case WM_LBUTTONUP:\r
636                                 if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE) && (GetCapture() == this))\r
637                                 {\r
638                                         SendNotify(UWM_BAR_END);\r
639                                         ReleaseCapture();\r
640                                 }\r
641                                 break;\r
642 \r
643                         case WM_MOUSEMOVE:\r
644                                 if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE) && (GetCapture() == this))\r
645                                 {\r
646                                         SendNotify(UWM_BAR_MOVE);\r
647                                 }\r
648                                 break;\r
649                         }\r
650                 }\r
651 \r
652                 // pass unhandled messages on for default processing\r
653                 return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
654         }\r
655 \r
656 \r
657         ////////////////////////////////////////////////////////////////\r
658         // Definitions for the CDockClient class nested within CDocker\r
659         //\r
660         inline CDocker::CDockClient::CDockClient() : m_pView(0), m_IsClosePressed(FALSE),\r
661                                                 m_bOldFocus(FALSE), m_bCaptionPressed(FALSE), m_IsTracking(FALSE)\r
662         {\r
663                 m_Foregnd1 = RGB(32,32,32);\r
664                 m_Backgnd1 = RGB(190,207,227);\r
665                 m_Foregnd2 =  GetSysColor(COLOR_BTNTEXT);\r
666                 m_Backgnd2 = GetSysColor(COLOR_BTNFACE);\r
667         }\r
668 \r
669         inline void CDocker::CDockClient::Draw3DBorder(RECT& Rect)\r
670         {\r
671                 // Imitates the drawing of the WS_EX_CLIENTEDGE extended style\r
672                 // This draws a 2 pixel border around the specified Rect\r
673                 CWindowDC dc(this);\r
674                 CRect rcw = Rect;\r
675                 dc.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));\r
676                 dc.MoveTo(0, rcw.Height());\r
677                 dc.LineTo(0, 0);\r
678                 dc.LineTo(rcw.Width(), 0);\r
679                 dc.CreatePen(PS_SOLID,1, GetSysColor(COLOR_3DDKSHADOW));\r
680                 dc.MoveTo(1, rcw.Height()-2);\r
681                 dc.LineTo(1, 1);\r
682                 dc.LineTo(rcw.Width()-2, 1);\r
683                 dc.CreatePen(PS_SOLID,1, GetSysColor(COLOR_3DHILIGHT));\r
684                 dc.MoveTo(rcw.Width()-1, 0);\r
685                 dc.LineTo(rcw.Width()-1, rcw.Height()-1);\r
686                 dc.LineTo(0, rcw.Height()-1);\r
687                 dc.CreatePen(PS_SOLID,1, GetSysColor(COLOR_3DLIGHT));\r
688                 dc.MoveTo(rcw.Width()-2, 1);\r
689                 dc.LineTo(rcw.Width()-2, rcw.Height()-2);\r
690                 dc.LineTo(1, rcw.Height()-2);\r
691         }\r
692 \r
693         inline CRect CDocker::CDockClient::GetCloseRect()\r
694         {\r
695                 // Calculate the close rect position in screen co-ordinates\r
696                 CRect rcClose;\r
697 \r
698                 int gap = 4;\r
699                 CRect rc = GetWindowRect();\r
700                 int cx = GetSystemMetrics(SM_CXSMICON);\r
701                 int cy = GetSystemMetrics(SM_CYSMICON);\r
702 \r
703                 rcClose.top = 2 + rc.top + m_pDock->m_NCHeight/2 - cy/2;\r
704                 rcClose.bottom = 2 + rc.top + m_pDock->m_NCHeight/2 + cy/2;\r
705                 rcClose.right = rc.right - gap;\r
706                 rcClose.left = rcClose.right - cx;\r
707 \r
708 #if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)\r
709                 if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)\r
710                 {\r
711                         rcClose.left = rc.left + gap;\r
712                         rcClose.right = rcClose.left + cx;\r
713                 }\r
714 #endif\r
715 \r
716 \r
717                 return rcClose;\r
718         }\r
719 \r
720         inline void CDocker::CDockClient::DrawCaption(WPARAM wParam)\r
721         {\r
722                 if (IsWindow() && m_pDock->IsDocked() && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))\r
723                 {\r
724                         BOOL bFocus = m_pDock->IsChildOfDocker(GetFocus());\r
725                         m_bOldFocus = FALSE;\r
726 \r
727                         // Acquire the DC for our NonClient painting\r
728                         CDC* pDC;\r
729                         if ((wParam != 1) && (bFocus == m_bOldFocus))\r
730                                 pDC = GetDCEx((HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN|DCX_PARENTCLIP);\r
731                         else\r
732                                 pDC     = GetWindowDC();\r
733 \r
734                         // Create and set up our memory DC\r
735                         CRect rc = GetWindowRect();\r
736                         CMemDC dcMem(pDC);\r
737                         int rcAdjust = (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)? 2 : 0;\r
738                         int Width = MAX(rc.Width() -rcAdjust, 0);\r
739                         int Height = m_pDock->m_NCHeight + rcAdjust;\r
740                         dcMem.CreateCompatibleBitmap(pDC, Width, Height);\r
741                         m_bOldFocus = bFocus;\r
742 \r
743                         // Set the font for the title\r
744                         NONCLIENTMETRICS info = {0};\r
745                         info.cbSize = GetSizeofNonClientMetrics();\r
746                         SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);\r
747                         dcMem.CreateFontIndirect(&info.lfStatusFont);\r
748 \r
749                         // Set the Colours\r
750                         if (bFocus)\r
751                         {\r
752                                 dcMem.SetTextColor(m_Foregnd1);\r
753                                 dcMem.CreateSolidBrush(m_Backgnd1);\r
754                                 dcMem.SetBkColor(m_Backgnd1);\r
755                         }\r
756                         else\r
757                         {\r
758                                 dcMem.SetTextColor(m_Foregnd2);\r
759                                 dcMem.CreateSolidBrush(m_Backgnd2);\r
760                                 dcMem.SetBkColor(m_Backgnd2);\r
761                         }\r
762 \r
763                         // Draw the rectangle\r
764                         dcMem.CreatePen(PS_SOLID, 1, RGB(160, 150, 140));\r
765                         dcMem.Rectangle(rcAdjust, rcAdjust, rc.Width() -rcAdjust, m_pDock->m_NCHeight +rcAdjust);\r
766 \r
767                         // Display the caption\r
768                         int cx = (m_pDock->GetDockStyle() & DS_NO_CLOSE)? 0 : GetSystemMetrics(SM_CXSMICON);\r
769                         CRect rcText(4 +rcAdjust, rcAdjust, rc.Width() -4 - cx -rcAdjust, m_pDock->m_NCHeight +rcAdjust);\r
770                         dcMem.DrawText(m_csCaption, m_csCaption.GetLength(), rcText, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);\r
771 \r
772                         // Draw the close button\r
773                         if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))\r
774                                 DrawCloseButton(dcMem, bFocus);\r
775 \r
776                         // Draw the 3D border\r
777                         if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)\r
778                                 Draw3DBorder(rc);\r
779 \r
780                         // Copy the Memory DC to the window's DC\r
781                         pDC->BitBlt(rcAdjust, rcAdjust, Width, Height, &dcMem, rcAdjust, rcAdjust, SRCCOPY);\r
782 \r
783                         // Required for Win98/WinME\r
784                         pDC->Destroy();\r
785                 }\r
786         }\r
787 \r
788         inline void CDocker::CDockClient::DrawCloseButton(CDC& DrawDC, BOOL bFocus)\r
789         {\r
790                 // The close button isn't displayed on Win95\r
791                 if (GetWinVersion() == 1400)  return;\r
792 \r
793                 if (m_pDock->IsDocked() && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))\r
794                 {\r
795                         // Determine the close button's drawing position relative to the window\r
796                         CRect rcClose = GetCloseRect();\r
797                         UINT uState = GetCloseRect().PtInRect(GetCursorPos())? m_IsClosePressed && IsLeftButtonDown()? 2 : 1 : 0;\r
798                         ScreenToClient(rcClose);\r
799 \r
800                         if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)\r
801                         {\r
802                                 rcClose.OffsetRect(2, m_pDock->m_NCHeight+2);\r
803                                 if (GetWindowRect().Height() < (m_pDock->m_NCHeight+4))\r
804                                         rcClose.OffsetRect(-2, -2);\r
805                         }\r
806                         else\r
807                                 rcClose.OffsetRect(0, m_pDock->m_NCHeight-2);\r
808 \r
809                         // Draw the outer highlight for the close button\r
810                         if (!IsRectEmpty(&rcClose))\r
811                         {\r
812                                 switch (uState)\r
813                                 {\r
814                                 case 0:\r
815                                         {\r
816                                                 // Normal button\r
817                                                 DrawDC.CreatePen(PS_SOLID, 1, RGB(232, 228, 220));\r
818                                                 DrawDC.MoveTo(rcClose.left, rcClose.bottom);\r
819                                                 DrawDC.LineTo(rcClose.right, rcClose.bottom);\r
820                                                 DrawDC.LineTo(rcClose.right, rcClose.top);\r
821                                                 DrawDC.LineTo(rcClose.left, rcClose.top);\r
822                                                 DrawDC.LineTo(rcClose.left, rcClose.bottom);\r
823                                                 break;\r
824                                         }\r
825 \r
826                                 case 1:\r
827                                         {\r
828                                                 // Popped up button\r
829                                                 // Draw outline, white at top, black on bottom\r
830                                                 DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));\r
831                                                 DrawDC.MoveTo(rcClose.left, rcClose.bottom);\r
832                                                 DrawDC.LineTo(rcClose.right, rcClose.bottom);\r
833                                                 DrawDC.LineTo(rcClose.right, rcClose.top);\r
834                                                 DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));\r
835                                                 DrawDC.LineTo(rcClose.left, rcClose.top);\r
836                                                 DrawDC.LineTo(rcClose.left, rcClose.bottom);\r
837                                         }\r
838 \r
839                                         break;\r
840                                 case 2:\r
841                                         {\r
842                                                 // Pressed button\r
843                                                 // Draw outline, black on top, white on bottom\r
844                                                 DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));\r
845                                                 DrawDC.MoveTo(rcClose.left, rcClose.bottom);\r
846                                                 DrawDC.LineTo(rcClose.right, rcClose.bottom);\r
847                                                 DrawDC.LineTo(rcClose.right, rcClose.top);\r
848                                                 DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));\r
849                                                 DrawDC.LineTo(rcClose.left, rcClose.top);\r
850                                                 DrawDC.LineTo(rcClose.left, rcClose.bottom);\r
851                                         }\r
852                                         break;\r
853                                 }\r
854 \r
855                                 // Manually Draw Close Button\r
856                                 if (bFocus)\r
857                                         DrawDC.CreatePen(PS_SOLID, 1, m_Foregnd1);\r
858                                 else\r
859                                         DrawDC.CreatePen(PS_SOLID, 1, m_Foregnd2);\r
860 \r
861                                 DrawDC.MoveTo(rcClose.left + 3, rcClose.top +3);\r
862                                 DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -2);\r
863 \r
864                                 DrawDC.MoveTo(rcClose.left + 4, rcClose.top +3);\r
865                                 DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -3);\r
866 \r
867                                 DrawDC.MoveTo(rcClose.left + 3, rcClose.top +4);\r
868                                 DrawDC.LineTo(rcClose.right - 3, rcClose.bottom -2);\r
869 \r
870                                 DrawDC.MoveTo(rcClose.right -3, rcClose.top +3);\r
871                                 DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -2);\r
872 \r
873                                 DrawDC.MoveTo(rcClose.right -3, rcClose.top +4);\r
874                                 DrawDC.LineTo(rcClose.left + 3, rcClose.bottom -2);\r
875 \r
876                                 DrawDC.MoveTo(rcClose.right -4, rcClose.top +3);\r
877                                 DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -3);\r
878                         }\r
879                 }\r
880         }\r
881 \r
882         inline void CDocker::CDockClient::OnNCCalcSize(WPARAM& wParam, LPARAM& lParam)\r
883         {\r
884                 // Sets the non-client area (and hence sets the client area)\r
885                 // This function modifies lParam\r
886 \r
887                 UNREFERENCED_PARAMETER(wParam);\r
888 \r
889                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))\r
890                 {\r
891                         if (m_pDock->IsDocked())\r
892                         {\r
893                                 LPRECT rc = (LPRECT)lParam;\r
894                                 rc->top += m_pDock->m_NCHeight;\r
895                         }\r
896                 }\r
897         }\r
898 \r
899         inline LRESULT CDocker::CDockClient::OnNCHitTest(WPARAM wParam, LPARAM lParam)\r
900         {\r
901                 // Identify which part of the non-client area the cursor is over\r
902                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))\r
903                 {\r
904                         if (m_pDock->IsDocked())\r
905                         {\r
906                                 CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));\r
907 \r
908                                 // Indicate if the point is in the close button (except for Win95)\r
909                                 if ((GetWinVersion() > 1400) && (GetCloseRect().PtInRect(pt)))\r
910                                         return HTCLOSE;\r
911 \r
912                                 ScreenToClient(pt);\r
913 \r
914                                 // Indicate if the point is in the caption\r
915                                 if (pt.y < 0)\r
916                                         return HTCAPTION;\r
917                         }\r
918                 }\r
919                 return CWnd::WndProcDefault(WM_NCHITTEST, wParam, lParam);\r
920         }\r
921 \r
922         inline LRESULT CDocker::CDockClient::OnNCLButtonDown(WPARAM wParam, LPARAM lParam)\r
923         {\r
924                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))\r
925                 {\r
926                         if ((HTCLOSE == wParam) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))\r
927                         {\r
928                                 m_IsClosePressed = TRUE;\r
929                                 SetCapture();\r
930                         }\r
931 \r
932                         m_bCaptionPressed = TRUE;\r
933                         m_Oldpt.x = GET_X_LPARAM(lParam);\r
934                         m_Oldpt.y = GET_Y_LPARAM(lParam);\r
935                         if (m_pDock->IsDocked())\r
936                         {\r
937                                 CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));\r
938                                 ScreenToClient(pt);\r
939                                 m_pView->SetFocus();\r
940 \r
941                                 // Update the close button\r
942                                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))\r
943                                 {\r
944                                         CWindowDC dc(this);\r
945                                         DrawCloseButton(dc, m_bOldFocus);\r
946                                 }\r
947 \r
948                                 return 0L;\r
949                         }\r
950                 }\r
951                 return CWnd::WndProcDefault(WM_NCLBUTTONDOWN, wParam, lParam);\r
952         }\r
953 \r
954         inline void CDocker::CDockClient::OnLButtonUp(WPARAM wParam, LPARAM lParam)\r
955         {\r
956                 UNREFERENCED_PARAMETER(wParam);\r
957                 UNREFERENCED_PARAMETER(lParam);\r
958 \r
959                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & (DS_NO_CAPTION|DS_NO_CLOSE)))\r
960                 {\r
961                         m_bCaptionPressed = FALSE;\r
962                         if (m_IsClosePressed && GetCloseRect().PtInRect(GetCursorPos()))\r
963                         {\r
964                                 // Destroy the docker\r
965                                 if (dynamic_cast<CDockContainer*>(m_pDock->GetView()))\r
966                                 {\r
967                                         CDockContainer* pContainer = ((CDockContainer*)m_pDock->GetView())->GetActiveContainer();\r
968                                         CDocker* pDock = m_pDock->GetDockFromView(pContainer);\r
969                                         pDock->GetDockClient().SetClosePressed();\r
970                                         m_pDock->UndockContainer(pContainer, GetCursorPos(), FALSE);\r
971                                         pDock->Destroy();\r
972                                 }\r
973                                 else\r
974                                 {\r
975                                         m_pDock->Hide();\r
976                                         m_pDock->Destroy();\r
977                                 }\r
978                         }\r
979                 }\r
980         }\r
981 \r
982         inline void CDocker::CDockClient::OnLButtonDown(WPARAM wParam, LPARAM lParam)\r
983         {\r
984                 UNREFERENCED_PARAMETER(wParam);\r
985                 UNREFERENCED_PARAMETER(lParam);\r
986 \r
987                 m_IsClosePressed = FALSE;\r
988                 ReleaseCapture();\r
989                 CWindowDC dc(this);\r
990                 DrawCloseButton(dc, m_bOldFocus);\r
991         }\r
992 \r
993         inline void CDocker::CDockClient::OnMouseActivate(WPARAM wParam, LPARAM lParam)\r
994         // Focus changed, so redraw the captions\r
995         {\r
996                 UNREFERENCED_PARAMETER(wParam);\r
997                 UNREFERENCED_PARAMETER(lParam);\r
998 \r
999                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))\r
1000                 {\r
1001                         m_pDock->GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);\r
1002                 }\r
1003         }\r
1004 \r
1005         inline void CDocker::CDockClient::OnMouseMove(WPARAM wParam, LPARAM lParam)\r
1006         {\r
1007                 OnNCMouseMove(wParam, lParam);\r
1008         }\r
1009 \r
1010         inline void CDocker::CDockClient::OnNCMouseLeave(WPARAM wParam, LPARAM lParam)\r
1011         {\r
1012                 UNREFERENCED_PARAMETER(wParam);\r
1013                 UNREFERENCED_PARAMETER(lParam);\r
1014 \r
1015                 m_IsTracking = FALSE;\r
1016                 CWindowDC dc(this);\r
1017                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & (DS_NO_CAPTION|DS_NO_CLOSE)) && m_pDock->IsDocked())\r
1018                         DrawCloseButton(dc, m_bOldFocus);\r
1019 \r
1020                 m_IsTracking = FALSE;\r
1021         }\r
1022 \r
1023         inline LRESULT CDocker::CDockClient::OnNCMouseMove(WPARAM wParam, LPARAM lParam)\r
1024         {\r
1025                 if (!m_IsTracking)\r
1026                 {\r
1027                         TRACKMOUSEEVENT TrackMouseEventStruct = {0};\r
1028                         TrackMouseEventStruct.cbSize = sizeof(TrackMouseEventStruct);\r
1029                         TrackMouseEventStruct.dwFlags = TME_LEAVE|TME_NONCLIENT;\r
1030                         TrackMouseEventStruct.hwndTrack = m_hWnd;\r
1031                         _TrackMouseEvent(&TrackMouseEventStruct);\r
1032                         m_IsTracking = TRUE;\r
1033                 }\r
1034 \r
1035                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))\r
1036                 {\r
1037                         if (m_pDock->IsDocked())\r
1038                         {\r
1039                                 // Discard phantom mouse move messages\r
1040                                 if ( (m_Oldpt.x == GET_X_LPARAM(lParam) ) && (m_Oldpt.y == GET_Y_LPARAM(lParam)))\r
1041                                         return 0L;\r
1042 \r
1043                                 if (IsLeftButtonDown() && (wParam == HTCAPTION)  && (m_bCaptionPressed))\r
1044                                 {\r
1045                                         CDocker* pDock = (CDocker*)GetParent();\r
1046                                         if (pDock)\r
1047                                                 pDock->Undock(GetCursorPos());\r
1048                                 }\r
1049 \r
1050                                 // Update the close button\r
1051                                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))\r
1052                                 {\r
1053                                         CWindowDC dc(this);\r
1054                                         DrawCloseButton(dc, m_bOldFocus);\r
1055                                 }\r
1056                         }\r
1057 \r
1058                         m_bCaptionPressed = FALSE;\r
1059                 }\r
1060                 return CWnd::WndProcDefault(WM_MOUSEMOVE, wParam, lParam);\r
1061         }\r
1062 \r
1063         inline LRESULT CDocker::CDockClient::OnNCPaint(WPARAM wParam, LPARAM lParam)\r
1064         {\r
1065                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))\r
1066                 {\r
1067                         if (m_pDock->IsDocked())\r
1068                         {\r
1069                                 DefWindowProc(WM_NCPAINT, wParam, lParam);\r
1070                                 DrawCaption(wParam);\r
1071                                 return 0;\r
1072                         }\r
1073                 }\r
1074                 return CWnd::WndProcDefault(WM_NCPAINT, wParam, lParam);\r
1075         }\r
1076 \r
1077         inline void CDocker::CDockClient::OnWindowPosChanged(WPARAM wParam, LPARAM lParam)\r
1078         {\r
1079                 UNREFERENCED_PARAMETER(wParam);\r
1080                 UNREFERENCED_PARAMETER(lParam);\r
1081 \r
1082                 // Reposition the View window to cover the DockClient's client area\r
1083                 CRect rc = GetClientRect();\r
1084                 m_pView->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);\r
1085         }\r
1086 \r
1087         inline void CDocker::CDockClient::PreRegisterClass(WNDCLASS& wc)\r
1088         {\r
1089                 wc.lpszClassName = _T("Win32++ DockClient");\r
1090                 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);\r
1091         }\r
1092 \r
1093         inline void CDocker::CDockClient::PreCreate(CREATESTRUCT& cs)\r
1094         {\r
1095                 DWORD dwStyle = m_pDock->GetDockStyle();\r
1096                 if (dwStyle & DS_CLIENTEDGE)\r
1097                         cs.dwExStyle = WS_EX_CLIENTEDGE;\r
1098 \r
1099 #if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)\r
1100                 if (m_pDock->GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)\r
1101                         cs.dwExStyle |= WS_EX_LAYOUTRTL;\r
1102 #endif\r
1103 \r
1104         }\r
1105 \r
1106         inline void CDocker::CDockClient::SendNotify(UINT nMessageID)\r
1107         {\r
1108                 // Fill the DragPos structure with data\r
1109                 DRAGPOS DragPos;\r
1110                 DragPos.hdr.code = nMessageID;\r
1111                 DragPos.hdr.hwndFrom = m_hWnd;\r
1112                 DragPos.ptPos = GetCursorPos();\r
1113 \r
1114                 // Send a DragPos notification to the docker\r
1115                 GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&DragPos);\r
1116         }\r
1117 \r
1118         inline void CDocker::CDockClient::SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF Foregnd2, COLORREF Backgnd2)\r
1119         {\r
1120                 // Set the colors used when drawing the caption\r
1121                 // m_Foregnd1 Foreground colour (focused).  m_Backgnd1 Background colour (focused)\r
1122                 // m_Foregnd2 Foreground colour (not focused). m_Backgnd2 Foreground colour (not focused)\r
1123                 m_Foregnd1 = Foregnd1;\r
1124                 m_Backgnd1 = Backgnd1;\r
1125                 m_Foregnd2 = Foregnd2;\r
1126                 m_Backgnd2 = Backgnd2;\r
1127         }\r
1128 \r
1129         inline LRESULT CDocker::CDockClient::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
1130         {\r
1131                 switch (uMsg)\r
1132                 {\r
1133                 case WM_LBUTTONUP:\r
1134                         {\r
1135                                 ReleaseCapture();\r
1136                                 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))\r
1137                                 {\r
1138                                         CWindowDC dc(this);\r
1139                                         DrawCloseButton(dc, m_bOldFocus);\r
1140                                         OnLButtonUp(wParam, lParam);\r
1141                                 }\r
1142                         }\r
1143                         break;\r
1144 \r
1145                 case WM_MOUSEACTIVATE:\r
1146                         OnMouseActivate(wParam, lParam);\r
1147                         break;\r
1148 \r
1149                 case WM_MOUSEMOVE:\r
1150                         OnMouseMove(wParam, lParam);\r
1151                         break;\r
1152 \r
1153                 case WM_NCCALCSIZE:\r
1154                         OnNCCalcSize(wParam, lParam);\r
1155                         break;\r
1156 \r
1157                 case WM_NCHITTEST:\r
1158                         return OnNCHitTest(wParam, lParam);\r
1159 \r
1160                 case WM_NCLBUTTONDOWN:\r
1161                         return OnNCLButtonDown(wParam, lParam);\r
1162 \r
1163                 case WM_NCMOUSEMOVE:\r
1164                         return OnNCMouseMove(wParam, lParam);\r
1165 \r
1166                 case WM_NCPAINT:\r
1167                         return OnNCPaint(wParam, lParam);\r
1168 \r
1169                 case WM_NCMOUSELEAVE:\r
1170                         OnNCMouseLeave(wParam, lParam);\r
1171                         break;\r
1172 \r
1173                 case WM_WINDOWPOSCHANGED:\r
1174                         OnWindowPosChanged(wParam, lParam);\r
1175                         break;\r
1176                 }\r
1177 \r
1178                 return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
1179         }\r
1180 \r
1181 \r
1182         //////////////////////////////////////////////////////////////\r
1183         // Definitions for the CDockHint class nested within CDocker\r
1184         //\r
1185         inline CDocker::CDockHint::CDockHint() : m_uDockSideOld(0)\r
1186         {\r
1187         }\r
1188 \r
1189         inline CDocker::CDockHint::~CDockHint()\r
1190         {\r
1191         }\r
1192 \r
1193         inline RECT CDocker::CDockHint::CalcHintRectContainer(CDocker* pDockTarget)\r
1194         {\r
1195                 // Calculate the hint window's position for container docking\r
1196                 CRect rcHint = pDockTarget->GetDockClient().GetWindowRect();\r
1197                 if (pDockTarget->GetDockClient().GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)\r
1198                         rcHint.InflateRect(-2, -2);\r
1199                 pDockTarget->ScreenToClient(rcHint);\r
1200 \r
1201                 return rcHint;\r
1202         }\r
1203 \r
1204         inline RECT CDocker::CDockHint::CalcHintRectInner(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide)\r
1205         {\r
1206                 // Calculate the hint window's position for inner docking\r
1207                 CRect rcHint = pDockTarget->GetDockClient().GetWindowRect();\r
1208                 if (pDockTarget->GetDockClient().GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)\r
1209                         rcHint.InflateRect(-2, -2);\r
1210                 pDockTarget->ScreenToClient(rcHint);\r
1211 \r
1212                 int Width;\r
1213                 CRect rcDockDrag = pDockDrag->GetWindowRect();\r
1214                 CRect rcDockTarget = pDockTarget->GetDockClient().GetWindowRect();\r
1215                 if ((uDockSide  == DS_DOCKED_LEFT) || (uDockSide  == DS_DOCKED_RIGHT))\r
1216                 {\r
1217                         Width = rcDockDrag.Width();\r
1218                         if (Width >= (rcDockTarget.Width() - pDockDrag->GetBarWidth()))\r
1219                                 Width = MAX(rcDockTarget.Width()/2 - pDockDrag->GetBarWidth(), pDockDrag->GetBarWidth());\r
1220                 }\r
1221                 else\r
1222                 {\r
1223                         Width = rcDockDrag.Height();\r
1224                         if (Width >= (rcDockTarget.Height() - pDockDrag->GetBarWidth()))\r
1225                                 Width = MAX(rcDockTarget.Height()/2 - pDockDrag->GetBarWidth(), pDockDrag->GetBarWidth());\r
1226                 }\r
1227                 switch (uDockSide)\r
1228                 {\r
1229                 case DS_DOCKED_LEFT:\r
1230                         rcHint.right = rcHint.left + Width;\r
1231                         break;\r
1232                 case DS_DOCKED_RIGHT:\r
1233                         rcHint.left = rcHint.right - Width;\r
1234                         break;\r
1235                 case DS_DOCKED_TOP:\r
1236                         rcHint.bottom = rcHint.top + Width;\r
1237                         break;\r
1238                 case DS_DOCKED_BOTTOM:\r
1239                         rcHint.top = rcHint.bottom - Width;\r
1240                         break;\r
1241                 }\r
1242 \r
1243                 return rcHint;\r
1244         }\r
1245 \r
1246         inline RECT CDocker::CDockHint::CalcHintRectOuter(CDocker* pDockDrag, UINT uDockSide)\r
1247         {\r
1248                 // Calculate the hint window's position for outer docking\r
1249                 CDocker* pDockTarget = pDockDrag->GetDockAncestor();\r
1250                 CRect rcHint = pDockTarget->GetClientRect();\r
1251                 if (pDockTarget->GetDockClient().GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)\r
1252                         rcHint.InflateRect(-2, -2);\r
1253 \r
1254                 int Width;\r
1255                 CRect rcDockDrag = pDockDrag->GetWindowRect();\r
1256                 CRect rcDockTarget = pDockTarget->GetDockClient().GetWindowRect();\r
1257 \r
1258                 // Limit the docked size to half the parent's size if it won't fit inside parent\r
1259                 if ((uDockSide == DS_DOCKED_LEFTMOST) || (uDockSide  == DS_DOCKED_RIGHTMOST))\r
1260                 {\r
1261                         Width = rcDockDrag.Width();\r
1262                         int BarWidth = pDockDrag->GetBarWidth();\r
1263                         if (Width >= pDockTarget->GetDockClient().GetClientRect().Width() - pDockDrag->GetBarWidth())\r
1264                                 Width = MAX(pDockTarget->GetDockClient().GetClientRect().Width()/2 - BarWidth, BarWidth);\r
1265                 }\r
1266                 else\r
1267                 {\r
1268                         Width = rcDockDrag.Height();\r
1269                         int BarWidth = pDockDrag->GetBarWidth();\r
1270                         if (Width >= pDockTarget->GetDockClient().GetClientRect().Height() - pDockDrag->GetBarWidth())\r
1271                                 Width = MAX(pDockTarget->GetDockClient().GetClientRect().Height()/2 - BarWidth, BarWidth);\r
1272                 }\r
1273                 switch (uDockSide)\r
1274                 {\r
1275                 case DS_DOCKED_LEFTMOST:\r
1276                         rcHint.right = rcHint.left + Width;\r
1277                         break;\r
1278                 case DS_DOCKED_RIGHTMOST:\r
1279                         rcHint.left = rcHint.right - Width;\r
1280                         break;\r
1281                 case DS_DOCKED_TOPMOST:\r
1282                         rcHint.bottom = rcHint.top + Width;\r
1283                         break;\r
1284                 case DS_DOCKED_BOTTOMMOST:\r
1285                         rcHint.top = rcHint.bottom - Width;\r
1286                         break;\r
1287                 }\r
1288 \r
1289                 return rcHint;\r
1290         }\r
1291 \r
1292         inline void CDocker::CDockHint::DisplayHint(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide)\r
1293         {\r
1294                 // Ensure a new hint window is created if dock side changes\r
1295                 if (uDockSide != m_uDockSideOld)\r
1296                 {\r
1297                         Destroy();\r
1298                         pDockTarget->RedrawWindow( NULL, NULL, RDW_NOERASE | RDW_UPDATENOW );\r
1299                         pDockDrag->RedrawWindow();\r
1300                 }\r
1301                 m_uDockSideOld = uDockSide;\r
1302 \r
1303                 if (!IsWindow())\r
1304                 {\r
1305                         CRect rcHint;\r
1306 \r
1307                         if (uDockSide & 0xF)\r
1308                                 rcHint = CalcHintRectInner(pDockTarget, pDockDrag, uDockSide);\r
1309                         else if (uDockSide & 0xF0000)\r
1310                                 rcHint = CalcHintRectOuter(pDockDrag, uDockSide);\r
1311                         else if (uDockSide & DS_DOCKED_CONTAINER)\r
1312                                 rcHint = CalcHintRectContainer(pDockTarget);\r
1313                         else\r
1314                                 return;\r
1315 \r
1316                         ShowHintWindow(pDockTarget, rcHint);\r
1317                 }\r
1318         }\r
1319 \r
1320         inline void CDocker::CDockHint::OnDraw(CDC* pDC)\r
1321         {\r
1322                 // Display the blue tinted bitmap\r
1323                 CRect rc = GetClientRect();\r
1324                 CMemDC MemDC(pDC);\r
1325                 MemDC.SelectObject(&m_bmBlueTint);\r
1326                 pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &MemDC, 0, 0, SRCCOPY);\r
1327         }\r
1328 \r
1329         inline void CDocker::CDockHint::PreCreate(CREATESTRUCT &cs)\r
1330         {\r
1331                 cs.style = WS_POPUP;\r
1332 \r
1333                 // WS_EX_TOOLWINDOW prevents the window being displayed on the taskbar\r
1334                 cs.dwExStyle = WS_EX_TOOLWINDOW;\r
1335 \r
1336                 cs.lpszClass = _T("Win32++ DockHint");\r
1337         }\r
1338 \r
1339         inline void CDocker::CDockHint::ShowHintWindow(CDocker* pDockTarget, CRect rcHint)\r
1340         {\r
1341                 // Save the Dock window's blue tinted bitmap\r
1342                 CClientDC dcDesktop(NULL);\r
1343                 CMemDC dcMem(&dcDesktop);\r
1344                 CRect rcBitmap = rcHint;\r
1345                 CRect rcTarget = rcHint;\r
1346                 pDockTarget->ClientToScreen(rcTarget);\r
1347 \r
1348                 m_bmBlueTint.CreateCompatibleBitmap(&dcDesktop, rcBitmap.Width(), rcBitmap.Height());\r
1349                 CBitmap* pOldBitmap = dcMem.SelectObject(&m_bmBlueTint);\r
1350                 dcMem.BitBlt(0, 0, rcBitmap.Width(), rcBitmap.Height(), &dcDesktop, rcTarget.left, rcTarget.top, SRCCOPY);\r
1351                 dcMem.SelectObject(pOldBitmap); \r
1352                 TintBitmap(&m_bmBlueTint, -64, -24, +128);\r
1353 \r
1354                 // Create the Hint window\r
1355                 if (!IsWindow())\r
1356                 {\r
1357                         Create(pDockTarget);\r
1358                 }\r
1359 \r
1360                 pDockTarget->ClientToScreen(rcHint);\r
1361                 SetWindowPos(NULL, rcHint, SWP_SHOWWINDOW|SWP_NOZORDER|SWP_NOACTIVATE);\r
1362         }\r
1363 \r
1364 \r
1365         ////////////////////////////////////////////////////////////////\r
1366         // Definitions for the CTargetCentre class nested within CDocker\r
1367         //\r
1368         inline CDocker::CTargetCentre::CTargetCentre() : m_bIsOverContainer(FALSE), m_pOldDockTarget(0)\r
1369         {\r
1370         }\r
1371 \r
1372         inline CDocker::CTargetCentre::~CTargetCentre()\r
1373         {\r
1374         }\r
1375 \r
1376         inline void CDocker::CTargetCentre::OnDraw(CDC* pDC)\r
1377         {\r
1378                 CBitmap bmCentre(IDW_SDCENTER);\r
1379                 CBitmap bmLeft(IDW_SDLEFT);\r
1380                 CBitmap bmRight(IDW_SDRIGHT);\r
1381                 CBitmap bmTop(IDW_SDTOP);\r
1382                 CBitmap bmBottom(IDW_SDBOTTOM);\r
1383 \r
1384                 if (bmCentre.GetHandle())       pDC->DrawBitmap(0, 0, 88, 88, bmCentre, RGB(255,0,255));\r
1385                 else TRACE(_T("Missing docking resource: Target Centre\n"));\r
1386 \r
1387                 if (bmLeft.GetHandle()) pDC->DrawBitmap(0, 29, 31, 29, bmLeft, RGB(255,0,255));\r
1388                 else TRACE(_T("Missing docking resource: Target Left\n"));\r
1389 \r
1390                 if (bmTop.GetHandle()) pDC->DrawBitmap(29, 0, 29, 31, bmTop, RGB(255,0,255));\r
1391                 else TRACE(_T("Missing docking resource: Target Top\n"));\r
1392 \r
1393                 if (bmRight.GetHandle()) pDC->DrawBitmap(55, 29, 31, 29, bmRight, RGB(255,0,255));\r
1394                 else TRACE(_T("Missing docking resource: Target Right\n"));\r
1395 \r
1396                 if (bmBottom.GetHandle()) pDC->DrawBitmap(29, 55, 29, 31, bmBottom, RGB(255,0,255));\r
1397                 else TRACE(_T("Missing docking resource: Target Bottom\n"));\r
1398 \r
1399                 if (IsOverContainer())\r
1400                 {\r
1401                         CBitmap bmMiddle(IDW_SDMIDDLE);\r
1402                         pDC->DrawBitmap(31, 31, 25, 26, bmMiddle, RGB(255,0,255));\r
1403                 }\r
1404         }\r
1405 \r
1406         inline void CDocker::CTargetCentre::OnCreate()\r
1407         {\r
1408                 // Use a region to create an irregularly shapped window\r
1409                 POINT ptArray[16] = { {0,29}, {22, 29}, {29, 22}, {29, 0},\r
1410                                       {58, 0}, {58, 22}, {64, 29}, {87, 29},\r
1411                                       {87, 58}, {64, 58}, {58, 64}, {58, 87},\r
1412                                       {29, 87}, {29, 64}, {23, 58}, {0, 58} };\r
1413 \r
1414                 CRgn rgnPoly;\r
1415                 rgnPoly.CreatePolygonRgn(ptArray, 16, WINDING);\r
1416                 SetWindowRgn(&rgnPoly, FALSE);\r
1417         }\r
1418 \r
1419         inline BOOL CDocker::CTargetCentre::CheckTarget(LPDRAGPOS pDragPos)\r
1420         {\r
1421                 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);\r
1422                 if (NULL == pDockDrag) return FALSE;\r
1423 \r
1424                 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pDragPos->ptPos);\r
1425                 if (NULL == pDockTarget) return FALSE;\r
1426 \r
1427                 if (!IsWindow())        Create();\r
1428                 m_bIsOverContainer = (dynamic_cast<CDockContainer*>(pDockTarget->GetView()) != NULL);\r
1429 \r
1430                 // Redraw the target if the dock target changes\r
1431                 if (m_pOldDockTarget != pDockTarget)    Invalidate();\r
1432                 m_pOldDockTarget = pDockTarget;\r
1433 \r
1434                 int cxImage = 88;\r
1435                 int cyImage = 88;\r
1436 \r
1437                 CRect rcTarget = pDockTarget->GetDockClient().GetWindowRect();\r
1438                 int xMid = rcTarget.left + (rcTarget.Width() - cxImage)/2;\r
1439                 int yMid = rcTarget.top + (rcTarget.Height() - cyImage)/2;\r
1440                 SetWindowPos(&wndTopMost, xMid, yMid, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);\r
1441 \r
1442                 // Create the docking zone rectangles\r
1443                 CPoint pt = pDragPos->ptPos;\r
1444                 ScreenToClient(pt);\r
1445                 CRect rcLeft(0, 29, 31, 58);\r
1446                 CRect rcTop(29, 0, 58, 31);\r
1447                 CRect rcRight(55, 29, 87, 58);\r
1448                 CRect rcBottom(29, 55, 58, 87);\r
1449                 CRect rcMiddle(31, 31, 56, 57);\r
1450 \r
1451                 // Test if our cursor is in one of the docking zones\r
1452                 if ((rcLeft.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_LEFT))\r
1453                 {\r
1454                         pDockDrag->m_BlockMove = TRUE;\r
1455                         pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_LEFT);\r
1456                         pDockDrag->m_dwDockZone = DS_DOCKED_LEFT;\r
1457                         return TRUE;\r
1458                 }\r
1459                 else if ((rcTop.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_TOP))\r
1460                 {\r
1461                         pDockDrag->m_BlockMove = TRUE;\r
1462                         pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_TOP);\r
1463                         pDockDrag->m_dwDockZone = DS_DOCKED_TOP;\r
1464                         return TRUE;\r
1465                 }\r
1466                 else if ((rcRight.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_RIGHT))\r
1467                 {\r
1468                         pDockDrag->m_BlockMove = TRUE;\r
1469                         pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_RIGHT);\r
1470                         pDockDrag->m_dwDockZone = DS_DOCKED_RIGHT;\r
1471                         return TRUE;\r
1472                 }\r
1473                 else if ((rcBottom.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_BOTTOM))\r
1474                 {\r
1475                         pDockDrag->m_BlockMove = TRUE;\r
1476                         pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_BOTTOM);\r
1477                         pDockDrag->m_dwDockZone = DS_DOCKED_BOTTOM;\r
1478                         return TRUE;\r
1479                 }\r
1480                 else if ((rcMiddle.PtInRect(pt)) && (IsOverContainer()))\r
1481                 {\r
1482                         pDockDrag->m_BlockMove = TRUE;\r
1483                         pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_CONTAINER);\r
1484                         pDockDrag->m_dwDockZone = DS_DOCKED_CONTAINER;\r
1485                         return TRUE;\r
1486                 }\r
1487                 else\r
1488                         return FALSE;\r
1489         }\r
1490 \r
1491         ////////////////////////////////////////////////////////////////\r
1492         // Definitions for the CTarget class nested within CDocker\r
1493         // CTarget is the base class for a number of CTargetXXX classes\r
1494         inline CDocker::CTarget::~CTarget()\r
1495         {\r
1496         }\r
1497 \r
1498         inline void CDocker::CTarget::OnDraw(CDC* pDC)\r
1499         {\r
1500                 BITMAP bm = m_bmImage.GetBitmapData();\r
1501                 int cxImage = bm.bmWidth;\r
1502                 int cyImage = bm.bmHeight;\r
1503 \r
1504                 if (m_bmImage) \r
1505                         pDC->DrawBitmap(0, 0, cxImage, cyImage, m_bmImage, RGB(255,0,255));\r
1506                 else \r
1507                         TRACE(_T("Missing docking resource\n"));\r
1508         }\r
1509 \r
1510         inline void CDocker::CTarget::PreCreate(CREATESTRUCT &cs)\r
1511         {\r
1512                 cs.style = WS_POPUP;\r
1513                 cs.dwExStyle = WS_EX_TOPMOST|WS_EX_TOOLWINDOW;\r
1514                 cs.lpszClass = _T("Win32++ DockTargeting");\r
1515         }\r
1516 \r
1517 \r
1518         ////////////////////////////////////////////////////////////////\r
1519         // Definitions for the CTargetLeft class nested within CDocker\r
1520         //\r
1521         inline BOOL CDocker::CTargetLeft::CheckTarget(LPDRAGPOS pDragPos)\r
1522         {\r
1523                 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);\r
1524                 if (NULL == pDockDrag) return FALSE;\r
1525 \r
1526                 CPoint pt = pDragPos->ptPos;\r
1527                 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();\r
1528                 if (pDockTarget != pDockDrag->GetDockAncestor())\r
1529                 {\r
1530                         Destroy();\r
1531                         return FALSE;\r
1532                 }\r
1533 \r
1534                 BITMAP bm = m_bmImage.GetBitmapData();\r
1535                 int cxImage = bm.bmWidth;\r
1536                 int cyImage = bm.bmHeight;\r
1537 \r
1538                 if (!IsWindow())\r
1539                 {\r
1540                         Create();\r
1541                         CRect rc = pDockTarget->GetWindowRect();\r
1542                         int yMid = rc.top + (rc.Height() - cyImage)/2;\r
1543                         SetWindowPos(&wndTopMost, rc.left + 10, yMid, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);\r
1544                 }\r
1545 \r
1546                 CRect rcLeft(0, 0, cxImage, cyImage);\r
1547                 ScreenToClient(pt);\r
1548 \r
1549                 // Test if our cursor is in one of the docking zones\r
1550                 if ((rcLeft.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_LEFT))\r
1551                 {\r
1552                         pDockDrag->m_BlockMove = TRUE;\r
1553                         pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_LEFTMOST);\r
1554                         pDockDrag->m_dwDockZone = DS_DOCKED_LEFTMOST;\r
1555                         return TRUE;\r
1556                 }\r
1557 \r
1558                 return FALSE;\r
1559         }\r
1560 \r
1561 \r
1562         ////////////////////////////////////////////////////////////////\r
1563         // Definitions for the CTargetTop class nested within CDocker\r
1564         //\r
1565         inline BOOL CDocker::CTargetTop::CheckTarget(LPDRAGPOS pDragPos)\r
1566         {\r
1567                 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);\r
1568                 if (NULL == pDockDrag) return FALSE;\r
1569 \r
1570                 CPoint pt = pDragPos->ptPos;\r
1571                 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();\r
1572                 if (pDockTarget != pDockDrag->GetDockAncestor())\r
1573                 {\r
1574                         Destroy();\r
1575                         return FALSE;\r
1576                 }\r
1577 \r
1578                 BITMAP bm = m_bmImage.GetBitmapData();\r
1579                 int cxImage = bm.bmWidth;\r
1580                 int cyImage = bm.bmHeight;\r
1581 \r
1582                 if (!IsWindow())\r
1583                 {\r
1584                         Create();\r
1585                         CRect rc = pDockTarget->GetWindowRect();\r
1586                         int xMid = rc.left + (rc.Width() - cxImage)/2;\r
1587                         SetWindowPos(&wndTopMost, xMid, rc.top + 10, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);\r
1588                 }\r
1589 \r
1590                 CRect rcTop(0, 0, cxImage, cyImage);\r
1591                 ScreenToClient(pt);\r
1592 \r
1593                 // Test if our cursor is in one of the docking zones\r
1594                 if ((rcTop.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_TOP))\r
1595                 {\r
1596                         pDockDrag->m_BlockMove = TRUE;\r
1597                         pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_TOPMOST);\r
1598                         pDockDrag->m_dwDockZone = DS_DOCKED_TOPMOST;\r
1599                         return TRUE;\r
1600                 }\r
1601 \r
1602                 return FALSE;\r
1603         }\r
1604 \r
1605 \r
1606         ////////////////////////////////////////////////////////////////\r
1607         // Definitions for the CTargetRight class nested within CDocker\r
1608         //\r
1609         inline BOOL CDocker::CTargetRight::CheckTarget(LPDRAGPOS pDragPos)\r
1610         {\r
1611                 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);\r
1612                 if (NULL == pDockDrag) return FALSE;\r
1613 \r
1614                 CPoint pt = pDragPos->ptPos;\r
1615                 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();\r
1616                 if (pDockTarget != pDockDrag->GetDockAncestor())\r
1617                 {\r
1618                         Destroy();\r
1619                         return FALSE;\r
1620                 }\r
1621 \r
1622                 BITMAP bm = m_bmImage.GetBitmapData();\r
1623                 int cxImage = bm.bmWidth;\r
1624                 int cyImage = bm.bmHeight;\r
1625 \r
1626                 if (!IsWindow())\r
1627                 {\r
1628                         Create();\r
1629                         CRect rc = pDockTarget->GetWindowRect();\r
1630                         int yMid = rc.top + (rc.Height() - cyImage)/2;\r
1631                         SetWindowPos(&wndTopMost, rc.right - 10 - cxImage, yMid, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);\r
1632                 }\r
1633 \r
1634                 CRect rcRight(0, 0, cxImage, cyImage);\r
1635                 ScreenToClient(pt);\r
1636 \r
1637                 // Test if our cursor is in one of the docking zones\r
1638                 if ((rcRight.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_RIGHT))\r
1639                 {\r
1640                         pDockDrag->m_BlockMove = TRUE;\r
1641                         pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_RIGHTMOST);\r
1642                         pDockDrag->m_dwDockZone = DS_DOCKED_RIGHTMOST;\r
1643                         return TRUE;\r
1644                 }\r
1645 \r
1646                 return FALSE;\r
1647         }\r
1648 \r
1649 \r
1650         ////////////////////////////////////////////////////////////////\r
1651         // Definitions for the CTargetBottom class nested within CDocker\r
1652         //\r
1653         inline BOOL CDocker::CTargetBottom::CheckTarget(LPDRAGPOS pDragPos)\r
1654         {\r
1655                 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);\r
1656                 if (NULL == pDockDrag) return FALSE;\r
1657 \r
1658                 CPoint pt = pDragPos->ptPos;\r
1659                 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();\r
1660                 if (pDockTarget != pDockDrag->GetDockAncestor())\r
1661                 {\r
1662                         Destroy();\r
1663                         return FALSE;\r
1664                 }\r
1665 \r
1666                 BITMAP bm = m_bmImage.GetBitmapData();\r
1667                 int cxImage = bm.bmWidth;\r
1668                 int cyImage = bm.bmHeight;\r
1669 \r
1670                 if (!IsWindow())\r
1671                 {\r
1672                         Create();\r
1673                         CRect rc = pDockTarget->GetWindowRect();\r
1674                         int xMid = rc.left + (rc.Width() - cxImage)/2;\r
1675                         SetWindowPos(&wndTopMost, xMid, rc.bottom - 10 - cyImage, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);\r
1676                 }\r
1677                 CRect rcBottom(0, 0, cxImage, cyImage);\r
1678                 ScreenToClient(pt);\r
1679 \r
1680                 // Test if our cursor is in one of the docking zones\r
1681                 if ((rcBottom.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_BOTTOM))\r
1682                 {\r
1683                         pDockDrag->m_BlockMove = TRUE;\r
1684                         pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_BOTTOMMOST);\r
1685                         pDockDrag->m_dwDockZone = DS_DOCKED_BOTTOMMOST;\r
1686                         return TRUE;\r
1687                 }\r
1688 \r
1689                 return FALSE;\r
1690         }\r
1691 \r
1692 \r
1693         /////////////////////////////////////////\r
1694         // Definitions for the CDocker class\r
1695         //\r
1696         inline CDocker::CDocker() : m_pDockParent(NULL), m_pDockActive(NULL), m_BlockMove(FALSE), m_Undocking(FALSE),\r
1697                             m_bIsClosing(FALSE), m_bIsDragging(FALSE), m_bDragAutoResize(TRUE), m_DockStartSize(0), m_nDockID(0),\r
1698                             m_nTimerCount(0), m_NCHeight(0), m_dwDockZone(0), m_DockSizeRatio(1.0), m_DockStyle(0), m_hOldFocus(0)\r
1699         {\r
1700                 // Assume this docker is the DockAncestor for now.\r
1701                 m_pDockAncestor = this;\r
1702         }\r
1703 \r
1704         inline CDocker::~CDocker()\r
1705         {\r
1706                 GetDockBar().Destroy();\r
1707 \r
1708                 std::vector <DockPtr>::iterator iter;\r
1709                 if (GetDockAncestor() == this)\r
1710                 {\r
1711                         // Destroy all dock descendants of this dock ancestor\r
1712                         for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)\r
1713                         {\r
1714                                 (*iter)->Destroy();\r
1715                         }\r
1716                 }\r
1717         }\r
1718 \r
1719         inline CDocker* CDocker::AddDockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, int nDockID /* = 0*/)\r
1720         // This function creates the docker, and adds it to the docker heirachy as docked\r
1721         {\r
1722                 // Create the docker window as a child of the frame window.\r
1723                 // This pernamently sets the frame window as the docker window's owner,\r
1724                 // even when its parent is subsequently changed.\r
1725 \r
1726                 assert(pDocker);\r
1727 \r
1728                 // Store the Docker's pointer in the DockAncestor's vector for later deletion\r
1729                 GetDockAncestor()->m_vAllDockers.push_back(DockPtr(pDocker));\r
1730 \r
1731                 pDocker->SetDockStyle(dwDockStyle);\r
1732                 pDocker->m_nDockID = nDockID;\r
1733                 pDocker->m_pDockAncestor = GetDockAncestor();\r
1734                 pDocker->m_pDockParent = this;\r
1735                 pDocker->SetDockSize(DockSize);\r
1736                 CWnd* pFrame = GetDockAncestor()->GetAncestor();\r
1737                 pDocker->Create(pFrame);\r
1738                 pDocker->SetParent(this);\r
1739 \r
1740                 // Dock the docker window\r
1741                 if (dwDockStyle & DS_DOCKED_CONTAINER)\r
1742                         DockInContainer(pDocker, dwDockStyle);\r
1743                 else\r
1744                         Dock(pDocker, dwDockStyle);\r
1745 \r
1746                 // Issue TRACE warnings for any missing resources\r
1747                 HMODULE hMod= GetApp()->GetResourceHandle();\r
1748 \r
1749                 if (!(dwDockStyle & DS_NO_RESIZE))\r
1750                 {\r
1751                         if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SPLITH), RT_GROUP_CURSOR))\r
1752                                 TRACE(_T("**WARNING** Horizontal cursor resource missing\n"));\r
1753                         if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SPLITV), RT_GROUP_CURSOR))\r
1754                                 TRACE(_T("**WARNING** Vertical cursor resource missing\n"));\r
1755                 }\r
1756 \r
1757                 if (!(dwDockStyle & DS_NO_UNDOCK))\r
1758                 {\r
1759                         if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDCENTER), RT_BITMAP))\r
1760                                 TRACE(_T("**WARNING** Docking center bitmap resource missing\n"));\r
1761                         if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDLEFT), RT_BITMAP))\r
1762                                 TRACE(_T("**WARNING** Docking left bitmap resource missing\n"));\r
1763                         if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDRIGHT), RT_BITMAP))\r
1764                                 TRACE(_T("**WARNING** Docking right bitmap resource missing\n"));\r
1765                         if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDTOP), RT_BITMAP))\r
1766                                 TRACE(_T("**WARNING** Docking top bitmap resource missing\n"));\r
1767                         if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDBOTTOM), RT_BITMAP))\r
1768                                 TRACE(_T("**WARNING** Docking center bottom resource missing\n"));\r
1769                 }\r
1770 \r
1771                 if (dwDockStyle & DS_DOCKED_CONTAINER)\r
1772                 {\r
1773                         if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDMIDDLE), RT_BITMAP))\r
1774                                 TRACE(_T("**WARNING** Docking container bitmap resource missing\n"));\r
1775                 }\r
1776 \r
1777                 return pDocker;\r
1778         }\r
1779 \r
1780         inline CDocker* CDocker::AddUndockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, RECT rc, int nDockID /* = 0*/)\r
1781         // This function creates the docker, and adds it to the docker heirachy as undocked\r
1782         {\r
1783                 assert(pDocker);\r
1784 \r
1785                 // Store the Docker's pointer in the DockAncestor's vector for later deletion\r
1786                 GetDockAncestor()->m_vAllDockers.push_back(DockPtr(pDocker));\r
1787 \r
1788                 pDocker->SetDockSize(DockSize);\r
1789                 pDocker->SetDockStyle(dwDockStyle & 0XFFFFFF0);\r
1790                 pDocker->m_nDockID = nDockID;\r
1791                 pDocker->m_pDockAncestor = GetDockAncestor();\r
1792 \r
1793                 // Initially create the as a child window of the frame\r
1794                 // This makes the frame window the owner of our docker\r
1795                 CWnd* pFrame = GetDockAncestor()->GetAncestor();\r
1796                 pDocker->Create(pFrame);\r
1797                 pDocker->SetParent(this);\r
1798 \r
1799                 // Change the Docker to a POPUP window\r
1800                 DWORD dwStyle = WS_POPUP| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE;\r
1801                 pDocker->SetWindowLongPtr(GWL_STYLE, dwStyle);\r
1802                 pDocker->SetRedraw(FALSE);\r
1803                 pDocker->SetParent(0);\r
1804                 pDocker->SetWindowPos(0, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED);\r
1805                 pDocker->SetRedraw(TRUE);\r
1806                 pDocker->RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ALLCHILDREN);\r
1807                 pDocker->SetWindowText(pDocker->GetCaption().c_str());\r
1808 \r
1809                 return pDocker;\r
1810         }\r
1811 \r
1812         inline void CDocker::CheckAllTargets(LPDRAGPOS pDragPos)\r
1813         // Calls CheckTarget for each possible target zone\r
1814         {\r
1815                 if (!GetDockAncestor()->m_TargetCentre.CheckTarget(pDragPos))\r
1816                 {\r
1817                         if (!GetDockAncestor()->m_TargetLeft.CheckTarget(pDragPos))\r
1818                         {\r
1819                                 if(!GetDockAncestor()->m_TargetTop.CheckTarget(pDragPos))\r
1820                                 {\r
1821                                         if(!GetDockAncestor()->m_TargetRight.CheckTarget(pDragPos))\r
1822                                         {\r
1823                                                 if(!GetDockAncestor()->m_TargetBottom.CheckTarget(pDragPos))\r
1824                                                 {\r
1825                                                         // Not in a docking zone, so clean up\r
1826                                                         NMHDR nmhdr = pDragPos->hdr;\r
1827                                                         CDocker* pDockDrag = (CDocker*)FromHandle(nmhdr.hwndFrom);\r
1828                                                         if (pDockDrag)\r
1829                                                         {\r
1830                                                                 if (pDockDrag->m_BlockMove)\r
1831                                                                         pDockDrag->RedrawWindow(0, 0, RDW_FRAME|RDW_INVALIDATE);\r
1832 \r
1833                                                                 GetDockHint().Destroy();\r
1834                                                                 pDockDrag->m_dwDockZone = 0;\r
1835                                                                 pDockDrag->m_BlockMove = FALSE;\r
1836                                                         }\r
1837                                                 }\r
1838                                         }\r
1839                                 }\r
1840                         }\r
1841                 }\r
1842         }\r
1843 \r
1844         inline BOOL CDocker::VerifyDockers()\r
1845         // A diagnostic routine which verifies the integrity of the docking layout\r
1846         {\r
1847                 BOOL bResult = TRUE;\r
1848 \r
1849                 // Check dock ancestor\r
1850                 std::vector<DockPtr>::iterator iter;\r
1851 \r
1852                 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)\r
1853                 {\r
1854                         if (GetDockAncestor() != (*iter)->m_pDockAncestor)\r
1855                         {\r
1856                                 TRACE(_T("Invalid Dock Ancestor\n"));\r
1857                                 bResult = FALSE;\r
1858                         }\r
1859                 }\r
1860 \r
1861                 // Check presence of dock parent\r
1862                 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)\r
1863                 {\r
1864                         if ((*iter)->IsUndocked() && (*iter)->m_pDockParent != 0)\r
1865                         {\r
1866                                 TRACE(_T("Error: Undocked dockers should not have a dock parent\n"));\r
1867                                         bResult = FALSE;\r
1868                         }\r
1869 \r
1870                         if ((*iter)->IsDocked() && (*iter)->m_pDockParent == 0)\r
1871                         {\r
1872                                 TRACE(_T("Error: Docked dockers should have a dock parent\n"));\r
1873                                         bResult = FALSE;\r
1874                         }\r
1875                 }\r
1876 \r
1877                 // Check dock parent/child relationship\r
1878                 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)\r
1879                 {\r
1880                         std::vector<CDocker*>::iterator iterChild;\r
1881                         for (iterChild = (*iter)->GetDockChildren().begin(); iterChild != (*iter)->GetDockChildren().end(); ++iterChild)\r
1882                         {\r
1883                                 if ((*iterChild)->m_pDockParent != (*iter).get())\r
1884                                 {\r
1885                                         TRACE(_T("Error: Docking parent/Child information mismatch\n"));\r
1886                                         bResult = FALSE;\r
1887                                 }\r
1888                                 if ((*iterChild)->GetParent() != (*iter).get())\r
1889                                 {\r
1890                                         TRACE(_T("Error: Incorrect windows child parent relationship\n"));\r
1891                                         bResult = FALSE;\r
1892                                 }\r
1893                         }\r
1894                 }\r
1895 \r
1896                 // Check dock parent chain\r
1897                 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)\r
1898                 {\r
1899                         CDocker* pDockTopLevel = (*iter)->GetTopmostDocker();\r
1900                         if (pDockTopLevel->IsDocked())\r
1901                                 TRACE(_T("Error: Top level parent should be undocked\n"));\r
1902                 }\r
1903 \r
1904                 return bResult;\r
1905         }\r
1906 \r
1907         inline void CDocker::Close()\r
1908         {\r
1909                 // Destroy the docker\r
1910                 Hide();\r
1911                 Destroy();\r
1912         }\r
1913 \r
1914         inline void CDocker::CloseAllDockers()\r
1915         {\r
1916                 assert(this == GetDockAncestor());      // Must call CloseAllDockers from the DockAncestor\r
1917 \r
1918                 std::vector <DockPtr>::iterator v;\r
1919 \r
1920                 SetRedraw(FALSE);\r
1921                 std::vector<DockPtr> AllDockers = GetAllDockers();\r
1922                 for (v = AllDockers.begin(); v != AllDockers.end(); ++v)\r
1923                 {\r
1924                         // The CDocker is destroyed when the window is destroyed\r
1925                         (*v)->m_bIsClosing = TRUE;\r
1926                         (*v)->Destroy();        // Destroy the window\r
1927                 }\r
1928 \r
1929                 GetDockChildren().clear();\r
1930                 SetRedraw(TRUE);\r
1931                 \r
1932                 // Delete any child containers this container might have\r
1933                 if (GetContainer())\r
1934                 {\r
1935                         std::vector<ContainerInfo> AllContainers = GetContainer()->GetAllContainers();\r
1936                         std::vector<ContainerInfo>::iterator iter;\r
1937                         for (iter = AllContainers.begin(); iter < AllContainers.end(); ++iter)\r
1938                         {\r
1939                                 if (GetContainer() != (*iter).pContainer)\r
1940                                         GetContainer()->RemoveContainer((*iter).pContainer);\r
1941                         }\r
1942                 }\r
1943 \r
1944                 RecalcDockLayout();\r
1945         }\r
1946 \r
1947         inline void CDocker::CloseAllTargets()\r
1948         {\r
1949                 GetDockAncestor()->m_TargetCentre.Destroy();\r
1950                 GetDockAncestor()->m_TargetLeft.Destroy();\r
1951                 GetDockAncestor()->m_TargetTop.Destroy();\r
1952                 GetDockAncestor()->m_TargetRight.Destroy();\r
1953                 GetDockAncestor()->m_TargetBottom.Destroy();\r
1954         }\r
1955 \r
1956         inline void CDocker::Dock(CDocker* pDocker, UINT DockStyle)\r
1957         // Docks the specified docker inside this docker\r
1958         {\r
1959                 assert(pDocker);\r
1960 \r
1961                 pDocker->m_pDockParent = this;\r
1962                 pDocker->m_BlockMove = FALSE;\r
1963                 pDocker->SetDockStyle(DockStyle);\r
1964                 m_vDockChildren.push_back(pDocker);\r
1965                 pDocker->ConvertToChild(m_hWnd);\r
1966 \r
1967                 // Limit the docked size to half the parent's size if it won't fit inside parent\r
1968                 if (((DockStyle & 0xF)  == DS_DOCKED_LEFT) || ((DockStyle &0xF)  == DS_DOCKED_RIGHT))\r
1969                 {\r
1970                         int Width = GetDockClient().GetWindowRect().Width();\r
1971                         int BarWidth = pDocker->GetBarWidth();\r
1972                         if (pDocker->m_DockStartSize >= (Width - BarWidth))\r
1973                                 pDocker->SetDockSize(MAX(Width/2 - BarWidth, BarWidth));\r
1974 \r
1975                         pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetWindowRect().Width();\r
1976                 }\r
1977                 else\r
1978                 {\r
1979                         int Height = GetDockClient().GetWindowRect().Height();\r
1980                         int BarWidth = pDocker->GetBarWidth();\r
1981                         if (pDocker->m_DockStartSize >= (Height - BarWidth))\r
1982                                 pDocker->SetDockSize(MAX(Height/2 - BarWidth, BarWidth));\r
1983 \r
1984                         pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetWindowRect().Height();\r
1985                 }\r
1986 \r
1987                 // Redraw the docked windows\r
1988                 GetAncestor()->SetForegroundWindow();\r
1989                 GetTopmostDocker()->m_hOldFocus = pDocker->GetView()->GetHwnd();\r
1990                 pDocker->GetView()->SetFocus();\r
1991 \r
1992                 GetTopmostDocker()->SetRedraw(FALSE);\r
1993                 RecalcDockLayout();\r
1994                 GetTopmostDocker()->SetRedraw(TRUE);\r
1995                 GetTopmostDocker()->RedrawWindow();\r
1996         }\r
1997 \r
1998         inline void CDocker::DockInContainer(CDocker* pDock, DWORD dwDockStyle)\r
1999         // Add a container to an existing container\r
2000         {\r
2001                 if ((dwDockStyle & DS_DOCKED_CONTAINER) && (dynamic_cast<CDockContainer*>(pDock->GetView())))\r
2002                 {\r
2003                         // Transfer any dock children to this docker\r
2004                         pDock->MoveDockChildren(this);\r
2005 \r
2006                         // Transfer container children to the target container\r
2007                         CDockContainer* pContainer = (CDockContainer*)GetView();\r
2008                         CDockContainer* pContainerSource = (CDockContainer*)pDock->GetView();\r
2009 \r
2010                         if (pContainerSource->GetAllContainers().size() > 1)\r
2011                         {\r
2012                                 // The container we're about to add has children, so transfer those first\r
2013                                 std::vector<ContainerInfo>::reverse_iterator riter;\r
2014                                 std::vector<ContainerInfo> AllContainers = pContainerSource->GetAllContainers();\r
2015                                 for ( riter = AllContainers.rbegin() ; riter < AllContainers.rend() -1; ++riter )\r
2016                                 {\r
2017                                         // Remove child container from pContainerSource\r
2018                                         CDockContainer* pContainerChild = (*riter).pContainer;\r
2019                                         pContainerChild->ShowWindow(SW_HIDE);\r
2020                                         pContainerSource->RemoveContainer(pContainerChild);\r
2021 \r
2022                                         // Add child container to this container\r
2023                                         pContainer->AddContainer(pContainerChild);\r
2024 \r
2025                                         CDocker* pDockChild = GetDockFromView(pContainerChild);\r
2026                                         pDockChild->SetParent(this);\r
2027                                         pDockChild->m_pDockParent = this;\r
2028                                 }\r
2029                         }\r
2030 \r
2031                         pContainer->AddContainer((CDockContainer*)pDock->GetView());\r
2032                         pDock->m_pDockParent = this;\r
2033                         pDock->m_BlockMove = FALSE;\r
2034                         pDock->ShowWindow(SW_HIDE);\r
2035                         pDock->SetWindowLongPtr(GWL_STYLE, WS_CHILD);\r
2036                         pDock->SetDockStyle(dwDockStyle);\r
2037                         pDock->SetParent(this);\r
2038                 }\r
2039         }\r
2040 \r
2041         inline void CDocker::DockOuter(CDocker* pDocker, DWORD dwDockStyle)\r
2042         // Docks the specified docker inside the dock ancestor\r
2043         {\r
2044                 assert(pDocker);\r
2045 \r
2046                 pDocker->m_pDockParent = GetDockAncestor();\r
2047 \r
2048                 DWORD OuterDocking = dwDockStyle & 0xF0000;\r
2049                 DWORD DockSide = OuterDocking / 0x10000;\r
2050                 dwDockStyle &= 0xFFF0FFFF;\r
2051                 dwDockStyle |= DockSide;\r
2052 \r
2053                 // Set the dock styles\r
2054                 DWORD dwStyle = WS_CHILD | WS_VISIBLE;\r
2055                 pDocker->m_BlockMove = FALSE;\r
2056                 pDocker->SetWindowLongPtr(GWL_STYLE, dwStyle);\r
2057                 pDocker->ShowWindow(SW_HIDE);\r
2058                 pDocker->SetDockStyle(dwDockStyle);\r
2059 \r
2060                 // Set the docking relationships\r
2061                 std::vector<CDocker*>::iterator iter = GetDockAncestor()->m_vDockChildren.begin();\r
2062                 GetDockAncestor()->m_vDockChildren.insert(iter, pDocker);\r
2063                 pDocker->SetParent(GetDockAncestor());\r
2064                 pDocker->GetDockBar().SetParent(GetDockAncestor());\r
2065 \r
2066                 // Limit the docked size to half the parent's size if it won't fit inside parent\r
2067                 if (((dwDockStyle & 0xF)  == DS_DOCKED_LEFT) || ((dwDockStyle &0xF)  == DS_DOCKED_RIGHT))\r
2068                 {\r
2069                         int Width = GetDockAncestor()->GetDockClient().GetWindowRect().Width();\r
2070                         int BarWidth = pDocker->GetBarWidth();\r
2071                         if (pDocker->m_DockStartSize >= (Width - BarWidth))\r
2072                                 pDocker->SetDockSize(MAX(Width/2 - BarWidth, BarWidth));\r
2073 \r
2074                         pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetDockAncestor()->GetWindowRect().Width();\r
2075                 }\r
2076                 else\r
2077                 {\r
2078                         int Height = GetDockAncestor()->GetDockClient().GetWindowRect().Height();\r
2079                         int BarWidth = pDocker->GetBarWidth();\r
2080                         if (pDocker->m_DockStartSize >= (Height - BarWidth))\r
2081                                 pDocker->SetDockSize(MAX(Height/2 - BarWidth, BarWidth));\r
2082 \r
2083                         pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetDockAncestor()->GetWindowRect().Height();\r
2084                 }\r
2085 \r
2086                 // Redraw the docked windows\r
2087                 GetAncestor()->SetFocus();\r
2088                 pDocker->GetView()->SetFocus();\r
2089                 RecalcDockLayout();\r
2090         }\r
2091 \r
2092         inline void CDocker::DrawAllCaptions()\r
2093         {\r
2094                 std::vector<DockPtr>::iterator iter;\r
2095                 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); iter++)\r
2096                 {\r
2097                         if ((*iter)->IsDocked())\r
2098                                 (*iter)->GetDockClient().DrawCaption((WPARAM)1);\r
2099                 } \r
2100         }\r
2101 \r
2102         inline void CDocker::DrawHashBar(HWND hBar, POINT Pos)\r
2103         // Draws a hashed bar while the splitter bar is being dragged\r
2104         {\r
2105                 CDocker* pDock = ((CDockBar*)FromHandle(hBar))->GetDock();\r
2106                 if (NULL == pDock) return;\r
2107 \r
2108                 BOOL bVertical = ((pDock->GetDockStyle() & 0xF) == DS_DOCKED_LEFT) || ((pDock->GetDockStyle() & 0xF) == DS_DOCKED_RIGHT);\r
2109 \r
2110                 CClientDC dcBar(this);\r
2111 \r
2112                 WORD HashPattern[] = {0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA};\r
2113                 CBitmap bmHash;\r
2114                 CBrush brDithered;\r
2115                 bmHash.CreateBitmap(8, 8, 1, 1, HashPattern);\r
2116                 brDithered.CreatePatternBrush(&bmHash);\r
2117                 dcBar.SelectObject(&brDithered);\r
2118 \r
2119                 CRect rc = FromHandle(hBar)->GetWindowRect();\r
2120                 ScreenToClient(rc);\r
2121                 int cx = rc.Width();\r
2122                 int cy = rc.Height();\r
2123                 int BarWidth = pDock->GetDockBar().GetWidth();\r
2124 \r
2125                 if (bVertical)\r
2126                         dcBar.PatBlt(Pos.x - BarWidth/2, rc.top, BarWidth, cy, PATINVERT);\r
2127                 else\r
2128                         dcBar.PatBlt(rc.left, Pos.y - BarWidth/2, cx, BarWidth, PATINVERT);\r
2129         }\r
2130         \r
2131         inline CDockContainer* CDocker::GetContainer() const\r
2132         {\r
2133                 CDockContainer* pContainer = NULL;\r
2134                 if (dynamic_cast<CDockContainer*>(GetView()))\r
2135                         pContainer = (CDockContainer*)GetView();\r
2136 \r
2137                 return pContainer;\r
2138         }\r
2139 \r
2140         inline CDocker* CDocker::GetActiveDocker() const\r
2141         // Returns the docker whose child window has focus\r
2142         {\r
2143                 CWnd* pWnd = GetFocus();\r
2144                 CDocker* pDock= NULL;\r
2145                 while (pWnd && (pDock == NULL))\r
2146                 {\r
2147                         if (IsRelated(pWnd))\r
2148                                 pDock = (CDocker*)pWnd;\r
2149 \r
2150                         pWnd = pWnd->GetParent();\r
2151                 }\r
2152 \r
2153                 return pDock;\r
2154         }\r
2155 \r
2156         inline CDocker* CDocker::GetDockAncestor() const\r
2157         // The GetDockAncestor function retrieves the pointer to the\r
2158         //  ancestor (root docker parent) of the Docker.\r
2159         {\r
2160                 return m_pDockAncestor;\r
2161         }\r
2162 \r
2163         inline CDocker* CDocker::GetDockFromPoint(POINT pt) const\r
2164         // Retrieves the Docker whose view window contains the specified point\r
2165         {\r
2166                 // Step 1: Find the top level Docker the point is over\r
2167                 CDocker* pDockTop = NULL;\r
2168                 CWnd* pAncestor = GetDockAncestor()->GetAncestor();\r
2169 \r
2170                 // Iterate through all top level windows\r
2171                 CWnd* pWnd = GetWindow(GW_HWNDFIRST);\r
2172                 while(pWnd)\r
2173                 {\r
2174                         if (IsRelated(pWnd) || pWnd == pAncestor)\r
2175                         {\r
2176                                 CDocker* pDockTest;\r
2177                                 if (pWnd == pAncestor)\r
2178                                         pDockTest = GetDockAncestor();\r
2179                                 else\r
2180                                         pDockTest = (CDocker*)pWnd;\r
2181 \r
2182                                 CRect rc = pDockTest->GetClientRect();\r
2183                                 pDockTest->ClientToScreen(rc);\r
2184                                 if ((this != pDockTest) && rc.PtInRect(pt))\r
2185                                 {\r
2186                                         pDockTop = pDockTest;\r
2187                                         break;\r
2188                                 }\r
2189                         }\r
2190 \r
2191                         pWnd = pWnd->GetWindow(GW_HWNDNEXT);\r
2192                 }\r
2193 \r
2194                 // Step 2: Find the docker child whose view window has the point\r
2195                 CDocker* pDockTarget = NULL;\r
2196                 if (pDockTop)\r
2197                 {\r
2198                         CDocker* pDockParent = pDockTop;\r
2199                         CDocker* pDockTest = pDockParent;\r
2200 \r
2201                         while (IsRelated(pDockTest))\r
2202                         {\r
2203                                 pDockParent = pDockTest;\r
2204                                 CPoint ptLocal = pt;\r
2205                                 pDockParent->ScreenToClient(ptLocal);\r
2206                                 pDockTest = (CDocker*)pDockParent->ChildWindowFromPoint(ptLocal);\r
2207                                 assert (pDockTest != pDockParent);\r
2208                         }\r
2209 \r
2210                         CRect rc = pDockParent->GetDockClient().GetWindowRect();\r
2211                         if (rc.PtInRect(pt)) pDockTarget = pDockParent;\r
2212                 }\r
2213 \r
2214                 return pDockTarget;\r
2215         }\r
2216 \r
2217         inline CDocker* CDocker::GetDockFromID(int n_DockID) const\r
2218         {\r
2219                 std::vector <DockPtr>::iterator v;\r
2220 \r
2221                 if (GetDockAncestor())\r
2222                 {\r
2223                         for (v = GetDockAncestor()->m_vAllDockers.begin(); v != GetDockAncestor()->m_vAllDockers.end(); v++)\r
2224                         {\r
2225                                 if (n_DockID == (*v)->GetDockID())\r
2226                                         return (*v).get();\r
2227                         }\r
2228                 }\r
2229 \r
2230                 return 0;\r
2231         }\r
2232 \r
2233         inline CDocker* CDocker::GetDockFromView(CWnd* pView) const\r
2234         {\r
2235                 CDocker* pDock = 0;\r
2236                 std::vector<DockPtr>::iterator iter;\r
2237                 std::vector<DockPtr> AllDockers = GetAllDockers();\r
2238                 for (iter = AllDockers.begin(); iter != AllDockers.end(); ++iter)\r
2239                 {\r
2240                         if ((*iter)->GetView() == pView)\r
2241                                 pDock = (*iter).get();\r
2242                 }\r
2243 \r
2244                 if (GetDockAncestor()->GetView() == pView)\r
2245                         pDock = GetDockAncestor();\r
2246 \r
2247                 return pDock;\r
2248         }\r
2249 \r
2250         inline int CDocker::GetDockSize() const\r
2251         {\r
2252                 // Returns the size of the docker to be used if it is redocked\r
2253                 // Note: This function returns 0 if the docker has the DS_DOCKED_CONTAINER style\r
2254 \r
2255                 CRect rcParent;\r
2256                 if (GetDockParent())\r
2257                         rcParent = GetDockParent()->GetWindowRect();\r
2258                 else\r
2259                         rcParent = GetDockAncestor()->GetWindowRect();\r
2260 \r
2261                 double DockSize = 0;\r
2262                 if ((GetDockStyle() & DS_DOCKED_LEFT) || (GetDockStyle() & DS_DOCKED_RIGHT))\r
2263                         DockSize = (double)(rcParent.Width()*m_DockSizeRatio);\r
2264                 else if ((GetDockStyle() & DS_DOCKED_TOP) || (GetDockStyle() & DS_DOCKED_BOTTOM))\r
2265                         DockSize = (double)(rcParent.Height()*m_DockSizeRatio);\r
2266                 else if ((GetDockStyle() & DS_DOCKED_CONTAINER))\r
2267                         DockSize = 0;\r
2268 \r
2269                 return (int)DockSize;\r
2270         }\r
2271 \r
2272         inline CDocker* CDocker::GetTopmostDocker() const\r
2273         // Returns the docker's parent at the top of the Z order.\r
2274         // Could be the dock ancestor or an undocked docker.\r
2275         {\r
2276                 CDocker* pDockTopLevel = (CDocker* const)this;\r
2277 \r
2278                 while(pDockTopLevel->GetDockParent())\r
2279                 {\r
2280                         assert (pDockTopLevel != pDockTopLevel->GetDockParent());\r
2281                         pDockTopLevel = pDockTopLevel->GetDockParent();\r
2282                 }\r
2283 \r
2284                 return pDockTopLevel;\r
2285         }\r
2286 \r
2287         inline CTabbedMDI* CDocker::GetTabbedMDI() const\r
2288         {\r
2289                 CTabbedMDI* pTabbedMDI = NULL;\r
2290                 if (dynamic_cast<CTabbedMDI*>(GetView()))\r
2291                         pTabbedMDI = (CTabbedMDI*)GetView();\r
2292 \r
2293                 return pTabbedMDI;\r
2294         }\r
2295 \r
2296         inline int CDocker::GetTextHeight()\r
2297         {\r
2298                 NONCLIENTMETRICS nm = {0};\r
2299                 nm.cbSize = GetSizeofNonClientMetrics();\r
2300                 SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &nm, 0);\r
2301                 LOGFONT lf = nm.lfStatusFont;\r
2302 \r
2303                 CClientDC dc(this);\r
2304                 dc.CreateFontIndirect(&lf);\r
2305                 CSize szText = dc.GetTextExtentPoint32(_T("Text"), lstrlen(_T("Text")));\r
2306                 return szText.cy;\r
2307         }\r
2308 \r
2309         inline void CDocker::Hide()\r
2310         {\r
2311                 // Undocks a docker (if needed) and hides it.\r
2312                 // Do unhide the docker, dock it.\r
2313 \r
2314                 if (IsDocked())\r
2315                 {\r
2316                         if (dynamic_cast<CDockContainer*>(GetView()))\r
2317                         {\r
2318                                 CDockContainer* pContainer = GetContainer();\r
2319                                 CDocker* pDock = GetDockFromView(pContainer->GetContainerParent());\r
2320                                 pDock->UndockContainer(pContainer, GetCursorPos(), FALSE);\r
2321                         }\r
2322                         else\r
2323                         {\r
2324                                 CDocker* pDockUndockedFrom = SeparateFromDock();\r
2325                                 pDockUndockedFrom->RecalcDockLayout();\r
2326                         }\r
2327                 }\r
2328 \r
2329                 ShowWindow(SW_HIDE);\r
2330         }\r
2331 \r
2332         inline BOOL CDocker::IsChildOfDocker(CWnd* pWnd) const\r
2333         // returns true if the specified window is a child of this docker\r
2334         {\r
2335                 while ((pWnd != NULL) && (pWnd != GetDockAncestor()))\r
2336                 {\r
2337                         if (pWnd == (CWnd*)this) return TRUE;\r
2338                         if (IsRelated(pWnd)) break;\r
2339                         pWnd = pWnd->GetParent();\r
2340                 }\r
2341 \r
2342                 return FALSE;\r
2343         }\r
2344 \r
2345         inline BOOL CDocker::IsDocked() const\r
2346         {\r
2347                 return (((m_DockStyle&0xF) || (m_DockStyle & DS_DOCKED_CONTAINER)) && !m_Undocking); // Boolean expression\r
2348         }\r
2349 \r
2350         inline BOOL CDocker::IsDragAutoResize()\r
2351         {\r
2352                 return m_bDragAutoResize;\r
2353         }\r
2354 \r
2355         inline BOOL CDocker::IsRelated(CWnd* pWnd) const\r
2356         // Returns TRUE if the hWnd is a docker within this dock family\r
2357         {\r
2358                 if (GetDockAncestor() == pWnd) return TRUE;\r
2359 \r
2360                 std::vector<DockPtr>::iterator iter;\r
2361                 for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)\r
2362                 {\r
2363                         if ((*iter).get() == pWnd) return TRUE;\r
2364                 }\r
2365 \r
2366                 return FALSE;\r
2367         }\r
2368 \r
2369         inline BOOL CDocker::IsUndocked() const\r
2370         {\r
2371                 return (!((m_DockStyle&0xF)|| (m_DockStyle & DS_DOCKED_CONTAINER)) && !m_Undocking); // Boolean expression\r
2372         }\r
2373 \r
2374         inline BOOL CDocker::LoadRegistrySettings(LPCTSTR szRegistryKeyName)\r
2375         // Recreates the docker layout based on information stored in the registry.\r
2376         // Assumes the DockAncestor window is already created.\r
2377         {\r
2378                 BOOL bResult = FALSE;\r
2379 \r
2380                 if (szRegistryKeyName)\r
2381                 {\r
2382                         std::vector<DockInfo> vDockList;\r
2383                         std::vector<int> vActiveContainers;\r
2384 \r
2385                         CString strKey = _T("Software\\") + CString(szRegistryKeyName) + _T("\\Dock Windows");\r
2386                         HKEY hKey = 0;\r
2387                         RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey);\r
2388                         if (hKey)\r
2389                         {\r
2390                                 DWORD dwType = REG_BINARY;\r
2391                                 DWORD BufferSize = sizeof(DockInfo);\r
2392                                 DockInfo di;\r
2393                                 int i = 0;\r
2394                                 TCHAR szNumber[20];\r
2395                                 CString strSubKey = _T("DockChild");\r
2396                                 strSubKey += _itot(i, szNumber, 10);\r
2397 \r
2398                                 // Fill the DockList vector from the registry\r
2399                                 while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&di, &BufferSize))\r
2400                                 {\r
2401                                         vDockList.push_back(di);\r
2402                                         i++;\r
2403                                         strSubKey = _T("DockChild");\r
2404                                         strSubKey += _itot(i, szNumber, 10);\r
2405                                 }\r
2406 \r
2407                                 dwType = REG_DWORD;\r
2408                                 BufferSize = sizeof(int);\r
2409                                 int nID;\r
2410                                 i = 0;\r
2411                                 strSubKey = _T("ActiveContainer");\r
2412                                 strSubKey += _itot(i, szNumber, 10);\r
2413                                 \r
2414                                 // Fill the DockList vector from the registry\r
2415                                 while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&nID, &BufferSize))\r
2416                                 {\r
2417                                         vActiveContainers.push_back(nID);\r
2418                                         i++;\r
2419                                         strSubKey = _T("ActiveContainer");\r
2420                                         strSubKey += _itot(i, szNumber, 10);\r
2421                                 }\r
2422 \r
2423                                 RegCloseKey(hKey);\r
2424                                 if (vDockList.size() > 0) bResult = TRUE;\r
2425                         }\r
2426 \r
2427                         // Add dockers without parents first\r
2428                         std::vector<DockInfo>::iterator iter;\r
2429                         for (iter = vDockList.begin(); iter < vDockList.end() ; ++iter)\r
2430                         {\r
2431                                 DockInfo di = (*iter);\r
2432                                 if (di.DockParentID == 0)\r
2433                                 {\r
2434                                         CDocker* pDocker = NewDockerFromID(di.DockID);\r
2435                                         if (pDocker)\r
2436                                         {\r
2437                                                 if (di.DockStyle & 0xF)\r
2438                                                         AddDockedChild(pDocker, di.DockStyle, di.DockSize, di.DockID);\r
2439                                                 else\r
2440                                                         AddUndockedChild(pDocker, di.DockStyle, di.DockSize, di.Rect, di.DockID);\r
2441                                         }\r
2442                                         else\r
2443                                         {\r
2444                                                 TRACE(_T("Failed to add dockers without parents from registry"));\r
2445                                                 bResult = FALSE;\r
2446                                         }\r
2447                                 }\r
2448                         }\r
2449 \r
2450                         // Remove dockers without parents from vDockList\r
2451                         for (UINT n = (UINT)vDockList.size(); n > 0; --n)\r
2452                         {\r
2453                                 iter = vDockList.begin() + n-1;\r
2454                                 if ((*iter).DockParentID == 0)\r
2455                                         vDockList.erase(iter);\r
2456                         }\r
2457 \r
2458                         // Add remaining dockers\r
2459                         while (vDockList.size() > 0)\r
2460                         {\r
2461                                 bool bFound = false;\r
2462                                 std::vector<DockInfo>::iterator iter;\r
2463                                 for (iter = vDockList.begin(); iter < vDockList.end(); ++iter)\r
2464                                 {\r
2465                                         DockInfo di = *iter;\r
2466                                         CDocker* pDockParent = GetDockFromID(di.DockParentID);\r
2467 \r
2468                                         if (pDockParent != 0)\r
2469                                         {\r
2470                                                 CDocker* pDock = NewDockerFromID(di.DockID);\r
2471                                                 if(pDock)\r
2472                                                 {\r
2473                                                         pDockParent->AddDockedChild(pDock, di.DockStyle, di.DockSize, di.DockID);\r
2474                                                         bFound = true;\r
2475                                                 }\r
2476                                                 else\r
2477                                                 {\r
2478                                                         TRACE(_T("Failed to add dockers with parents from registry"));\r
2479                                                         bResult = FALSE;\r
2480                                                 }\r
2481 \r
2482                                                 vDockList.erase(iter);\r
2483                                                 break;\r
2484                                         }\r
2485                                 }\r
2486 \r
2487                                 if (!bFound)\r
2488                                 {\r
2489                                         TRACE(_T("Orphaned dockers stored in registry "));\r
2490                                         bResult = FALSE;\r
2491                                         break;\r
2492                                 }\r
2493                         }\r
2494 \r
2495                         std::vector<int>::iterator iterID;\r
2496                         for (iterID = vActiveContainers.begin(); iterID < vActiveContainers.end(); ++iterID)\r
2497                         {\r
2498                                 CDocker* pDocker = GetDockFromID(*iterID);\r
2499                                 if (pDocker)\r
2500                                 {\r
2501                                         CDockContainer* pContainer = pDocker->GetContainer();\r
2502                                         if (pContainer)\r
2503                                         {\r
2504                                                 int nPage = pContainer->GetContainerIndex(pContainer);\r
2505                                                 if (nPage >= 0)\r
2506                                                         pContainer->SelectPage(nPage);\r
2507                                         }\r
2508                                 }\r
2509                         }\r
2510                 }\r
2511 \r
2512                 if (!bResult) CloseAllDockers();\r
2513                 return bResult;\r
2514         }\r
2515 \r
2516         inline void CDocker::MoveDockChildren(CDocker* pDockTarget)\r
2517         // Used internally by Dock and Undock\r
2518         {\r
2519                 assert(pDockTarget);\r
2520 \r
2521                 // Transfer any dock children from the current docker to the target docker\r
2522                 std::vector<CDocker*>::iterator iter;\r
2523                 for (iter = GetDockChildren().begin(); iter < GetDockChildren().end(); ++iter)\r
2524                 {\r
2525                         pDockTarget->GetDockChildren().push_back(*iter);\r
2526                         (*iter)->m_pDockParent = pDockTarget;\r
2527                         (*iter)->SetParent(pDockTarget);\r
2528                         (*iter)->GetDockBar().SetParent(pDockTarget);\r
2529                 }\r
2530                 GetDockChildren().clear();\r
2531         }\r
2532 \r
2533         inline CDocker* CDocker::NewDockerFromID(int nID)\r
2534         // Used in LoadRegistrySettings. Creates a new Docker from the specified ID\r
2535         {\r
2536                 UNREFERENCED_PARAMETER(nID);\r
2537 \r
2538                 // Override this function to create the Docker objects as shown below\r
2539 \r
2540                 CDocker* pDock = NULL;\r
2541         /*      switch(nID)\r
2542                 {\r
2543                 case ID_CLASSES:\r
2544                         pDock = new CDockClasses;\r
2545                         break;\r
2546                 case ID_FILES:\r
2547                         pDock = new CDockFiles;\r
2548                         break;\r
2549                 default:\r
2550                         TRACE(_T("Unknown Dock ID\n"));\r
2551                         break;\r
2552                 } */\r
2553 \r
2554                 return pDock;\r
2555         }\r
2556 \r
2557         inline void CDocker::OnActivate(WPARAM wParam, LPARAM lParam)\r
2558         {\r
2559                 UNREFERENCED_PARAMETER(lParam);\r
2560 \r
2561                 // Only top level undocked dockers get this message\r
2562                 if (LOWORD(wParam) == WA_INACTIVE)\r
2563                 {\r
2564                         GetTopmostDocker()->m_hOldFocus = ::GetFocus();\r
2565 \r
2566                         // Send a notification of focus lost\r
2567                         int idCtrl = ::GetDlgCtrlID(m_hOldFocus);\r
2568                         NMHDR nhdr={0};\r
2569                         nhdr.hwndFrom = m_hOldFocus;\r
2570                         nhdr.idFrom = idCtrl;\r
2571                         nhdr.code = UWM_FRAMELOSTFOCUS;\r
2572                         SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);\r
2573                 }\r
2574         }\r
2575 \r
2576         inline void CDocker::OnCaptionTimer(WPARAM wParam, LPARAM lParam)\r
2577         {\r
2578                 UNREFERENCED_PARAMETER(lParam);\r
2579 \r
2580                 if (this == GetDockAncestor())\r
2581                 {\r
2582                         if (wParam == 1)\r
2583                         {\r
2584                                 DrawAllCaptions();\r
2585                                 m_nTimerCount++;\r
2586                                 if (m_nTimerCount == 10)\r
2587                                 {\r
2588                                         KillTimer(wParam);\r
2589                                         m_nTimerCount = 0;\r
2590                                 }\r
2591                         }\r
2592                 }\r
2593         }\r
2594 \r
2595         inline void CDocker::OnCreate()\r
2596         {\r
2597 \r
2598 #if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)\r
2599                 if (GetParent()->GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)\r
2600                 {\r
2601                         DWORD dwExStyle = (DWORD)GetWindowLongPtr(GWL_EXSTYLE);\r
2602                         SetWindowLongPtr(GWL_EXSTYLE, dwExStyle | WS_EX_LAYOUTRTL);\r
2603                 }\r
2604 #endif\r
2605 \r
2606                 // Create the various child windows\r
2607                 GetDockClient().SetDock(this);\r
2608                 GetDockClient().Create(this);\r
2609 \r
2610                 assert(GetView());                      // Use SetView in CMainFrame's constructor to set the view window\r
2611                 GetView()->Create(&GetDockClient());\r
2612 \r
2613                 // Create the slider bar belonging to this docker\r
2614                 GetDockBar().SetDock(this);\r
2615                 if (GetDockAncestor() != this)\r
2616                         GetDockBar().Create(GetParent());\r
2617 \r
2618                 // Now remove the WS_POPUP style. It was required to allow this window\r
2619                 // to be owned by the frame window.\r
2620                 SetWindowLongPtr(GWL_STYLE, WS_CHILD);\r
2621                 SetParent(GetParent());         // Reinstate the window's parent\r
2622 \r
2623                 // Set the default colour for the splitter bar\r
2624                 COLORREF rgbColour = GetSysColor(COLOR_BTNFACE);\r
2625                 CWnd* pFrame = GetDockAncestor()->GetAncestor();\r
2626                 ReBarTheme* pTheme = (ReBarTheme*)pFrame->SendMessage(UWM_GETREBARTHEME, 0, 0);\r
2627 \r
2628                 if (pTheme && pTheme->UseThemes && pTheme->clrBkgnd2 != 0)\r
2629                                 rgbColour =pTheme->clrBkgnd2;\r
2630 \r
2631                 SetBarColor(rgbColour);\r
2632 \r
2633                 // Set the caption height based on text height\r
2634                 m_NCHeight = MAX(20, GetTextHeight() + 5);\r
2635         }\r
2636 \r
2637         inline void CDocker::OnDestroy(WPARAM wParam, LPARAM lParam)\r
2638         {\r
2639                 UNREFERENCED_PARAMETER(wParam);\r
2640                 UNREFERENCED_PARAMETER(lParam);\r
2641 \r
2642                 // Destroy any dock children first\r
2643                 std::vector<CDocker*>::iterator iter;\r
2644                 for (iter = GetDockChildren().begin(); iter < GetDockChildren().end(); ++iter)\r
2645                 {\r
2646                         (*iter)->Destroy();\r
2647                 }\r
2648 \r
2649                 if (dynamic_cast<CDockContainer*>(GetView()) && IsUndocked())\r
2650                 {\r
2651                         CDockContainer* pContainer = (CDockContainer*)GetView();\r
2652                         if (pContainer->GetAllContainers().size() > 1)\r
2653                         {\r
2654                                 // This container has children, so destroy them now\r
2655                                 std::vector<ContainerInfo> AllContainers = pContainer->GetAllContainers();\r
2656                                 std::vector<ContainerInfo>::iterator iter;\r
2657                                 for (iter = AllContainers.begin(); iter < AllContainers.end(); ++iter)\r
2658                                 {\r
2659                                         if ((*iter).pContainer != pContainer)\r
2660                                         {\r
2661                                                 // Reset container parent before destroying the dock window\r
2662                                                 CDocker* pDock = GetDockFromView((*iter).pContainer);\r
2663                                                 if (pContainer->IsWindow())\r
2664                                                         pContainer->SetParent(&pDock->GetDockClient());\r
2665 \r
2666                                                 pDock->Destroy();\r
2667                                         }\r
2668                                 }\r
2669                         }\r
2670                 }\r
2671 \r
2672                 GetDockBar().Destroy();\r
2673 \r
2674                 // Post a destroy docker message\r
2675                 if ( GetDockAncestor()->IsWindow() )\r
2676                         GetDockAncestor()->PostMessage(UWM_DOCK_DESTROYED, (WPARAM)this, 0L);\r
2677         }\r
2678 \r
2679         inline void CDocker::OnDockDestroyed(WPARAM wParam, LPARAM lParam)\r
2680         {\r
2681                 UNREFERENCED_PARAMETER(lParam);\r
2682 \r
2683                 CDocker* pDock = (CDocker*)wParam;\r
2684 \r
2685                 assert( this == GetDockAncestor() );\r
2686                 std::vector<DockPtr>::iterator iter;\r
2687                 for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)\r
2688                 {\r
2689                         if ((*iter).get() == pDock)\r
2690                         {\r
2691                                 GetAllDockers().erase(iter);\r
2692                                 break;\r
2693                         }\r
2694                 }\r
2695         }\r
2696 \r
2697         inline void CDocker::OnExitSizeMove(WPARAM wParam, LPARAM lParam)\r
2698         {\r
2699                 UNREFERENCED_PARAMETER(wParam);\r
2700                 UNREFERENCED_PARAMETER(lParam);\r
2701 \r
2702                 m_BlockMove = FALSE;\r
2703                 m_bIsDragging = FALSE;\r
2704                 SendNotify(UWM_DOCK_END);\r
2705         }\r
2706 \r
2707         inline LRESULT CDocker::OnNotify(WPARAM wParam, LPARAM lParam)\r
2708         {\r
2709                 UNREFERENCED_PARAMETER(wParam);\r
2710                 LPDRAGPOS pdp = (LPDRAGPOS)lParam;\r
2711 \r
2712                 switch (((LPNMHDR)lParam)->code)\r
2713                 {\r
2714                 case UWM_DOCK_START:\r
2715                         {\r
2716                                 if (IsDocked())\r
2717                                 {\r
2718                                         Undock(GetCursorPos());\r
2719                                         SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pdp->ptPos.x, pdp->ptPos.y));\r
2720                                 }\r
2721                         }\r
2722                         break;\r
2723 \r
2724                 case UWM_DOCK_MOVE:\r
2725                         {\r
2726                                 CheckAllTargets((LPDRAGPOS)lParam);\r
2727                         }\r
2728                         break;\r
2729 \r
2730                 case UWM_DOCK_END:\r
2731                         {\r
2732                                 CDocker* pDock = (CDocker*)FromHandle(pdp->hdr.hwndFrom);\r
2733                                 if (NULL == pDock) break;\r
2734 \r
2735                                 UINT DockZone = pdp->DockZone;\r
2736                                 CRect rc = pDock->GetWindowRect();\r
2737 \r
2738                                 switch(DockZone)\r
2739                                 {\r
2740                                 case DS_DOCKED_LEFT:\r
2741                                 case DS_DOCKED_RIGHT:\r
2742                                         pDock->SetDockSize(rc.Width());\r
2743                                         Dock(pDock, pDock->GetDockStyle() | DockZone);\r
2744                                         break;\r
2745                                 case DS_DOCKED_TOP:\r
2746                                 case DS_DOCKED_BOTTOM:\r
2747                                         pDock->SetDockSize(rc.Height());\r
2748                                         Dock(pDock, pDock->GetDockStyle() | DockZone);\r
2749                                         break;\r
2750                                 case DS_DOCKED_CONTAINER:\r
2751                                         {\r
2752                                                 DockInContainer(pDock, pDock->GetDockStyle() | DockZone);\r
2753                                                 CDockContainer* pContainer = (CDockContainer*)GetView();\r
2754                                                 int nPage = pContainer->GetContainerIndex((CDockContainer*)pDock->GetView());\r
2755                                                 pContainer->SelectPage(nPage);\r
2756                                         }\r
2757                                         break;\r
2758                                 case DS_DOCKED_LEFTMOST:\r
2759                                 case DS_DOCKED_RIGHTMOST:\r
2760                                         pDock->SetDockSize(rc.Width());\r
2761                                         DockOuter(pDock, pDock->GetDockStyle() | DockZone);\r
2762                                         break;\r
2763                                 case DS_DOCKED_TOPMOST:\r
2764                                 case DS_DOCKED_BOTTOMMOST:\r
2765                                         pDock->SetDockSize(rc.Height());\r
2766                                         DockOuter(pDock, pDock->GetDockStyle() | DockZone);\r
2767                                         break;\r
2768                                 }\r
2769 \r
2770                                 GetDockHint().Destroy();\r
2771                                 CloseAllTargets();\r
2772                         }\r
2773                         break;\r
2774 \r
2775                 case UWM_BAR_START:\r
2776                         {\r
2777                                 CPoint pt = pdp->ptPos;\r
2778                                 ScreenToClient(pt);\r
2779                                 if (!IsDragAutoResize())\r
2780                                         DrawHashBar(pdp->hdr.hwndFrom, pt);\r
2781                                 m_OldPoint = pt;\r
2782                         }\r
2783                         break;\r
2784 \r
2785                 case UWM_BAR_MOVE:\r
2786                         {\r
2787                                 CPoint pt = pdp->ptPos;\r
2788                                 ScreenToClient(pt);\r
2789 \r
2790                                 if (pt != m_OldPoint)\r
2791                                 {\r
2792                                         if (IsDragAutoResize())\r
2793                                                 ResizeDockers(pdp);\r
2794                                         else\r
2795                                         {\r
2796                                                 DrawHashBar(pdp->hdr.hwndFrom, m_OldPoint);\r
2797                                                 DrawHashBar(pdp->hdr.hwndFrom, pt);\r
2798                                         }\r
2799 \r
2800                                         m_OldPoint = pt;\r
2801                                 }\r
2802                         }\r
2803                         break;\r
2804 \r
2805                 case UWM_BAR_END:\r
2806                         {\r
2807                                 POINT pt = pdp->ptPos;\r
2808                                 ScreenToClient(pt);\r
2809 \r
2810                                 if (!IsDragAutoResize())\r
2811                                         DrawHashBar(pdp->hdr.hwndFrom, pt);\r
2812 \r
2813                                 ResizeDockers(pdp);\r
2814                         }\r
2815                         break;\r
2816                 case NM_SETFOCUS:\r
2817                         if (GetDockAncestor()->IsWindow())\r
2818                                 GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);\r
2819                         break;\r
2820                 case UWM_FRAMEGOTFOCUS:\r
2821                         if (GetDockAncestor()->IsWindow())\r
2822                                 GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);\r
2823                         if (GetView()->IsWindow())\r
2824                                 GetView()->SendMessage(WM_NOTIFY, wParam, lParam);\r
2825                         break;\r
2826                 case UWM_FRAMELOSTFOCUS:\r
2827                         if (GetDockAncestor()->IsWindow())\r
2828                                 GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);\r
2829                         if (GetView()->IsWindow())\r
2830                                 GetView()->SendMessage(WM_NOTIFY, wParam, lParam);\r
2831                         break;\r
2832                 }\r
2833                 return 0L;\r
2834         }\r
2835 \r
2836         inline void CDocker::ResizeDockers(LPDRAGPOS pdp)\r
2837         // Called when the docker's splitter bar is dragged\r
2838         {\r
2839                 assert(pdp);\r
2840 \r
2841                 POINT pt = pdp->ptPos;\r
2842                 ScreenToClient(pt);\r
2843 \r
2844                 CDocker* pDock = ((CDockBar*)FromHandle(pdp->hdr.hwndFrom))->GetDock();\r
2845                 if (NULL == pDock) return;\r
2846 \r
2847                 RECT rcDock = pDock->GetWindowRect();\r
2848                 ScreenToClient(rcDock);\r
2849 \r
2850                 double dBarWidth = pDock->GetDockBar().GetWidth();\r
2851                 int iBarWidth    = pDock->GetDockBar().GetWidth();\r
2852                 int DockSize;\r
2853 \r
2854                 switch (pDock->GetDockStyle() & 0xF)\r
2855                 {\r
2856                 case DS_DOCKED_LEFT:\r
2857                         DockSize = MAX(pt.x, iBarWidth/2) - rcDock.left - (int)(.5* dBarWidth);\r
2858                         DockSize = MAX(-iBarWidth, DockSize);\r
2859                         pDock->SetDockSize(DockSize);\r
2860                         pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Width());\r
2861                         break;\r
2862                 case DS_DOCKED_RIGHT:\r
2863                         DockSize = rcDock.right - MAX(pt.x, iBarWidth/2) - (int)(.5* dBarWidth);\r
2864                         DockSize = MAX(-iBarWidth, DockSize);\r
2865                         pDock->SetDockSize(DockSize);\r
2866                         pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Width());\r
2867                         break;\r
2868                 case DS_DOCKED_TOP:\r
2869                         DockSize = MAX(pt.y, iBarWidth/2) - rcDock.top - (int)(.5* dBarWidth);\r
2870                         DockSize = MAX(-iBarWidth, DockSize);\r
2871                         pDock->SetDockSize(DockSize);\r
2872                         pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Height());\r
2873                         break;\r
2874                 case DS_DOCKED_BOTTOM:\r
2875                         DockSize = rcDock.bottom - MAX(pt.y, iBarWidth/2) - (int)(.5* dBarWidth);\r
2876                         DockSize = MAX(-iBarWidth, DockSize);\r
2877                         pDock->SetDockSize(DockSize);\r
2878                         pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Height());\r
2879                         break;\r
2880                 }\r
2881 \r
2882                 RecalcDockLayout();\r
2883         }\r
2884 \r
2885         inline void CDocker::OnSetFocus(WPARAM wParam, LPARAM lParam)\r
2886         {\r
2887                 UNREFERENCED_PARAMETER(wParam);\r
2888                 UNREFERENCED_PARAMETER(lParam);\r
2889 \r
2890                 if (IsUndocked() && m_hOldFocus)\r
2891                         ::SetFocus(m_hOldFocus);\r
2892                 else\r
2893                         // Pass focus on the the view window\r
2894                         GetView()->SetFocus();\r
2895 \r
2896                 if ((this == GetTopmostDocker()) && (this != GetDockAncestor()))\r
2897                 {\r
2898                         // Send a notification to top level window\r
2899                         int idCtrl = ::GetDlgCtrlID(m_hOldFocus);\r
2900                         NMHDR nhdr={0};\r
2901                         nhdr.hwndFrom = m_hOldFocus;\r
2902                         nhdr.idFrom = idCtrl;\r
2903                         nhdr.code = NM_SETFOCUS;\r
2904                         SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);\r
2905                 }\r
2906         }\r
2907 \r
2908         inline void CDocker::OnSysColorChange(WPARAM wParam, LPARAM lParam)\r
2909         {\r
2910                 UNREFERENCED_PARAMETER(wParam);\r
2911                 UNREFERENCED_PARAMETER(lParam);\r
2912 \r
2913                 if (this == GetDockAncestor())\r
2914                 {\r
2915                         COLORREF rgbColour = GetSysColor(COLOR_BTNFACE);\r
2916                         CWnd* pFrame = GetDockAncestor()->GetAncestor();\r
2917                         ReBarTheme* pTheme = (ReBarTheme*)pFrame->SendMessage(UWM_GETREBARTHEME, 0, 0);\r
2918 \r
2919                         if (pTheme && pTheme->UseThemes && pTheme->clrBand2 != 0)\r
2920                                 rgbColour = pTheme->clrBkgnd2;\r
2921                         else\r
2922                                 rgbColour = GetSysColor(COLOR_BTNFACE);\r
2923 \r
2924                         // Set the splitter bar colour for each docker decendant\r
2925                         std::vector<DockPtr>::iterator iter;\r
2926                         for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)\r
2927                                 (*iter)->SetBarColor(rgbColour);\r
2928 \r
2929                         // Set the splitter bar colour for the docker ancestor\r
2930                         SetBarColor(rgbColour);\r
2931                 }\r
2932         }\r
2933 \r
2934         inline LRESULT CDocker::OnSysCommand(WPARAM wParam, LPARAM lParam)\r
2935         {\r
2936                 switch(wParam&0xFFF0)\r
2937                 {\r
2938                 case SC_MOVE:\r
2939                         // An undocked docker is being moved\r
2940                         {\r
2941                                 BOOL bResult = FALSE;\r
2942                                 m_bIsDragging = TRUE;\r
2943                                 SetCursor(LoadCursor(NULL, IDC_ARROW));\r
2944 \r
2945                                 if (SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &bResult, 0))\r
2946                                 {\r
2947                                         // Turn on DragFullWindows for this move\r
2948                                         SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, 0, 0);\r
2949 \r
2950                                         // Process this message\r
2951                                         DefWindowProc(WM_SYSCOMMAND, wParam, lParam);\r
2952 \r
2953                                         // Return DragFullWindows to its previous state\r
2954                                         SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, bResult, 0, 0);\r
2955                                         return 0L;\r
2956                                 }\r
2957                         }\r
2958                         break;\r
2959                 case SC_CLOSE:\r
2960                         // The close button is pressed on an undocked docker\r
2961                         m_bIsClosing = TRUE;\r
2962                         break;\r
2963                 }\r
2964                 return CWnd::WndProcDefault(WM_SYSCOMMAND, wParam, lParam);\r
2965         }\r
2966 \r
2967         inline LRESULT CDocker::OnWindowPosChanging(WPARAM wParam, LPARAM lParam)\r
2968         {\r
2969                 // Suspend dock drag moving while over dock zone\r
2970                 if (m_BlockMove)\r
2971                 {\r
2972                 LPWINDOWPOS pWndPos = (LPWINDOWPOS)lParam;\r
2973                         pWndPos->flags |= SWP_NOMOVE|SWP_FRAMECHANGED;\r
2974                         return 0;\r
2975                 }\r
2976 \r
2977                 return CWnd::WndProcDefault(WM_WINDOWPOSCHANGING, wParam, lParam);\r
2978         }\r
2979 \r
2980         inline void CDocker::OnWindowPosChanged(WPARAM wParam, LPARAM lParam)\r
2981         {\r
2982                 UNREFERENCED_PARAMETER(wParam);\r
2983 \r
2984                 if (m_bIsDragging)\r
2985                 {\r
2986                         // Send a Move notification to the parent\r
2987                         if ( IsLeftButtonDown() )\r
2988                         {\r
2989                                 LPWINDOWPOS wPos = (LPWINDOWPOS)lParam;\r
2990                                 if ((!(wPos->flags & SWP_NOMOVE)) || m_BlockMove)\r
2991                                         SendNotify(UWM_DOCK_MOVE);\r
2992                         }\r
2993                         else\r
2994                         {\r
2995                                 CloseAllTargets();\r
2996                                 m_BlockMove = FALSE;\r
2997                         }\r
2998                 }\r
2999                 else if (this == GetTopmostDocker())\r
3000                 {\r
3001                         // Reposition the dock children\r
3002                         if (IsUndocked() && IsWindowVisible() && !m_bIsClosing) RecalcDockLayout();\r
3003                 }\r
3004         }\r
3005 \r
3006         inline void CDocker::PreCreate(CREATESTRUCT &cs)\r
3007         {\r
3008                 // Specify the WS_POPUP style to have this window owned\r
3009                 if (this != GetDockAncestor())\r
3010                         cs.style = WS_POPUP;\r
3011 \r
3012                 cs.dwExStyle = WS_EX_TOOLWINDOW;\r
3013         }\r
3014 \r
3015         inline void CDocker::PreRegisterClass(WNDCLASS &wc)\r
3016         {\r
3017                 wc.lpszClassName = _T("Win32++ Docker");\r
3018                 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);\r
3019         }\r
3020 \r
3021         inline void CDocker::RecalcDockChildLayout(CRect rc)\r
3022         {\r
3023                 // This function positions the Docker's dock children, the Dockers client area\r
3024                 //  and draws the dockbar bars.\r
3025 \r
3026                 // Notes:\r
3027                 // 1) This function is called recursively.\r
3028                 // 2) The client area and child dockers are positioned simultaneously with\r
3029                 //      DeferWindowPos to avoid drawing errors in complex docker arrangements.\r
3030                 // 3) The docker's client area contains the docker's caption (if any) and the docker's view window.\r
3031 \r
3032                 // Note: All top level dockers are undocked, including the dock ancestor.\r
3033                 if (IsDocked())\r
3034                 {\r
3035                         rc.OffsetRect(-rc.left, -rc.top);\r
3036                 }\r
3037 \r
3038                 HDWP hdwp = BeginDeferWindowPos((int)m_vDockChildren.size() +2);\r
3039 \r
3040                 // Step 1: Calculate the position of each Docker child, DockBar, and Client window.\r
3041                 //   The Client area = the docker rect minus the area of dock children and the dock bar (splitter bar).\r
3042                 for (UINT u = 0; u < m_vDockChildren.size(); ++u)\r
3043                 {\r
3044                         CRect rcChild = rc;\r
3045                         double DockSize = m_vDockChildren[u]->m_DockStartSize;;\r
3046 \r
3047                         // Calculate the size of the Docker children\r
3048                         switch (m_vDockChildren[u]->GetDockStyle() & 0xF)\r
3049                         {\r
3050                         case DS_DOCKED_LEFT:\r
3051                                 if (!(GetDockStyle() & DS_FIXED_RESIZE))\r
3052                                         DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Width()), rcChild.Width());\r
3053                                 rcChild.right = rcChild.left + (int)DockSize;\r
3054                                 break;\r
3055                         case DS_DOCKED_RIGHT:\r
3056                                 if (!(GetDockStyle() & DS_FIXED_RESIZE))\r
3057                                         DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Width()), rcChild.Width());\r
3058                                 rcChild.left = rcChild.right - (int)DockSize;\r
3059                                 break;\r
3060                         case DS_DOCKED_TOP:\r
3061                                 if (!(GetDockStyle() & DS_FIXED_RESIZE))\r
3062                                         DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Height()), rcChild.Height());\r
3063                                 rcChild.bottom = rcChild.top + (int)DockSize;\r
3064                                 break;\r
3065                         case DS_DOCKED_BOTTOM:\r
3066                                 if (!(GetDockStyle() & DS_FIXED_RESIZE))\r
3067                                         DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Height()), rcChild.Height());\r
3068                                 rcChild.top = rcChild.bottom - (int)DockSize;\r
3069                                 break;\r
3070                         }\r
3071 \r
3072                         if (m_vDockChildren[u]->IsDocked())\r
3073                         {\r
3074                                 // Position this docker's children\r
3075                                 hdwp = m_vDockChildren[u]->DeferWindowPos(hdwp, NULL, rcChild, SWP_SHOWWINDOW|SWP_FRAMECHANGED);\r
3076                                 m_vDockChildren[u]->m_rcChild = rcChild;\r
3077 \r
3078                                 rc.SubtractRect(rc, rcChild);\r
3079 \r
3080                                 // Calculate the dimensions of the splitter bar\r
3081                                 CRect rcBar = rc;\r
3082                                 DWORD DockSide = m_vDockChildren[u]->GetDockStyle() & 0xF;\r
3083 \r
3084                                 if (DS_DOCKED_LEFT   == DockSide) rcBar.right  = rcBar.left + m_vDockChildren[u]->GetBarWidth();\r
3085                                 if (DS_DOCKED_RIGHT  == DockSide) rcBar.left   = rcBar.right - m_vDockChildren[u]->GetBarWidth();\r
3086                                 if (DS_DOCKED_TOP    == DockSide) rcBar.bottom = rcBar.top + m_vDockChildren[u]->GetBarWidth();\r
3087                                 if (DS_DOCKED_BOTTOM == DockSide) rcBar.top    = rcBar.bottom - m_vDockChildren[u]->GetBarWidth();\r
3088 \r
3089                                 // Save the splitter bar position. We will reposition it later.\r
3090                                 m_vDockChildren[u]->m_rcBar = rcBar;\r
3091                                 rc.SubtractRect(rc, rcBar);\r
3092                         }\r
3093                 }\r
3094 \r
3095                 // Step 2: Position the Dock client and dock bar\r
3096                 hdwp = GetDockClient().DeferWindowPos(hdwp, NULL, rc, SWP_SHOWWINDOW |SWP_FRAMECHANGED);\r
3097                 EndDeferWindowPos(hdwp);\r
3098 \r
3099                 // Position the dockbar. Only docked dockers have a dock bar.\r
3100                 if (IsDocked())\r
3101                 {\r
3102                         // The SWP_NOCOPYBITS forces a redraw of the dock bar.\r
3103                         GetDockBar().SetWindowPos(NULL, m_rcBar, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS );\r
3104                 }\r
3105 \r
3106                 // Step 3: Now recurse through the docker's children. They might have children of their own.\r
3107                 for (UINT v = 0; v < m_vDockChildren.size(); ++v)\r
3108                 {\r
3109                         m_vDockChildren[v]->RecalcDockChildLayout(m_vDockChildren[v]->m_rcChild);\r
3110                 }\r
3111         }\r
3112 \r
3113         inline void CDocker::RecalcDockLayout()\r
3114         // Repositions the dock children of a top level docker\r
3115         {\r
3116                 if (GetDockAncestor()->IsWindow())\r
3117                 {\r
3118                         CRect rc = GetTopmostDocker()->GetClientRect();\r
3119                         GetTopmostDocker()->RecalcDockChildLayout(rc);\r
3120                         GetTopmostDocker()->UpdateWindow();\r
3121                 }\r
3122         }\r
3123 \r
3124         inline std::vector<CDocker*> CDocker::SortDockers()\r
3125         // Returns a vector of sorted dockers, used by SaveRegistrySettings.\r
3126         {\r
3127                 std::vector<CDocker*> vSorted;\r
3128                 std::vector<CDocker*>::iterator itSort;\r
3129                 std::vector<DockPtr>::iterator itAll;\r
3130 \r
3131                 // Add undocked top level dockers\r
3132                 for (itAll = GetAllDockers().begin(); itAll <  GetAllDockers().end(); ++itAll)\r
3133                 {\r
3134                         if (!(*itAll)->GetDockParent())\r
3135                                 vSorted.push_back((*itAll).get());\r
3136                 }\r
3137 \r
3138                 // Add dock ancestor's children\r
3139                 vSorted.insert(vSorted.end(), GetDockAncestor()->GetDockChildren().begin(), GetDockAncestor()->GetDockChildren().end());\r
3140 \r
3141                 // Add other dock children\r
3142                 int index = 0;\r
3143                 itSort = vSorted.begin();\r
3144                 while (itSort < vSorted.end())\r
3145                 {\r
3146                         vSorted.insert(vSorted.end(), (*itSort)->GetDockChildren().begin(), (*itSort)->GetDockChildren().end());\r
3147                         itSort = vSorted.begin() + (++index);\r
3148                 }\r
3149 \r
3150                 // Add dockers docked in containers\r
3151                 std::vector<CDocker*> vDockContainers;\r
3152                 for (itSort = vSorted.begin(); itSort< vSorted.end(); ++itSort)\r
3153                 {\r
3154                         if ((*itSort)->GetContainer())\r
3155                                 vDockContainers.push_back(*itSort);\r
3156                 }\r
3157 \r
3158                 for (itSort = vDockContainers.begin(); itSort < vDockContainers.end(); ++itSort)\r
3159                 {\r
3160                         CDockContainer* pContainer = (*itSort)->GetContainer();\r
3161 \r
3162                         for (UINT i = 1; i < pContainer->GetAllContainers().size(); ++i)\r
3163                         {\r
3164                                 CDockContainer* pChild = pContainer->GetContainerFromIndex(i);\r
3165                                 CDocker* pDock = GetDockFromView(pChild);\r
3166                                 vSorted.push_back(pDock);\r
3167                         }\r
3168                 }\r
3169 \r
3170                 return vSorted;\r
3171         }\r
3172 \r
3173         inline BOOL CDocker::SaveRegistrySettings(LPCTSTR szRegistryKeyName)\r
3174         // Stores the docking configuration in the registry\r
3175         // NOTE: This function assumes that each docker has a unique DockID\r
3176         {\r
3177                 assert(VerifyDockers());\r
3178 \r
3179                 std::vector<CDocker*> vSorted = SortDockers();\r
3180                 std::vector<CDocker*>::iterator iter;\r
3181                 std::vector<DockInfo> vDockInfo;\r
3182 \r
3183                 if (szRegistryKeyName)\r
3184                 {\r
3185                         // Fill the DockInfo vector with the docking information\r
3186                         for (iter = vSorted.begin(); iter <  vSorted.end(); ++iter)\r
3187                         {\r
3188                                 DockInfo di      = {0};\r
3189                                 di.DockID        = (*iter)->GetDockID();\r
3190                                 di.DockStyle = (*iter)->GetDockStyle();\r
3191                                 di.DockSize  = (*iter)->GetDockSize();\r
3192                                 di.Rect          = (*iter)->GetWindowRect();\r
3193                                 if ((*iter)->GetDockParent())\r
3194                                         di.DockParentID = (*iter)->GetDockParent()->GetDockID();\r
3195 \r
3196                                 vDockInfo.push_back(di);\r
3197                         }\r
3198 \r
3199                         CString strKeyName = _T("Software\\") + CString(szRegistryKeyName);\r
3200                         HKEY hKey = NULL;\r
3201                         HKEY hKeyDock = NULL;\r
3202 \r
3203                         try\r
3204                         {\r
3205                                 if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))\r
3206                                         throw (CWinException(_T("RegCreateKeyEx Failed")));\r
3207 \r
3208                                 RegDeleteKey(hKey, _T("Dock Windows"));\r
3209                                 if (ERROR_SUCCESS != RegCreateKeyEx(hKey, _T("Dock Windows"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyDock, NULL))\r
3210                                         throw (CWinException(_T("RegCreateKeyEx Failed")));\r
3211 \r
3212                                 // Add the Dock windows information to the registry\r
3213                                 for (UINT u = 0; u < vDockInfo.size(); ++u)\r
3214                                 {\r
3215                                         DockInfo di = vDockInfo[u];\r
3216                                         TCHAR szNumber[16];\r
3217                                         CString strSubKey = _T("DockChild");\r
3218                                         strSubKey += _itot((int)u, szNumber, 10);\r
3219                                         if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, strSubKey, 0, REG_BINARY, (LPBYTE)&di, sizeof(DockInfo)))\r
3220                                                 throw (CWinException(_T("RegSetValueEx failed")));\r
3221                                 }\r
3222 \r
3223                                 // Add Active Container to the registry\r
3224                                 int i = 0;\r
3225                                 for (iter = vSorted.begin(); iter <  vSorted.end(); ++iter)\r
3226                                 {\r
3227                                         CDockContainer* pContainer = (*iter)->GetContainer();\r
3228 \r
3229                                         if (pContainer && (pContainer == pContainer->GetActiveContainer()))\r
3230                                         {\r
3231                                                 TCHAR szNumber[20];\r
3232                                                 CString strSubKey = _T("ActiveContainer");\r
3233                                                 strSubKey += _itot(i++, szNumber, 10);\r
3234                                                 int nID = GetDockFromView(pContainer)->GetDockID();\r
3235                                                 if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, strSubKey, 0, REG_DWORD, (LPBYTE)&nID, sizeof(int)))\r
3236                                                         throw (CWinException(_T("RegSetValueEx failed")));\r
3237                                         }\r
3238                                 }\r
3239 \r
3240                                 RegCloseKey(hKeyDock);\r
3241                                 RegCloseKey(hKey);\r
3242                         }\r
3243 \r
3244                         catch (const CWinException& e)\r
3245                         {\r
3246                                 // Roll back the registry changes by deleting the subkeys\r
3247                                 if (hKey)\r
3248                                 {\r
3249                                         if (hKeyDock)\r
3250                                         {\r
3251                                                 RegDeleteKey(hKeyDock, _T("Dock Windows"));\r
3252                                                 RegCloseKey(hKeyDock);\r
3253                                         }\r
3254 \r
3255                                         RegDeleteKey(HKEY_CURRENT_USER, strKeyName);\r
3256                                         RegCloseKey(hKey);\r
3257                                 }\r
3258 \r
3259                                 e.what();\r
3260                                 return FALSE;\r
3261                         }\r
3262                 }\r
3263 \r
3264                 return TRUE;\r
3265         }\r
3266 \r
3267         inline void CDocker::SendNotify(UINT nMessageID)\r
3268         // Sends a docking notification to the docker below the cursor\r
3269         {\r
3270                 DRAGPOS DragPos;\r
3271                 DragPos.hdr.code = nMessageID;\r
3272                 DragPos.hdr.hwndFrom = m_hWnd;\r
3273                 DragPos.ptPos = GetCursorPos();\r
3274                 DragPos.DockZone = m_dwDockZone;\r
3275                 m_dwDockZone = 0;\r
3276 \r
3277                 CDocker* pDock = GetDockFromPoint(DragPos.ptPos);\r
3278 \r
3279                 if (pDock)\r
3280                         pDock->SendMessage(WM_NOTIFY, 0L, (LPARAM)&DragPos);\r
3281                 else\r
3282                 {\r
3283                         if (GetDockHint().IsWindow())           GetDockHint().Destroy();\r
3284                         CloseAllTargets();\r
3285                         m_BlockMove = FALSE;\r
3286                 }\r
3287         }\r
3288 \r
3289         inline void CDocker::SetDockStyle(DWORD dwDockStyle)\r
3290         {\r
3291                 if (IsWindow())\r
3292                 {\r
3293                         if ((dwDockStyle & DS_CLIENTEDGE) != (m_DockStyle & DS_CLIENTEDGE))\r
3294                         {\r
3295                                 if (dwDockStyle & DS_CLIENTEDGE)\r
3296                                 {\r
3297                                         DWORD dwExStyle = (DWORD)GetDockClient().GetWindowLongPtr(GWL_EXSTYLE)|WS_EX_CLIENTEDGE;\r
3298                                         GetDockClient().SetWindowLongPtr(GWL_EXSTYLE, dwExStyle);\r
3299                                         GetDockClient().RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);\r
3300                                 }\r
3301                                 else\r
3302                                 {\r
3303                                         DWORD dwExStyle = (DWORD)GetDockClient().GetWindowLongPtr(GWL_EXSTYLE);\r
3304                                         dwExStyle &= ~WS_EX_CLIENTEDGE;\r
3305                                         GetDockClient().SetWindowLongPtr(GWL_EXSTYLE, dwExStyle);\r
3306                                         GetDockClient().RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);\r
3307                                 }\r
3308                         }\r
3309 \r
3310                         RecalcDockLayout();\r
3311                 }\r
3312 \r
3313                 m_DockStyle = dwDockStyle;\r
3314         }\r
3315 \r
3316         inline void CDocker::SetCaption(LPCTSTR szCaption)\r
3317         // Sets the caption text\r
3318         {\r
3319                 GetDockClient().SetCaption(szCaption);\r
3320 \r
3321                 if (IsWindow())\r
3322                         SetWindowText(szCaption);\r
3323         }\r
3324 \r
3325         inline void CDocker::SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2)\r
3326         {\r
3327                 GetDockClient().SetCaptionColors(Foregnd1, Backgnd1, ForeGnd2, BackGnd2);\r
3328         }\r
3329 \r
3330         inline void CDocker::SetCaptionHeight(int nHeight)\r
3331         // Sets the height of the caption\r
3332         {\r
3333                 m_NCHeight = nHeight;\r
3334                 RedrawWindow();\r
3335                 RecalcDockLayout();\r
3336         }\r
3337 \r
3338         inline void CDocker::SetDockSize(int DockSize)\r
3339         // Sets the size of a docked docker\r
3340         {\r
3341                 if (IsDocked())\r
3342                 {\r
3343                         assert (m_pDockParent);\r
3344                         switch (GetDockStyle() & 0xF)\r
3345                         {\r
3346                         case DS_DOCKED_LEFT:\r
3347                                 m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Width());\r
3348                                 m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Width());\r
3349                                 break;\r
3350                         case DS_DOCKED_RIGHT:\r
3351                                 m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Width());\r
3352                                 m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Width());\r
3353                                 break;\r
3354                         case DS_DOCKED_TOP:\r
3355                                 m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Height());\r
3356                                 m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Height());\r
3357                                 break;\r
3358                         case DS_DOCKED_BOTTOM:\r
3359                                 m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Height());\r
3360                                 m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Height());\r
3361                                 break;\r
3362                         }\r
3363 \r
3364                         RecalcDockLayout();\r
3365                 }\r
3366                 else\r
3367                 {\r
3368                         m_DockStartSize = DockSize;\r
3369                         m_DockSizeRatio = 1.0;\r
3370                 }\r
3371         }\r
3372 \r
3373         inline void CDocker::SetDragAutoResize(BOOL bAutoResize)\r
3374         {\r
3375                 m_bDragAutoResize = bAutoResize;\r
3376         }\r
3377 \r
3378         inline void CDocker::SetView(CWnd& wndView)\r
3379         // Assigns the view window to the docker\r
3380         {\r
3381                 CWnd* pWnd = &wndView;\r
3382                 GetDockClient().SetView(wndView);\r
3383                 if (dynamic_cast<CDockContainer*>(pWnd))\r
3384                 {\r
3385                         CDockContainer* pContainer = (CDockContainer*)&wndView;\r
3386                         SetCaption(pContainer->GetDockCaption().c_str());\r
3387                 }\r
3388         }\r
3389 \r
3390         inline void CDocker::PromoteFirstChild()\r
3391         // One of the steps required for undocking\r
3392         {\r
3393                 // Promote our first child to replace ourself\r
3394                 if (m_pDockParent)\r
3395                 {\r
3396                         for (UINT u = 0 ; u < m_pDockParent->m_vDockChildren.size(); ++u)\r
3397                         {\r
3398                                 if (m_pDockParent->m_vDockChildren[u] == this)\r
3399                                 {\r
3400                                         if (m_vDockChildren.size() > 0)\r
3401                                                 // swap our first child for ourself as a child of the parent\r
3402                                                 m_pDockParent->m_vDockChildren[u] = m_vDockChildren[0];\r
3403                                         else\r
3404                                                 // remove ourself as a child of the parent\r
3405                                                 m_pDockParent->m_vDockChildren.erase(m_pDockParent->m_vDockChildren.begin() + u);\r
3406                                         break;\r
3407                                 }\r
3408                         }\r
3409                 }\r
3410 \r
3411                 // Transfer styles and data and children to the child docker\r
3412                 CDocker* pDockFirstChild = NULL;\r
3413                 if (m_vDockChildren.size() > 0)\r
3414                 {\r
3415                         pDockFirstChild = m_vDockChildren[0];\r
3416                         pDockFirstChild->m_DockStyle = (pDockFirstChild->m_DockStyle & 0xFFFFFFF0 ) | (m_DockStyle & 0xF);\r
3417                         pDockFirstChild->m_DockStartSize = m_DockStartSize;\r
3418                         pDockFirstChild->m_DockSizeRatio = m_DockSizeRatio;\r
3419 \r
3420                         if (m_pDockParent)\r
3421                         {\r
3422                                 pDockFirstChild->m_pDockParent = m_pDockParent;\r
3423                                 pDockFirstChild->SetParent(m_pDockParent);\r
3424                                 pDockFirstChild->GetDockBar().SetParent(m_pDockParent);\r
3425                         }\r
3426                         else\r
3427                         {\r
3428                                 std::vector<CDocker*>::iterator iter;\r
3429                                 for (iter = GetDockChildren().begin() + 1; iter < GetDockChildren().end(); ++iter)\r
3430                                         (*iter)->ShowWindow(SW_HIDE);\r
3431 \r
3432                                 pDockFirstChild->ConvertToPopup(GetWindowRect());\r
3433                                 pDockFirstChild->GetDockBar().ShowWindow(SW_HIDE);\r
3434                         }\r
3435 \r
3436                         m_vDockChildren.erase(m_vDockChildren.begin());\r
3437                         MoveDockChildren(pDockFirstChild);\r
3438                 }\r
3439         }\r
3440 \r
3441         inline void CDocker::ConvertToChild(HWND hWndParent)\r
3442         {\r
3443                 DWORD dwStyle = WS_CHILD | WS_VISIBLE;\r
3444                 SetWindowLongPtr(GWL_STYLE, dwStyle);\r
3445                 SetParent(FromHandle(hWndParent));\r
3446                 GetDockBar().SetParent(FromHandle(hWndParent));\r
3447         }\r
3448 \r
3449         inline void CDocker::ConvertToPopup(RECT rc)\r
3450         {\r
3451                 // Change the window to an "undocked" style\r
3452                 ShowWindow(SW_HIDE);\r
3453                 DWORD dwStyle = WS_POPUP| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;\r
3454                 SetWindowLongPtr(GWL_STYLE, dwStyle);\r
3455 \r
3456                 // Change the window's parent and reposition it\r
3457                 GetDockBar().ShowWindow(SW_HIDE);\r
3458                 SetWindowPos(0, 0, 0, 0, 0, SWP_NOSENDCHANGING|SWP_HIDEWINDOW|SWP_NOREDRAW);\r
3459                 m_pDockParent = 0;\r
3460                 SetParent(0);\r
3461                 SetWindowPos(NULL, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOOWNERZORDER);\r
3462                 GetDockClient().SetWindowPos(NULL, GetClientRect(), SWP_SHOWWINDOW);\r
3463 \r
3464                 SetWindowText(GetCaption().c_str());\r
3465         }\r
3466 \r
3467         inline CDocker* CDocker::SeparateFromDock()\r
3468         {\r
3469                 // This performs some of the tasks required for undocking.\r
3470                 // It is also used when a docker is hidden.\r
3471                 CDocker* pDockUndockedFrom = GetDockParent();\r
3472                 if (!pDockUndockedFrom && (GetDockChildren().size() > 0))\r
3473                         pDockUndockedFrom = GetDockChildren()[0];\r
3474 \r
3475                 GetTopmostDocker()->m_hOldFocus = 0;\r
3476                 PromoteFirstChild();\r
3477                 m_pDockParent = 0;\r
3478 \r
3479                 GetDockBar().ShowWindow(SW_HIDE);\r
3480                 m_DockStyle = m_DockStyle & 0xFFFFFFF0;\r
3481                 m_DockStyle &= ~DS_DOCKED_CONTAINER;\r
3482 \r
3483                 return pDockUndockedFrom;\r
3484         }\r
3485 \r
3486         inline void CDocker::SetUndockPosition(CPoint pt)\r
3487         {\r
3488                 m_Undocking = TRUE;\r
3489                 CRect rc;\r
3490                 rc = GetDockClient().GetWindowRect();\r
3491                 CRect rcTest = rc;\r
3492                 rcTest.bottom = MIN(rcTest.bottom, rcTest.top + m_NCHeight);\r
3493                 if ( !rcTest.PtInRect(pt))\r
3494                         rc.SetRect(pt.x - rc.Width()/2, pt.y - m_NCHeight/2, pt.x + rc.Width()/2, pt.y - m_NCHeight/2 + rc.Height());\r
3495 \r
3496                 ConvertToPopup(rc);\r
3497                 m_Undocking = FALSE;\r
3498 \r
3499                 // Send the undock notification to the frame\r
3500                 NMHDR nmhdr = {0};\r
3501                 nmhdr.hwndFrom = m_hWnd;\r
3502                 nmhdr.code = UWM_UNDOCKED;\r
3503                 nmhdr.idFrom = m_nDockID;\r
3504                 CWnd* pFrame = GetDockAncestor()->GetAncestor();\r
3505                 pFrame->SendMessage(WM_NOTIFY, m_nDockID, (LPARAM)&nmhdr);\r
3506 \r
3507                 // Initiate the window move\r
3508                 SetCursorPos(pt.x, pt.y);\r
3509                 ScreenToClient(pt);\r
3510                 PostMessage(WM_SYSCOMMAND, (WPARAM)(SC_MOVE|0x0002), MAKELPARAM(pt.x, pt.y));\r
3511         }\r
3512 \r
3513         inline void CDocker::Undock(CPoint pt, BOOL bShowUndocked)\r
3514         {\r
3515                 // Return if we shouldn't undock\r
3516                 if (GetDockStyle() & DS_NO_UNDOCK) return;\r
3517 \r
3518                 // Undocking isn't supported on Win95\r
3519                 if (1400 == GetWinVersion()) return;\r
3520 \r
3521                 CDocker* pDockUndockedFrom = SeparateFromDock();\r
3522 \r
3523                 // Position and draw the undocked window, unless it is about to be closed\r
3524                 if (bShowUndocked)\r
3525                 {\r
3526                         SetUndockPosition(pt);\r
3527                 }\r
3528 \r
3529                 RecalcDockLayout();\r
3530         if ((pDockUndockedFrom) && (pDockUndockedFrom->GetTopmostDocker() != GetTopmostDocker()))\r
3531                         pDockUndockedFrom->RecalcDockLayout();\r
3532         }\r
3533 \r
3534         inline void CDocker::UndockContainer(CDockContainer* pContainer, CPoint pt, BOOL bShowUndocked)\r
3535         {\r
3536                 assert(pContainer);\r
3537                 assert(this == GetDockFromView(pContainer->GetContainerParent()));\r
3538 \r
3539                 // Return if we shouldn't undock\r
3540                 if (GetDockFromView(pContainer)->GetDockStyle() & DS_NO_UNDOCK) return;\r
3541 \r
3542                 if (GetDockFromView(pContainer) == GetDockAncestor()) return;\r
3543 \r
3544                 // Undocking isn't supported on Win95\r
3545                 if (1400 == GetWinVersion()) return;\r
3546 \r
3547                 GetTopmostDocker()->m_hOldFocus = 0;\r
3548                 CDocker* pDockUndockedFrom = GetDockFromView(pContainer->GetContainerParent());\r
3549                 pDockUndockedFrom->ShowWindow(SW_HIDE);\r
3550                 if (GetView() == pContainer)\r
3551                 {\r
3552                         // The parent container is being undocked, so we need\r
3553                         // to transfer our child containers to a different docker\r
3554 \r
3555                         // Choose a new docker from among the dockers for child containers\r
3556                         CDocker* pDockNew = 0;\r
3557                         CDocker* pDockOld = GetDockFromView(pContainer);\r
3558                         std::vector<ContainerInfo> AllContainers = pContainer->GetAllContainers();\r
3559                         std::vector<ContainerInfo>::iterator iter = AllContainers.begin();\r
3560                         while ((0 == pDockNew) && (iter < AllContainers.end()))\r
3561                         {\r
3562                                 if ((*iter).pContainer != pContainer)\r
3563                                         pDockNew = (CDocker*)FromHandle(::GetParent((*iter).pContainer->GetParent()->GetHwnd()));\r
3564 \r
3565                                 ++iter;\r
3566                         }\r
3567 \r
3568                         if (pDockNew)\r
3569                         {\r
3570                                 // Move containers from the old docker to the new docker\r
3571                                 CDockContainer* pContainerNew = (CDockContainer*)pDockNew->GetView();\r
3572                                 for (iter = AllContainers.begin(); iter != AllContainers.end(); ++iter)\r
3573                                 {\r
3574                                         if ((*iter).pContainer != pContainer)\r
3575                                         {\r
3576                                                 CDockContainer* pChildContainer = (CDockContainer*)(*iter).pContainer;\r
3577                                                 pContainer->RemoveContainer(pChildContainer);\r
3578                                                 if (pContainerNew != pChildContainer)\r
3579                                                 {\r
3580                                                         pContainerNew->AddContainer(pChildContainer);\r
3581                                                         CDocker* pDock = GetDockFromView(pChildContainer);\r
3582                                                         pDock->SetParent(pDockNew);\r
3583                                                         pDock->m_pDockParent = pDockNew;\r
3584                                                 }\r
3585                                         }\r
3586                                 }\r
3587 \r
3588                                 // Now transfer the old docker's settings to the new one.\r
3589                                 pDockUndockedFrom = pDockNew;\r
3590                                 pDockNew->m_DockStyle           = pDockOld->m_DockStyle;\r
3591                                 pDockNew->m_DockStartSize       = pDockOld->m_DockStartSize;\r
3592                                 pDockNew->m_DockSizeRatio       = pDockOld->m_DockSizeRatio;\r
3593                                 if (pDockOld->IsDocked())\r
3594                                 {\r
3595                                         pDockNew->m_pDockParent         = pDockOld->m_pDockParent;\r
3596                                         pDockNew->SetParent(pDockOld->GetParent());\r
3597                                 }\r
3598                                 else\r
3599                                 {\r
3600                                         CRect rc = pDockOld->GetWindowRect();\r
3601                                         pDockNew->ShowWindow(SW_HIDE);\r
3602                                         DWORD dwStyle = WS_POPUP| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE;\r
3603                                         pDockNew->SetWindowLongPtr(GWL_STYLE, dwStyle);\r
3604                                         pDockNew->m_pDockParent = 0;\r
3605                                         pDockNew->SetParent(0);\r
3606                                         pDockNew->SetWindowPos(NULL, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED| SWP_NOOWNERZORDER);\r
3607                                 }\r
3608                                 pDockNew->GetDockBar().SetParent(pDockOld->GetParent());\r
3609                                 pDockNew->GetView()->SetFocus();\r
3610 \r
3611                                 // Transfer the Dock children to the new docker\r
3612                                 pDockOld->MoveDockChildren(pDockNew);\r
3613 \r
3614                                 // insert pDockNew into its DockParent's DockChildren vector\r
3615                                 if (pDockNew->m_pDockParent)\r
3616                                 {\r
3617                                         std::vector<CDocker*>::iterator p;\r
3618                                         for (p = pDockNew->m_pDockParent->m_vDockChildren.begin(); p != pDockNew->m_pDockParent->m_vDockChildren.end(); ++p)\r
3619                                         {\r
3620                                                 if (*p == this)\r
3621                                                 {\r
3622                                                         pDockNew->m_pDockParent->m_vDockChildren.insert(p, pDockNew);\r
3623                                                         break;\r
3624                                                 }\r
3625                                         }\r
3626                                 }\r
3627                         }\r
3628                 }\r
3629                 else\r
3630                 {\r
3631                         // This is a child container, so simply remove it from the parent\r
3632                         CDockContainer* pContainerParent = (CDockContainer*)GetView();\r
3633                         pContainerParent->RemoveContainer(pContainer);\r
3634                         pContainerParent->SetTabSize();\r
3635                         pContainerParent->SetFocus();\r
3636                         pContainerParent->GetViewPage().SetParent(pContainerParent);\r
3637                 }\r
3638 \r
3639                 // Finally do the actual undocking\r
3640                 CDocker* pDock = GetDockFromView(pContainer);\r
3641                 CRect rc = GetDockClient().GetWindowRect();\r
3642                 ScreenToClient(rc);\r
3643                 pDock->GetDockClient().SetWindowPos(NULL, rc, SWP_SHOWWINDOW);\r
3644                 pDock->Undock(pt, bShowUndocked);\r
3645                 pDockUndockedFrom->ShowWindow();\r
3646                 pDockUndockedFrom->RecalcDockLayout();\r
3647                 pDock->BringWindowToTop();\r
3648         }\r
3649 \r
3650         inline LRESULT CDocker::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
3651         {\r
3652                 switch (uMsg)\r
3653                 {\r
3654                 case WM_ACTIVATE:\r
3655                         OnActivate(wParam, lParam);\r
3656                         break;\r
3657                 case WM_SYSCOMMAND:\r
3658                         return OnSysCommand(wParam, lParam);\r
3659 \r
3660                 case WM_EXITSIZEMOVE:\r
3661                         OnExitSizeMove(wParam, lParam);\r
3662                         break;\r
3663                 case WM_WINDOWPOSCHANGING:\r
3664                         return OnWindowPosChanging(wParam, lParam);\r
3665 \r
3666                 case WM_WINDOWPOSCHANGED:\r
3667                         OnWindowPosChanged(wParam, lParam);\r
3668                         break;\r
3669                 case WM_DESTROY:\r
3670                         OnDestroy(wParam, lParam);\r
3671                         break;\r
3672                 case WM_SETFOCUS:\r
3673                         OnSetFocus(wParam, lParam);\r
3674                         break;\r
3675                 case WM_TIMER:\r
3676                         OnCaptionTimer(wParam, lParam);\r
3677                         break;\r
3678                 case UWM_DOCK_DESTROYED:\r
3679                         OnDockDestroyed(wParam, lParam);\r
3680                         break;\r
3681                 case UWM_DOCK_ACTIVATED:\r
3682                         DrawAllCaptions();\r
3683                         SetTimer(1, 100, NULL);\r
3684                         break;\r
3685                 case WM_SYSCOLORCHANGE:\r
3686                         OnSysColorChange(wParam, lParam);\r
3687                         break;\r
3688                 case WM_NCLBUTTONDBLCLK :\r
3689                         m_bIsDragging = FALSE;\r
3690                         break;\r
3691                 }\r
3692 \r
3693                 return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
3694         }\r
3695 \r
3696 \r
3697         //////////////////////////////////////\r
3698         // Declaration of the CDockContainer class\r
3699         inline CDockContainer::CDockContainer() : m_iCurrentPage(0), m_hTabIcon(0), m_nTabPressed(-1)\r
3700         {\r
3701                 m_pContainerParent = this;\r
3702         }\r
3703 \r
3704         inline CDockContainer::~CDockContainer()\r
3705         {\r
3706                 if (m_hTabIcon)\r
3707                         DestroyIcon(m_hTabIcon);\r
3708         }\r
3709 \r
3710         inline void CDockContainer::AddContainer(CDockContainer* pContainer)\r
3711         {\r
3712                 assert(pContainer);\r
3713 \r
3714                 if (this == m_pContainerParent)\r
3715                 {\r
3716                         ContainerInfo ci = {0};\r
3717                         ci.pContainer = pContainer;\r
3718                         lstrcpy(ci.szTitle, pContainer->GetTabText());\r
3719                         ci.iImage = ImageList_AddIcon(GetImageList(), pContainer->GetTabIcon());\r
3720                         int iNewPage = (int)m_vContainerInfo.size();\r
3721                         m_vContainerInfo.push_back(ci);\r
3722 \r
3723                         if (m_hWnd)\r
3724                         {\r
3725                                 TCITEM tie = {0};\r
3726                                 tie.mask = TCIF_TEXT | TCIF_IMAGE;\r
3727                                 tie.iImage = ci.iImage;\r
3728                                 tie.pszText = m_vContainerInfo[iNewPage].szTitle;\r
3729                                 TabCtrl_InsertItem(m_hWnd, iNewPage, &tie);\r
3730 \r
3731                                 SetTabSize();\r
3732                         }\r
3733 \r
3734                         pContainer->m_pContainerParent = this;\r
3735                         if (pContainer->IsWindow())\r
3736                         {\r
3737                                 // Set the parent container relationships\r
3738                                 pContainer->GetViewPage().SetParent(this);\r
3739                                 pContainer->GetViewPage().ShowWindow(SW_HIDE);\r
3740                         }\r
3741                 }\r
3742         }\r
3743 \r
3744         inline void CDockContainer::AddToolBarButton(UINT nID, BOOL bEnabled /* = TRUE */)\r
3745         // Adds Resource IDs to toolbar buttons.\r
3746         // A resource ID of 0 is a separator\r
3747         {\r
3748                 GetToolBar().AddButton(nID, bEnabled);\r
3749         }\r
3750 \r
3751         inline CDockContainer* CDockContainer::GetContainerFromIndex(UINT nPage)\r
3752         {\r
3753                 CDockContainer* pContainer = NULL;\r
3754                 if (nPage < m_vContainerInfo.size())\r
3755                         pContainer = (CDockContainer*)m_vContainerInfo[nPage].pContainer;\r
3756 \r
3757                 return pContainer;\r
3758         }\r
3759 \r
3760         inline CWnd* CDockContainer::GetActiveView() const\r
3761         // Returns a pointer to the active view window, or NULL if there is no active veiw.\r
3762         {\r
3763                 CWnd* pWnd = NULL;\r
3764                 if (m_pContainerParent->m_vContainerInfo.size() > 0)\r
3765                 {\r
3766                         CDockContainer* pActiveContainer = m_pContainerParent->m_vContainerInfo[m_pContainerParent->m_iCurrentPage].pContainer;\r
3767                         if (pActiveContainer->GetViewPage().GetView()->IsWindow())\r
3768                                 pWnd = pActiveContainer->GetViewPage().GetView();\r
3769                 }\r
3770 \r
3771                 return pWnd;\r
3772         }\r
3773 \r
3774         inline CDockContainer* CDockContainer::GetContainerFromView(CWnd* pView) const\r
3775         {\r
3776                 assert(pView);\r
3777 \r
3778                 std::vector<ContainerInfo>::iterator iter;\r
3779                 CDockContainer* pViewContainer = 0;\r
3780                 for (iter = GetAllContainers().begin(); iter != GetAllContainers().end(); ++iter)\r
3781                 {\r
3782                         CDockContainer* pContainer = (*iter).pContainer;\r
3783                         if (pContainer->GetView() == pView)\r
3784                                 pViewContainer = pContainer;\r
3785                 }\r
3786 \r
3787                 return pViewContainer;\r
3788         }\r
3789 \r
3790         inline int CDockContainer::GetContainerIndex(CDockContainer* pContainer)\r
3791         {\r
3792                 assert(pContainer);\r
3793                 int iReturn = -1;\r
3794 \r
3795                 for (int i = 0; i < (int)m_pContainerParent->m_vContainerInfo.size(); ++i)\r
3796                 {\r
3797                         if (m_pContainerParent->m_vContainerInfo[i].pContainer == pContainer)\r
3798                                 iReturn = i;\r
3799                 }\r
3800 \r
3801                 return iReturn;\r
3802         }\r
3803 \r
3804         inline SIZE CDockContainer::GetMaxTabTextSize()\r
3805         {\r
3806                 CSize Size;\r
3807 \r
3808                 // Allocate an iterator for the ContainerInfo vector\r
3809                 std::vector<ContainerInfo>::iterator iter;\r
3810 \r
3811                 for (iter = m_vContainerInfo.begin(); iter != m_vContainerInfo.end(); ++iter)\r
3812                 {\r
3813                         CSize TempSize;\r
3814                         CClientDC dc(this);\r
3815                         NONCLIENTMETRICS info = {0};\r
3816                         info.cbSize = GetSizeofNonClientMetrics();\r
3817                         SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);\r
3818                         dc.CreateFontIndirect(&info.lfStatusFont);\r
3819                         TempSize = dc.GetTextExtentPoint32(iter->szTitle, lstrlen(iter->szTitle));\r
3820                         if (TempSize.cx > Size.cx)\r
3821                                 Size = TempSize;\r
3822                 }\r
3823 \r
3824                 return Size;\r
3825         }\r
3826 \r
3827         inline void CDockContainer::SetupToolBar()\r
3828         {\r
3829                 // Use this function to set the Resource IDs for the toolbar(s).\r
3830 \r
3831 /*              // Set the Resource IDs for the toolbar buttons\r
3832                 AddToolBarButton( IDM_FILE_NEW   );\r
3833                 AddToolBarButton( IDM_FILE_OPEN  );\r
3834                 AddToolBarButton( IDM_FILE_SAVE  );\r
3835                 AddToolBarButton( 0 );                          // Separator\r
3836                 AddToolBarButton( IDM_EDIT_CUT   );\r
3837                 AddToolBarButton( IDM_EDIT_COPY  );\r
3838                 AddToolBarButton( IDM_EDIT_PASTE );\r
3839                 AddToolBarButton( 0 );                          // Separator\r
3840                 AddToolBarButton( IDM_FILE_PRINT );\r
3841                 AddToolBarButton( 0 );                          // Separator\r
3842                 AddToolBarButton( IDM_HELP_ABOUT );\r
3843 */\r
3844         }\r
3845 \r
3846         inline void CDockContainer::OnCreate()\r
3847         {\r
3848                 assert(GetView());                      // Use SetView in CMainFrame's constructor to set the view window\r
3849 \r
3850                 ContainerInfo ci = {0};\r
3851                 ci.pContainer = this;\r
3852                 lstrcpy(ci.szTitle, GetTabText());\r
3853                 ci.iImage = ImageList_AddIcon(GetImageList(), GetTabIcon());\r
3854                 m_vContainerInfo.push_back(ci);\r
3855 \r
3856                 // Create the page window\r
3857                 GetViewPage().Create(this);\r
3858 \r
3859                 // Create the toolbar\r
3860                 GetToolBar().Create(&GetViewPage());\r
3861                 DWORD style = (DWORD)GetToolBar().GetWindowLongPtr(GWL_STYLE);\r
3862                 style |= CCS_NODIVIDER ;\r
3863                 GetToolBar().SetWindowLongPtr(GWL_STYLE, style);\r
3864                 SetupToolBar();\r
3865                 if (GetToolBar().GetToolBarData().size() > 0)\r
3866                 {\r
3867                         // Set the toolbar images\r
3868                         // A mask of 192,192,192 is compatible with AddBitmap (for Win95)\r
3869                         if (!GetToolBar().SendMessage(TB_GETIMAGELIST,  0L, 0L))\r
3870                                 GetToolBar().SetImages(RGB(192,192,192), IDW_MAIN, 0, 0);\r
3871 \r
3872                         GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);\r
3873                 }\r
3874                 else\r
3875                         GetToolBar().Destroy();\r
3876 \r
3877                 SetFixedWidth(TRUE);\r
3878                 SetOwnerDraw(TRUE);\r
3879 \r
3880                 // Add tabs for each container.\r
3881                 for (int i = 0; i < (int)m_vContainerInfo.size(); ++i)\r
3882                 {\r
3883                         // Add tabs for each view.\r
3884                         TCITEM tie = {0};\r
3885                         tie.mask = TCIF_TEXT | TCIF_IMAGE;\r
3886                         tie.iImage = i;\r
3887                         tie.pszText = m_vContainerInfo[i].szTitle;\r
3888                         TabCtrl_InsertItem(m_hWnd, i, &tie);\r
3889                 }\r
3890         }\r
3891 \r
3892         inline void CDockContainer::OnLButtonDown(WPARAM wParam, LPARAM lParam)\r
3893         {\r
3894                 // Overrides CTab::OnLButtonDown\r
3895 \r
3896                 UNREFERENCED_PARAMETER(wParam);\r
3897 \r
3898                 CPoint pt((DWORD)lParam);\r
3899                 TCHITTESTINFO info = {0};\r
3900                 info.pt = pt;\r
3901                 m_nTabPressed = HitTest(info);\r
3902         }\r
3903 \r
3904         inline void CDockContainer::OnLButtonUp(WPARAM wParam, LPARAM lParam)\r
3905         {\r
3906                 // Overrides CTab::OnLButtonUp and takes no action\r
3907 \r
3908                 UNREFERENCED_PARAMETER(wParam);\r
3909                 UNREFERENCED_PARAMETER(lParam);\r
3910         }\r
3911 \r
3912         inline void CDockContainer::OnMouseLeave(WPARAM wParam, LPARAM lParam)\r
3913         {\r
3914                 // Overrides CTab::OnMouseLeave\r
3915 \r
3916                 if (IsLeftButtonDown() && (m_nTabPressed >= 0))\r
3917                 {\r
3918                         CDocker* pDock = (CDocker*)FromHandle(::GetParent(GetParent()->GetHwnd()));\r
3919                         if (dynamic_cast<CDocker*>(pDock))\r
3920                         {\r
3921                                 CDockContainer* pContainer = GetContainerFromIndex(m_iCurrentPage);\r
3922                                 pDock->UndockContainer(pContainer, GetCursorPos(), TRUE);\r
3923                         }\r
3924                 }\r
3925 \r
3926                 m_nTabPressed = -1;\r
3927                 CTab::OnMouseLeave(wParam, lParam);\r
3928         }\r
3929 \r
3930         inline LRESULT CDockContainer::OnNotifyReflect(WPARAM wParam, LPARAM lParam)\r
3931         {\r
3932                 UNREFERENCED_PARAMETER(wParam);\r
3933 \r
3934                 switch (((LPNMHDR)lParam)->code)\r
3935                 {\r
3936                 case TCN_SELCHANGE:\r
3937                         {\r
3938                                 // Display the newly selected tab page\r
3939                                 int nPage = GetCurSel();\r
3940                                 SelectPage(nPage);\r
3941                         }\r
3942                         break;\r
3943                 }\r
3944 \r
3945                 return 0L;\r
3946         }\r
3947 \r
3948         inline void CDockContainer::PreCreate(CREATESTRUCT &cs)\r
3949         {\r
3950                 // For Tabs on the bottom, add the TCS_BOTTOM style\r
3951                 CTab::PreCreate(cs);\r
3952                 cs.style |= TCS_BOTTOM;\r
3953         }\r
3954 \r
3955         inline void CDockContainer::RecalcLayout()\r
3956         {\r
3957                 if (GetContainerParent() == this)\r
3958                 {\r
3959                         // Set the tab sizes\r
3960                         SetTabSize();\r
3961 \r
3962                         // Position the View over the tab control's display area\r
3963                         CRect rc = GetClientRect();\r
3964                         AdjustRect(FALSE, &rc);\r
3965                         CDockContainer* pContainer = m_vContainerInfo[m_iCurrentPage].pContainer;\r
3966                         pContainer->GetViewPage().SetWindowPos(0, rc, SWP_SHOWWINDOW);\r
3967                 } \r
3968         }\r
3969 \r
3970         inline void CDockContainer::RemoveContainer(CDockContainer* pWnd)\r
3971         {\r
3972                 assert(pWnd);\r
3973 \r
3974                 // Remove the tab\r
3975                 int iTab = GetContainerIndex(pWnd);\r
3976                 if (iTab > 0)\r
3977                 {\r
3978                 //      DeleteItem(iTab);\r
3979                         TabCtrl_DeleteItem(m_hWnd, iTab);\r
3980                 }\r
3981 \r
3982                 // Remove the ContainerInfo entry\r
3983                 std::vector<ContainerInfo>::iterator iter;\r
3984                 int iImage = -1;\r
3985                 for (iter = m_vContainerInfo.begin(); iter != m_vContainerInfo.end(); ++iter)\r
3986                 {\r
3987                         if (iter->pContainer == pWnd)\r
3988                         {\r
3989                                 iImage = (*iter).iImage;\r
3990                                 if (iImage >= 0)\r
3991                                         TabCtrl_RemoveImage(m_hWnd, iImage);\r
3992 \r
3993                                 m_vContainerInfo.erase(iter);\r
3994                                 break;\r
3995                         }\r
3996                 }\r
3997 \r
3998                 // Set the parent container relationships\r
3999                 pWnd->GetViewPage().SetParent(pWnd);\r
4000                 pWnd->m_pContainerParent = pWnd;\r
4001 \r
4002                 // Display the first page\r
4003                 m_iCurrentPage = 0;\r
4004                 if (IsWindow())\r
4005                         SelectPage(0);\r
4006         }\r
4007 \r
4008         inline void CDockContainer::SelectPage(int nPage)\r
4009         {\r
4010                 if (this != m_pContainerParent)\r
4011                         m_pContainerParent->SelectPage(nPage);\r
4012                 else\r
4013                 {\r
4014                         if ((nPage >= 0) && (nPage < (int)m_vContainerInfo.size() ))\r
4015                         {\r
4016                                 if (GetCurSel() != nPage)\r
4017                                         SetCurSel(nPage);\r
4018 \r
4019                                 // Create the new container window if required\r
4020                                 if (!m_vContainerInfo[nPage].pContainer->IsWindow())\r
4021                                 {\r
4022                                         CDockContainer* pContainer = m_vContainerInfo[nPage].pContainer;\r
4023                                         pContainer->Create(GetParent());\r
4024                                         pContainer->GetViewPage().SetParent(this);\r
4025                                 }\r
4026 \r
4027                                 // Determine the size of the tab page's view area\r
4028                                 CRect rc = GetClientRect();\r
4029                                 AdjustRect(FALSE, &rc);\r
4030 \r
4031                                 // Swap the pages over\r
4032                                 CDockContainer* pOldContainer = m_vContainerInfo[m_iCurrentPage].pContainer;\r
4033                                 CDockContainer* pNewContainer = m_vContainerInfo[nPage].pContainer;\r
4034                                 pOldContainer->GetViewPage().ShowWindow(SW_HIDE);\r
4035                                 pNewContainer->GetViewPage().SetWindowPos(0, rc, SWP_SHOWWINDOW);\r
4036                                 pNewContainer->GetViewPage().GetView()->SetFocus();\r
4037 \r
4038                                 // Adjust the docking caption\r
4039                                 CDocker* pDock = (CDocker*)FromHandle(::GetParent(::GetParent(m_hWnd)));\r
4040                                 if (dynamic_cast<CDocker*>(pDock))\r
4041                                 {\r
4042                                         pDock->SetCaption(pNewContainer->GetDockCaption().c_str());\r
4043                                         pDock->RedrawWindow();\r
4044                                 }\r
4045 \r
4046                                 m_iCurrentPage = nPage;\r
4047                         }\r
4048                 }\r
4049         }\r
4050 \r
4051         inline void CDockContainer::SetActiveContainer(CDockContainer* pContainer)\r
4052         {\r
4053                 int nPage = GetContainerIndex(pContainer);\r
4054                 assert (0 <= nPage);\r
4055                 SelectPage(nPage);\r
4056         }\r
4057 \r
4058         inline void CDockContainer::SetTabIcon(UINT nID_Icon)\r
4059         {\r
4060                 HICON hIcon = (HICON)LoadImage(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(nID_Icon), IMAGE_ICON, 0, 0, LR_SHARED);\r
4061                 SetTabIcon(hIcon);\r
4062         }\r
4063 \r
4064         inline void CDockContainer::SetTabSize()\r
4065         {\r
4066                 CRect rc = GetClientRect();\r
4067                 AdjustRect(FALSE, &rc);\r
4068                 if (rc.Width() < 0 )\r
4069                         rc.SetRectEmpty();\r
4070 \r
4071                 int nItemWidth = MIN(25 + GetMaxTabTextSize().cx, (rc.Width()-2)/(int)m_vContainerInfo.size());\r
4072                 int nItemHeight = MAX(20, GetTextHeight() + 5);\r
4073                 SendMessage(TCM_SETITEMSIZE, 0L, MAKELPARAM(nItemWidth, nItemHeight));\r
4074         }\r
4075 \r
4076         inline void CDockContainer::SetTabText(UINT nTab, LPCTSTR szText)\r
4077         {\r
4078                 CDockContainer* pContainer = GetContainerParent()->GetContainerFromIndex(nTab);\r
4079                 pContainer->SetTabText(szText);\r
4080 \r
4081                 CTab::SetTabText(nTab, szText);\r
4082         }\r
4083 \r
4084         inline void CDockContainer::SetView(CWnd& Wnd)\r
4085         {\r
4086                 GetViewPage().SetView(Wnd);\r
4087         }\r
4088 \r
4089         inline LRESULT CDockContainer::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
4090         {\r
4091                 switch (uMsg)\r
4092                 {\r
4093                 case WM_SIZE:\r
4094                         RecalcLayout();\r
4095                         return 0;\r
4096 \r
4097         // The following are called in CTab::WndProcDefault\r
4098         //      case WM_LBUTTONDOWN:\r
4099         //              OnLButtonDown(wParam, lParam);\r
4100         //              break;\r
4101         //      case WM_LBUTTONUP:\r
4102         //              OnLButtonUp(wParam, lParam);\r
4103         //              break;\r
4104         //      case WM_MOUSELEAVE:\r
4105         //              OnMouseLeave(wParam, lParam);\r
4106         //              break;\r
4107 \r
4108                 case WM_SETFOCUS:\r
4109                         {\r
4110                                 // Pass focus on to the current view\r
4111                                 GetActiveView()->SetFocus();\r
4112                         }\r
4113                         break;\r
4114                 }\r
4115 \r
4116                 // pass unhandled messages on to CTab for processing\r
4117                 return CTab::WndProcDefault(uMsg, wParam, lParam);\r
4118         }\r
4119 \r
4120 \r
4121         ///////////////////////////////////////////\r
4122         // Declaration of the nested CViewPage class\r
4123         inline BOOL CDockContainer::CViewPage::OnCommand(WPARAM wParam, LPARAM lParam)\r
4124         {\r
4125                 CDockContainer* pContainer = (CDockContainer*)GetParent();\r
4126                 BOOL bResult = FALSE;\r
4127                 if (pContainer && pContainer->GetActiveContainer())\r
4128                         bResult = (BOOL)pContainer->GetActiveContainer()->SendMessage(WM_COMMAND, wParam, lParam);\r
4129 \r
4130                 return bResult;\r
4131         }\r
4132 \r
4133         inline void CDockContainer::CViewPage::OnCreate()\r
4134         {\r
4135                 if (m_pView)\r
4136                         m_pView->Create(this);\r
4137         }\r
4138 \r
4139         inline LRESULT CDockContainer::CViewPage::OnNotify(WPARAM wParam, LPARAM lParam)\r
4140         {\r
4141                 UNREFERENCED_PARAMETER(wParam);\r
4142 \r
4143                 switch (((LPNMHDR)lParam)->code)\r
4144                 {\r
4145 \r
4146                 // Display tooltips for the toolbar\r
4147                 case TTN_GETDISPINFO:\r
4148                         {\r
4149                                 int iIndex =  GetToolBar().HitTest();\r
4150                                 LPNMTTDISPINFO lpDispInfo = (LPNMTTDISPINFO)lParam;\r
4151                                 if (iIndex >= 0)\r
4152                                 {\r
4153                                         int nID = GetToolBar().GetCommandID(iIndex);\r
4154                                         if (nID > 0)\r
4155                                         {\r
4156                                                 m_strTooltip = LoadString(nID);\r
4157                                                 lpDispInfo->lpszText = (LPTSTR)m_strTooltip.c_str();\r
4158                                         }\r
4159                                         else\r
4160                                                 m_strTooltip = _T("");\r
4161                                 }\r
4162                         }\r
4163                         break;\r
4164                 } // switch LPNMHDR\r
4165 \r
4166                 return 0L;\r
4167         }\r
4168 \r
4169         inline void CDockContainer::CViewPage::PreRegisterClass(WNDCLASS &wc)\r
4170         {\r
4171                 wc.lpszClassName = _T("Win32++ TabPage");\r
4172                 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);\r
4173         }\r
4174 \r
4175         inline void CDockContainer::CViewPage::RecalcLayout()\r
4176         {\r
4177                 CRect rc = GetClientRect();\r
4178                 if (GetToolBar().IsWindow())\r
4179                 {\r
4180                         GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);\r
4181                         CRect rcToolBar = m_ToolBar.GetClientRect();\r
4182                         rc.top += rcToolBar.Height();\r
4183                 }\r
4184 \r
4185                 GetView()->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);\r
4186         }\r
4187 \r
4188         inline void CDockContainer::CViewPage::SetView(CWnd& wndView)\r
4189         // Sets or changes the View window displayed within the frame\r
4190         {\r
4191                 // Assign the view window\r
4192                 m_pView = &wndView;\r
4193 \r
4194                 if (m_hWnd)\r
4195                 {\r
4196                         if (!m_pView->IsWindow())\r
4197                         {\r
4198                                 // The container is already created, so create and position the new view too\r
4199                                 GetView()->Create(this);\r
4200                         }\r
4201 \r
4202                         RecalcLayout();\r
4203                 }\r
4204         }\r
4205 \r
4206         inline LRESULT CDockContainer::CViewPage::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
4207         {\r
4208                 switch (uMsg)\r
4209                 {\r
4210                 case WM_SIZE:\r
4211                         RecalcLayout();\r
4212                         break;\r
4213                 case WM_NOTIFY:\r
4214                         switch (((LPNMHDR)lParam)->code)\r
4215                         {\r
4216                         // Send the focus change notifications to the grandparent\r
4217                         case NM_KILLFOCUS:\r
4218                         case NM_SETFOCUS:\r
4219                         case UWM_FRAMELOSTFOCUS:\r
4220                                 ::SendMessage(::GetParent(::GetParent(m_hWnd)), WM_NOTIFY, wParam, lParam);\r
4221                                 break;\r
4222                         }\r
4223 \r
4224                         break;\r
4225                 }\r
4226 \r
4227                 // pass unhandled messages on for default processing\r
4228                 return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
4229         }\r
4230 \r
4231 } // namespace Win32xx\r
4232 \r
4233 #endif // _WIN32XX_DOCKING_H_\r
4234 \r

UCC git Repository :: git.ucc.asn.au