1 // Win32++ Version 7.3
\r
2 // Released: 30th November 2011
\r
6 // url: https://sourceforge.net/projects/win32-framework
\r
9 // Copyright (c) 2005-2011 David Nash
\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
21 // The above copyright notice and this permission notice
\r
22 // shall be included in all copies or substantial portions
\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
35 ////////////////////////////////////////////////////////
\r
38 ///////////////////////////////////////////////////////
\r
40 // Declaration of the CDocker class
\r
42 #ifndef _WIN32XX_DOCKING_H_
\r
43 #define _WIN32XX_DOCKING_H_
\r
46 #include "wincore.h"
\r
48 #include "toolbar.h"
\r
51 #include "default_resource.h"
\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
75 // Required for Dev-C++
\r
76 #ifndef TME_NONCLIENT
\r
77 #define TME_NONCLIENT 0x00000010
\r
80 #define TME_LEAVE 0x000000002
\r
82 #ifndef WM_NCMOUSELEAVE
\r
83 #define WM_NCMOUSELEAVE 0x000002A2
\r
88 // Class declarations
\r
89 class CDockContainer;
\r
92 typedef Shared_Ptr<CDocker> DockPtr;
\r
94 struct ContainerInfo
\r
96 TCHAR szTitle[MAX_MENU_STRING];
\r
98 CDockContainer* pContainer;
\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
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
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
132 CWnd* GetTabCtrl() const { return m_pTab;}
\r
135 CToolBar m_ToolBar;
\r
136 CString m_strTooltip;
\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
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
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
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
197 typedef struct DRAGPOS
\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
213 // A nested class for the splitter bar that seperates the docked panes.
\r
214 class CDockBar : public CWnd
\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
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
232 CDockBar(const CDockBar&); // Disable copy construction
\r
233 CDockBar& operator = (const CDockBar&); // Disable assignment operator
\r
237 CBrush m_brBackground;
\r
238 int m_DockBarWidth;
\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
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
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
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
280 CDockClient(const CDockClient&); // Disable copy construction
\r
281 CDockClient& operator = (const CDockClient&); // Disable assignment operator
\r
283 CString m_csCaption;
\r
287 BOOL m_IsClosePressed;
\r
289 BOOL m_bCaptionPressed;
\r
291 COLORREF m_Foregnd1;
\r
292 COLORREF m_Backgnd1;
\r
293 COLORREF m_Foregnd2;
\r
294 COLORREF m_Backgnd2;
\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
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
313 CDockHint(const CDockHint&); // Disable copy construction
\r
314 CDockHint& operator = (const CDockHint&); // Disable assignment operator
\r
316 CBitmap m_bmBlueTint;
\r
317 UINT m_uDockSideOld;
\r
320 class CTarget : public CWnd
\r
324 virtual ~CTarget();
\r
325 virtual void OnDraw(CDC* pDC);
\r
326 virtual void PreCreate(CREATESTRUCT &cs);
\r
332 CTarget(const CTarget&); // Disable copy construction
\r
333 CTarget& operator = (const CTarget&); // Disable assignment operator
\r
336 class CTargetCentre : public CTarget
\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
347 CTargetCentre(const CTargetCentre&); // Disable copy construction
\r
348 CTargetCentre& operator = (const CTargetCentre&); // Disable assignment operator
\r
350 BOOL m_bIsOverContainer;
\r
351 CDocker* m_pOldDockTarget;
\r
354 class CTargetLeft : public CTarget
\r
357 CTargetLeft() {m_bmImage.LoadImage(IDW_SDLEFT,0,0,0);}
\r
358 virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
\r
361 CTargetLeft(const CTargetLeft&); // Disable copy construction
\r
362 CTargetLeft& operator = (const CTargetLeft&); // Disable assignment operator
\r
365 class CTargetTop : public CTarget
\r
368 CTargetTop() {m_bmImage.LoadImage(IDW_SDTOP,0,0,0);}
\r
369 virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
\r
371 CTargetTop(const CTargetTop&); // Disable copy construction
\r
372 CTargetTop& operator = (const CTargetTop&); // Disable assignment operator
\r
375 class CTargetRight : public CTarget
\r
378 CTargetRight() {m_bmImage.LoadImage(IDW_SDRIGHT,0,0,0);}
\r
379 virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
\r
382 CTargetRight(const CTargetRight&); // Disable copy construction
\r
383 CTargetRight& operator = (const CTargetRight&); // Disable assignment operator
\r
386 class CTargetBottom : public CTarget
\r
389 CTargetBottom() {m_bmImage.LoadImage(IDW_SDBOTTOM,0,0,0);}
\r
390 virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
\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
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
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
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
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
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
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
503 CTargetBottom m_TargetBottom;
\r
504 CDocker* m_pDockParent;
\r
505 CDocker* m_pDockAncestor;
\r
506 CDocker* m_pDockActive;
\r
508 std::vector <CDocker*> m_vDockChildren;
\r
509 std::vector <DockPtr> m_vAllDockers; // Only used in DockAncestor
\r
517 BOOL m_bIsDragging;
\r
518 BOOL m_bDragAutoResize;
\r
519 int m_DockStartSize;
\r
523 DWORD m_dwDockZone;
\r
524 double m_DockSizeRatio;
\r
528 }; // class CDocker
\r
541 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
546 /////////////////////////////////////////////////////////////
\r
547 // Definitions for the CDockBar class nested within CDocker
\r
549 inline CDocker::CDockBar::CDockBar() : m_pDock(NULL), m_DockBarWidth(4)
\r
551 m_brBackground.CreateSolidBrush(RGB(192,192,192));
\r
554 inline CDocker::CDockBar::~CDockBar()
\r
558 inline void CDocker::CDockBar::OnDraw(CDC* pDC)
\r
560 CRect rcClient = GetClientRect();
\r
561 ::SelectObject(*pDC, m_brBackground);
\r
562 pDC->PatBlt(0, 0, rcClient.Width(), rcClient.Height(), PATCOPY);
\r
565 inline void CDocker::CDockBar::PreCreate(CREATESTRUCT &cs)
\r
567 // Create a child window, initially hidden
\r
568 cs.style = WS_CHILD;
\r
571 inline void CDocker::CDockBar::PreRegisterClass(WNDCLASS& wc)
\r
573 wc.lpszClassName = _T("Win32++ Bar");
\r
574 wc.hbrBackground = m_brBackground;
\r
577 inline void CDocker::CDockBar::SendNotify(UINT nMessageID)
\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
587 inline void CDocker::CDockBar::SetColor(COLORREF color)
\r
590 // GetSysColor(COLOR_BTNFACE) // Default Grey
\r
591 // RGB(196, 215, 250) // Default Blue
\r
593 m_brBackground.CreateSolidBrush(color);
\r
596 inline LRESULT CDocker::CDockBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
603 if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE))
\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
610 hCursor = LoadCursor(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_SPLITV));
\r
612 if (hCursor) SetCursor(hCursor);
\r
613 else TRACE(_T("**WARNING** Missing cursor resource for slider bar\n"));
\r
618 SetCursor(LoadCursor(NULL, IDC_ARROW));
\r
622 case WM_ERASEBKGND:
\r
625 case WM_LBUTTONDOWN:
\r
627 if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE))
\r
629 SendNotify(UWM_BAR_START);
\r
636 if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE) && (GetCapture() == this))
\r
638 SendNotify(UWM_BAR_END);
\r
644 if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE) && (GetCapture() == this))
\r
646 SendNotify(UWM_BAR_MOVE);
\r
652 // pass unhandled messages on for default processing
\r
653 return CWnd::WndProcDefault(uMsg, wParam, lParam);
\r
657 ////////////////////////////////////////////////////////////////
\r
658 // Definitions for the CDockClient class nested within CDocker
\r
660 inline CDocker::CDockClient::CDockClient() : m_pView(0), m_IsClosePressed(FALSE),
\r
661 m_bOldFocus(FALSE), m_bCaptionPressed(FALSE), m_IsTracking(FALSE)
\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
669 inline void CDocker::CDockClient::Draw3DBorder(RECT& Rect)
\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
675 dc.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
\r
676 dc.MoveTo(0, rcw.Height());
\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
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
693 inline CRect CDocker::CDockClient::GetCloseRect()
\r
695 // Calculate the close rect position in screen co-ordinates
\r
699 CRect rc = GetWindowRect();
\r
700 int cx = GetSystemMetrics(SM_CXSMICON);
\r
701 int cy = GetSystemMetrics(SM_CYSMICON);
\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
708 #if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
\r
709 if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
\r
711 rcClose.left = rc.left + gap;
\r
712 rcClose.right = rcClose.left + cx;
\r
720 inline void CDocker::CDockClient::DrawCaption(WPARAM wParam)
\r
722 if (IsWindow() && m_pDock->IsDocked() && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
\r
724 BOOL bFocus = m_pDock->IsChildOfDocker(GetFocus());
\r
725 m_bOldFocus = FALSE;
\r
727 // Acquire the DC for our NonClient painting
\r
729 if ((wParam != 1) && (bFocus == m_bOldFocus))
\r
730 pDC = GetDCEx((HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN|DCX_PARENTCLIP);
\r
732 pDC = GetWindowDC();
\r
734 // Create and set up our memory DC
\r
735 CRect rc = GetWindowRect();
\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
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
752 dcMem.SetTextColor(m_Foregnd1);
\r
753 dcMem.CreateSolidBrush(m_Backgnd1);
\r
754 dcMem.SetBkColor(m_Backgnd1);
\r
758 dcMem.SetTextColor(m_Foregnd2);
\r
759 dcMem.CreateSolidBrush(m_Backgnd2);
\r
760 dcMem.SetBkColor(m_Backgnd2);
\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
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
772 // Draw the close button
\r
773 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
\r
774 DrawCloseButton(dcMem, bFocus);
\r
776 // Draw the 3D border
\r
777 if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
\r
780 // Copy the Memory DC to the window's DC
\r
781 pDC->BitBlt(rcAdjust, rcAdjust, Width, Height, &dcMem, rcAdjust, rcAdjust, SRCCOPY);
\r
783 // Required for Win98/WinME
\r
788 inline void CDocker::CDockClient::DrawCloseButton(CDC& DrawDC, BOOL bFocus)
\r
790 // The close button isn't displayed on Win95
\r
791 if (GetWinVersion() == 1400) return;
\r
793 if (m_pDock->IsDocked() && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
\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
800 if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
\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
807 rcClose.OffsetRect(0, m_pDock->m_NCHeight-2);
\r
809 // Draw the outer highlight for the close button
\r
810 if (!IsRectEmpty(&rcClose))
\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
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
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
855 // Manually Draw Close Button
\r
857 DrawDC.CreatePen(PS_SOLID, 1, m_Foregnd1);
\r
859 DrawDC.CreatePen(PS_SOLID, 1, m_Foregnd2);
\r
861 DrawDC.MoveTo(rcClose.left + 3, rcClose.top +3);
\r
862 DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -2);
\r
864 DrawDC.MoveTo(rcClose.left + 4, rcClose.top +3);
\r
865 DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -3);
\r
867 DrawDC.MoveTo(rcClose.left + 3, rcClose.top +4);
\r
868 DrawDC.LineTo(rcClose.right - 3, rcClose.bottom -2);
\r
870 DrawDC.MoveTo(rcClose.right -3, rcClose.top +3);
\r
871 DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -2);
\r
873 DrawDC.MoveTo(rcClose.right -3, rcClose.top +4);
\r
874 DrawDC.LineTo(rcClose.left + 3, rcClose.bottom -2);
\r
876 DrawDC.MoveTo(rcClose.right -4, rcClose.top +3);
\r
877 DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -3);
\r
882 inline void CDocker::CDockClient::OnNCCalcSize(WPARAM& wParam, LPARAM& lParam)
\r
884 // Sets the non-client area (and hence sets the client area)
\r
885 // This function modifies lParam
\r
887 UNREFERENCED_PARAMETER(wParam);
\r
889 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
\r
891 if (m_pDock->IsDocked())
\r
893 LPRECT rc = (LPRECT)lParam;
\r
894 rc->top += m_pDock->m_NCHeight;
\r
899 inline LRESULT CDocker::CDockClient::OnNCHitTest(WPARAM wParam, LPARAM lParam)
\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
904 if (m_pDock->IsDocked())
\r
906 CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
\r
908 // Indicate if the point is in the close button (except for Win95)
\r
909 if ((GetWinVersion() > 1400) && (GetCloseRect().PtInRect(pt)))
\r
912 ScreenToClient(pt);
\r
914 // Indicate if the point is in the caption
\r
919 return CWnd::WndProcDefault(WM_NCHITTEST, wParam, lParam);
\r
922 inline LRESULT CDocker::CDockClient::OnNCLButtonDown(WPARAM wParam, LPARAM lParam)
\r
924 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
\r
926 if ((HTCLOSE == wParam) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
\r
928 m_IsClosePressed = TRUE;
\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
937 CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
\r
938 ScreenToClient(pt);
\r
939 m_pView->SetFocus();
\r
941 // Update the close button
\r
942 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
\r
944 CWindowDC dc(this);
\r
945 DrawCloseButton(dc, m_bOldFocus);
\r
951 return CWnd::WndProcDefault(WM_NCLBUTTONDOWN, wParam, lParam);
\r
954 inline void CDocker::CDockClient::OnLButtonUp(WPARAM wParam, LPARAM lParam)
\r
956 UNREFERENCED_PARAMETER(wParam);
\r
957 UNREFERENCED_PARAMETER(lParam);
\r
959 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & (DS_NO_CAPTION|DS_NO_CLOSE)))
\r
961 m_bCaptionPressed = FALSE;
\r
962 if (m_IsClosePressed && GetCloseRect().PtInRect(GetCursorPos()))
\r
964 // Destroy the docker
\r
965 if (dynamic_cast<CDockContainer*>(m_pDock->GetView()))
\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
976 m_pDock->Destroy();
\r
982 inline void CDocker::CDockClient::OnLButtonDown(WPARAM wParam, LPARAM lParam)
\r
984 UNREFERENCED_PARAMETER(wParam);
\r
985 UNREFERENCED_PARAMETER(lParam);
\r
987 m_IsClosePressed = FALSE;
\r
989 CWindowDC dc(this);
\r
990 DrawCloseButton(dc, m_bOldFocus);
\r
993 inline void CDocker::CDockClient::OnMouseActivate(WPARAM wParam, LPARAM lParam)
\r
994 // Focus changed, so redraw the captions
\r
996 UNREFERENCED_PARAMETER(wParam);
\r
997 UNREFERENCED_PARAMETER(lParam);
\r
999 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
\r
1001 m_pDock->GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
\r
1005 inline void CDocker::CDockClient::OnMouseMove(WPARAM wParam, LPARAM lParam)
\r
1007 OnNCMouseMove(wParam, lParam);
\r
1010 inline void CDocker::CDockClient::OnNCMouseLeave(WPARAM wParam, LPARAM lParam)
\r
1012 UNREFERENCED_PARAMETER(wParam);
\r
1013 UNREFERENCED_PARAMETER(lParam);
\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
1020 m_IsTracking = FALSE;
\r
1023 inline LRESULT CDocker::CDockClient::OnNCMouseMove(WPARAM wParam, LPARAM lParam)
\r
1025 if (!m_IsTracking)
\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
1035 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
\r
1037 if (m_pDock->IsDocked())
\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
1043 if (IsLeftButtonDown() && (wParam == HTCAPTION) && (m_bCaptionPressed))
\r
1045 CDocker* pDock = (CDocker*)GetParent();
\r
1047 pDock->Undock(GetCursorPos());
\r
1050 // Update the close button
\r
1051 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
\r
1053 CWindowDC dc(this);
\r
1054 DrawCloseButton(dc, m_bOldFocus);
\r
1058 m_bCaptionPressed = FALSE;
\r
1060 return CWnd::WndProcDefault(WM_MOUSEMOVE, wParam, lParam);
\r
1063 inline LRESULT CDocker::CDockClient::OnNCPaint(WPARAM wParam, LPARAM lParam)
\r
1065 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
\r
1067 if (m_pDock->IsDocked())
\r
1069 DefWindowProc(WM_NCPAINT, wParam, lParam);
\r
1070 DrawCaption(wParam);
\r
1074 return CWnd::WndProcDefault(WM_NCPAINT, wParam, lParam);
\r
1077 inline void CDocker::CDockClient::OnWindowPosChanged(WPARAM wParam, LPARAM lParam)
\r
1079 UNREFERENCED_PARAMETER(wParam);
\r
1080 UNREFERENCED_PARAMETER(lParam);
\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
1087 inline void CDocker::CDockClient::PreRegisterClass(WNDCLASS& wc)
\r
1089 wc.lpszClassName = _T("Win32++ DockClient");
\r
1090 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
\r
1093 inline void CDocker::CDockClient::PreCreate(CREATESTRUCT& cs)
\r
1095 DWORD dwStyle = m_pDock->GetDockStyle();
\r
1096 if (dwStyle & DS_CLIENTEDGE)
\r
1097 cs.dwExStyle = WS_EX_CLIENTEDGE;
\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
1106 inline void CDocker::CDockClient::SendNotify(UINT nMessageID)
\r
1108 // Fill the DragPos structure with data
\r
1110 DragPos.hdr.code = nMessageID;
\r
1111 DragPos.hdr.hwndFrom = m_hWnd;
\r
1112 DragPos.ptPos = GetCursorPos();
\r
1114 // Send a DragPos notification to the docker
\r
1115 GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&DragPos);
\r
1118 inline void CDocker::CDockClient::SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF Foregnd2, COLORREF Backgnd2)
\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
1129 inline LRESULT CDocker::CDockClient::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
1133 case WM_LBUTTONUP:
\r
1136 if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
\r
1138 CWindowDC dc(this);
\r
1139 DrawCloseButton(dc, m_bOldFocus);
\r
1140 OnLButtonUp(wParam, lParam);
\r
1145 case WM_MOUSEACTIVATE:
\r
1146 OnMouseActivate(wParam, lParam);
\r
1149 case WM_MOUSEMOVE:
\r
1150 OnMouseMove(wParam, lParam);
\r
1153 case WM_NCCALCSIZE:
\r
1154 OnNCCalcSize(wParam, lParam);
\r
1157 case WM_NCHITTEST:
\r
1158 return OnNCHitTest(wParam, lParam);
\r
1160 case WM_NCLBUTTONDOWN:
\r
1161 return OnNCLButtonDown(wParam, lParam);
\r
1163 case WM_NCMOUSEMOVE:
\r
1164 return OnNCMouseMove(wParam, lParam);
\r
1167 return OnNCPaint(wParam, lParam);
\r
1169 case WM_NCMOUSELEAVE:
\r
1170 OnNCMouseLeave(wParam, lParam);
\r
1173 case WM_WINDOWPOSCHANGED:
\r
1174 OnWindowPosChanged(wParam, lParam);
\r
1178 return CWnd::WndProcDefault(uMsg, wParam, lParam);
\r
1182 //////////////////////////////////////////////////////////////
\r
1183 // Definitions for the CDockHint class nested within CDocker
\r
1185 inline CDocker::CDockHint::CDockHint() : m_uDockSideOld(0)
\r
1189 inline CDocker::CDockHint::~CDockHint()
\r
1193 inline RECT CDocker::CDockHint::CalcHintRectContainer(CDocker* pDockTarget)
\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
1204 inline RECT CDocker::CDockHint::CalcHintRectInner(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide)
\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
1213 CRect rcDockDrag = pDockDrag->GetWindowRect();
\r
1214 CRect rcDockTarget = pDockTarget->GetDockClient().GetWindowRect();
\r
1215 if ((uDockSide == DS_DOCKED_LEFT) || (uDockSide == DS_DOCKED_RIGHT))
\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
1223 Width = rcDockDrag.Height();
\r
1224 if (Width >= (rcDockTarget.Height() - pDockDrag->GetBarWidth()))
\r
1225 Width = MAX(rcDockTarget.Height()/2 - pDockDrag->GetBarWidth(), pDockDrag->GetBarWidth());
\r
1227 switch (uDockSide)
\r
1229 case DS_DOCKED_LEFT:
\r
1230 rcHint.right = rcHint.left + Width;
\r
1232 case DS_DOCKED_RIGHT:
\r
1233 rcHint.left = rcHint.right - Width;
\r
1235 case DS_DOCKED_TOP:
\r
1236 rcHint.bottom = rcHint.top + Width;
\r
1238 case DS_DOCKED_BOTTOM:
\r
1239 rcHint.top = rcHint.bottom - Width;
\r
1246 inline RECT CDocker::CDockHint::CalcHintRectOuter(CDocker* pDockDrag, UINT uDockSide)
\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
1255 CRect rcDockDrag = pDockDrag->GetWindowRect();
\r
1256 CRect rcDockTarget = pDockTarget->GetDockClient().GetWindowRect();
\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
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
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
1273 switch (uDockSide)
\r
1275 case DS_DOCKED_LEFTMOST:
\r
1276 rcHint.right = rcHint.left + Width;
\r
1278 case DS_DOCKED_RIGHTMOST:
\r
1279 rcHint.left = rcHint.right - Width;
\r
1281 case DS_DOCKED_TOPMOST:
\r
1282 rcHint.bottom = rcHint.top + Width;
\r
1284 case DS_DOCKED_BOTTOMMOST:
\r
1285 rcHint.top = rcHint.bottom - Width;
\r
1292 inline void CDocker::CDockHint::DisplayHint(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide)
\r
1294 // Ensure a new hint window is created if dock side changes
\r
1295 if (uDockSide != m_uDockSideOld)
\r
1298 pDockTarget->RedrawWindow( NULL, NULL, RDW_NOERASE | RDW_UPDATENOW );
\r
1299 pDockDrag->RedrawWindow();
\r
1301 m_uDockSideOld = uDockSide;
\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
1316 ShowHintWindow(pDockTarget, rcHint);
\r
1320 inline void CDocker::CDockHint::OnDraw(CDC* pDC)
\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
1329 inline void CDocker::CDockHint::PreCreate(CREATESTRUCT &cs)
\r
1331 cs.style = WS_POPUP;
\r
1333 // WS_EX_TOOLWINDOW prevents the window being displayed on the taskbar
\r
1334 cs.dwExStyle = WS_EX_TOOLWINDOW;
\r
1336 cs.lpszClass = _T("Win32++ DockHint");
\r
1339 inline void CDocker::CDockHint::ShowHintWindow(CDocker* pDockTarget, CRect rcHint)
\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
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
1354 // Create the Hint window
\r
1357 Create(pDockTarget);
\r
1360 pDockTarget->ClientToScreen(rcHint);
\r
1361 SetWindowPos(NULL, rcHint, SWP_SHOWWINDOW|SWP_NOZORDER|SWP_NOACTIVATE);
\r
1365 ////////////////////////////////////////////////////////////////
\r
1366 // Definitions for the CTargetCentre class nested within CDocker
\r
1368 inline CDocker::CTargetCentre::CTargetCentre() : m_bIsOverContainer(FALSE), m_pOldDockTarget(0)
\r
1372 inline CDocker::CTargetCentre::~CTargetCentre()
\r
1376 inline void CDocker::CTargetCentre::OnDraw(CDC* pDC)
\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
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
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
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
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
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
1399 if (IsOverContainer())
\r
1401 CBitmap bmMiddle(IDW_SDMIDDLE);
\r
1402 pDC->DrawBitmap(31, 31, 25, 26, bmMiddle, RGB(255,0,255));
\r
1406 inline void CDocker::CTargetCentre::OnCreate()
\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
1415 rgnPoly.CreatePolygonRgn(ptArray, 16, WINDING);
\r
1416 SetWindowRgn(&rgnPoly, FALSE);
\r
1419 inline BOOL CDocker::CTargetCentre::CheckTarget(LPDRAGPOS pDragPos)
\r
1421 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
\r
1422 if (NULL == pDockDrag) return FALSE;
\r
1424 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pDragPos->ptPos);
\r
1425 if (NULL == pDockTarget) return FALSE;
\r
1427 if (!IsWindow()) Create();
\r
1428 m_bIsOverContainer = (dynamic_cast<CDockContainer*>(pDockTarget->GetView()) != NULL);
\r
1430 // Redraw the target if the dock target changes
\r
1431 if (m_pOldDockTarget != pDockTarget) Invalidate();
\r
1432 m_pOldDockTarget = pDockTarget;
\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
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
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
1454 pDockDrag->m_BlockMove = TRUE;
\r
1455 pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_LEFT);
\r
1456 pDockDrag->m_dwDockZone = DS_DOCKED_LEFT;
\r
1459 else if ((rcTop.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_TOP))
\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
1466 else if ((rcRight.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_RIGHT))
\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
1473 else if ((rcBottom.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_BOTTOM))
\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
1480 else if ((rcMiddle.PtInRect(pt)) && (IsOverContainer()))
\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
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
1498 inline void CDocker::CTarget::OnDraw(CDC* pDC)
\r
1500 BITMAP bm = m_bmImage.GetBitmapData();
\r
1501 int cxImage = bm.bmWidth;
\r
1502 int cyImage = bm.bmHeight;
\r
1505 pDC->DrawBitmap(0, 0, cxImage, cyImage, m_bmImage, RGB(255,0,255));
\r
1507 TRACE(_T("Missing docking resource\n"));
\r
1510 inline void CDocker::CTarget::PreCreate(CREATESTRUCT &cs)
\r
1512 cs.style = WS_POPUP;
\r
1513 cs.dwExStyle = WS_EX_TOPMOST|WS_EX_TOOLWINDOW;
\r
1514 cs.lpszClass = _T("Win32++ DockTargeting");
\r
1518 ////////////////////////////////////////////////////////////////
\r
1519 // Definitions for the CTargetLeft class nested within CDocker
\r
1521 inline BOOL CDocker::CTargetLeft::CheckTarget(LPDRAGPOS pDragPos)
\r
1523 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
\r
1524 if (NULL == pDockDrag) return FALSE;
\r
1526 CPoint pt = pDragPos->ptPos;
\r
1527 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
\r
1528 if (pDockTarget != pDockDrag->GetDockAncestor())
\r
1534 BITMAP bm = m_bmImage.GetBitmapData();
\r
1535 int cxImage = bm.bmWidth;
\r
1536 int cyImage = bm.bmHeight;
\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
1546 CRect rcLeft(0, 0, cxImage, cyImage);
\r
1547 ScreenToClient(pt);
\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
1552 pDockDrag->m_BlockMove = TRUE;
\r
1553 pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_LEFTMOST);
\r
1554 pDockDrag->m_dwDockZone = DS_DOCKED_LEFTMOST;
\r
1562 ////////////////////////////////////////////////////////////////
\r
1563 // Definitions for the CTargetTop class nested within CDocker
\r
1565 inline BOOL CDocker::CTargetTop::CheckTarget(LPDRAGPOS pDragPos)
\r
1567 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
\r
1568 if (NULL == pDockDrag) return FALSE;
\r
1570 CPoint pt = pDragPos->ptPos;
\r
1571 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
\r
1572 if (pDockTarget != pDockDrag->GetDockAncestor())
\r
1578 BITMAP bm = m_bmImage.GetBitmapData();
\r
1579 int cxImage = bm.bmWidth;
\r
1580 int cyImage = bm.bmHeight;
\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
1590 CRect rcTop(0, 0, cxImage, cyImage);
\r
1591 ScreenToClient(pt);
\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
1596 pDockDrag->m_BlockMove = TRUE;
\r
1597 pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_TOPMOST);
\r
1598 pDockDrag->m_dwDockZone = DS_DOCKED_TOPMOST;
\r
1606 ////////////////////////////////////////////////////////////////
\r
1607 // Definitions for the CTargetRight class nested within CDocker
\r
1609 inline BOOL CDocker::CTargetRight::CheckTarget(LPDRAGPOS pDragPos)
\r
1611 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
\r
1612 if (NULL == pDockDrag) return FALSE;
\r
1614 CPoint pt = pDragPos->ptPos;
\r
1615 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
\r
1616 if (pDockTarget != pDockDrag->GetDockAncestor())
\r
1622 BITMAP bm = m_bmImage.GetBitmapData();
\r
1623 int cxImage = bm.bmWidth;
\r
1624 int cyImage = bm.bmHeight;
\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
1634 CRect rcRight(0, 0, cxImage, cyImage);
\r
1635 ScreenToClient(pt);
\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
1640 pDockDrag->m_BlockMove = TRUE;
\r
1641 pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_RIGHTMOST);
\r
1642 pDockDrag->m_dwDockZone = DS_DOCKED_RIGHTMOST;
\r
1650 ////////////////////////////////////////////////////////////////
\r
1651 // Definitions for the CTargetBottom class nested within CDocker
\r
1653 inline BOOL CDocker::CTargetBottom::CheckTarget(LPDRAGPOS pDragPos)
\r
1655 CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
\r
1656 if (NULL == pDockDrag) return FALSE;
\r
1658 CPoint pt = pDragPos->ptPos;
\r
1659 CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
\r
1660 if (pDockTarget != pDockDrag->GetDockAncestor())
\r
1666 BITMAP bm = m_bmImage.GetBitmapData();
\r
1667 int cxImage = bm.bmWidth;
\r
1668 int cyImage = bm.bmHeight;
\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
1677 CRect rcBottom(0, 0, cxImage, cyImage);
\r
1678 ScreenToClient(pt);
\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
1683 pDockDrag->m_BlockMove = TRUE;
\r
1684 pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_BOTTOMMOST);
\r
1685 pDockDrag->m_dwDockZone = DS_DOCKED_BOTTOMMOST;
\r
1693 /////////////////////////////////////////
\r
1694 // Definitions for the CDocker class
\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
1700 // Assume this docker is the DockAncestor for now.
\r
1701 m_pDockAncestor = this;
\r
1704 inline CDocker::~CDocker()
\r
1706 GetDockBar().Destroy();
\r
1708 std::vector <DockPtr>::iterator iter;
\r
1709 if (GetDockAncestor() == this)
\r
1711 // Destroy all dock descendants of this dock ancestor
\r
1712 for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
\r
1714 (*iter)->Destroy();
\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
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
1728 // Store the Docker's pointer in the DockAncestor's vector for later deletion
\r
1729 GetDockAncestor()->m_vAllDockers.push_back(DockPtr(pDocker));
\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
1740 // Dock the docker window
\r
1741 if (dwDockStyle & DS_DOCKED_CONTAINER)
\r
1742 DockInContainer(pDocker, dwDockStyle);
\r
1744 Dock(pDocker, dwDockStyle);
\r
1746 // Issue TRACE warnings for any missing resources
\r
1747 HMODULE hMod= GetApp()->GetResourceHandle();
\r
1749 if (!(dwDockStyle & DS_NO_RESIZE))
\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
1757 if (!(dwDockStyle & DS_NO_UNDOCK))
\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
1771 if (dwDockStyle & DS_DOCKED_CONTAINER)
\r
1773 if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDMIDDLE), RT_BITMAP))
\r
1774 TRACE(_T("**WARNING** Docking container bitmap resource missing\n"));
\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
1785 // Store the Docker's pointer in the DockAncestor's vector for later deletion
\r
1786 GetDockAncestor()->m_vAllDockers.push_back(DockPtr(pDocker));
\r
1788 pDocker->SetDockSize(DockSize);
\r
1789 pDocker->SetDockStyle(dwDockStyle & 0XFFFFFF0);
\r
1790 pDocker->m_nDockID = nDockID;
\r
1791 pDocker->m_pDockAncestor = GetDockAncestor();
\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
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
1812 inline void CDocker::CheckAllTargets(LPDRAGPOS pDragPos)
\r
1813 // Calls CheckTarget for each possible target zone
\r
1815 if (!GetDockAncestor()->m_TargetCentre.CheckTarget(pDragPos))
\r
1817 if (!GetDockAncestor()->m_TargetLeft.CheckTarget(pDragPos))
\r
1819 if(!GetDockAncestor()->m_TargetTop.CheckTarget(pDragPos))
\r
1821 if(!GetDockAncestor()->m_TargetRight.CheckTarget(pDragPos))
\r
1823 if(!GetDockAncestor()->m_TargetBottom.CheckTarget(pDragPos))
\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
1830 if (pDockDrag->m_BlockMove)
\r
1831 pDockDrag->RedrawWindow(0, 0, RDW_FRAME|RDW_INVALIDATE);
\r
1833 GetDockHint().Destroy();
\r
1834 pDockDrag->m_dwDockZone = 0;
\r
1835 pDockDrag->m_BlockMove = FALSE;
\r
1844 inline BOOL CDocker::VerifyDockers()
\r
1845 // A diagnostic routine which verifies the integrity of the docking layout
\r
1847 BOOL bResult = TRUE;
\r
1849 // Check dock ancestor
\r
1850 std::vector<DockPtr>::iterator iter;
\r
1852 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
\r
1854 if (GetDockAncestor() != (*iter)->m_pDockAncestor)
\r
1856 TRACE(_T("Invalid Dock Ancestor\n"));
\r
1861 // Check presence of dock parent
\r
1862 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
\r
1864 if ((*iter)->IsUndocked() && (*iter)->m_pDockParent != 0)
\r
1866 TRACE(_T("Error: Undocked dockers should not have a dock parent\n"));
\r
1870 if ((*iter)->IsDocked() && (*iter)->m_pDockParent == 0)
\r
1872 TRACE(_T("Error: Docked dockers should have a dock parent\n"));
\r
1877 // Check dock parent/child relationship
\r
1878 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
\r
1880 std::vector<CDocker*>::iterator iterChild;
\r
1881 for (iterChild = (*iter)->GetDockChildren().begin(); iterChild != (*iter)->GetDockChildren().end(); ++iterChild)
\r
1883 if ((*iterChild)->m_pDockParent != (*iter).get())
\r
1885 TRACE(_T("Error: Docking parent/Child information mismatch\n"));
\r
1888 if ((*iterChild)->GetParent() != (*iter).get())
\r
1890 TRACE(_T("Error: Incorrect windows child parent relationship\n"));
\r
1896 // Check dock parent chain
\r
1897 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
\r
1899 CDocker* pDockTopLevel = (*iter)->GetTopmostDocker();
\r
1900 if (pDockTopLevel->IsDocked())
\r
1901 TRACE(_T("Error: Top level parent should be undocked\n"));
\r
1907 inline void CDocker::Close()
\r
1909 // Destroy the docker
\r
1914 inline void CDocker::CloseAllDockers()
\r
1916 assert(this == GetDockAncestor()); // Must call CloseAllDockers from the DockAncestor
\r
1918 std::vector <DockPtr>::iterator v;
\r
1921 std::vector<DockPtr> AllDockers = GetAllDockers();
\r
1922 for (v = AllDockers.begin(); v != AllDockers.end(); ++v)
\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
1929 GetDockChildren().clear();
\r
1932 // Delete any child containers this container might have
\r
1933 if (GetContainer())
\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
1939 if (GetContainer() != (*iter).pContainer)
\r
1940 GetContainer()->RemoveContainer((*iter).pContainer);
\r
1944 RecalcDockLayout();
\r
1947 inline void CDocker::CloseAllTargets()
\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
1956 inline void CDocker::Dock(CDocker* pDocker, UINT DockStyle)
\r
1957 // Docks the specified docker inside this docker
\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
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
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
1975 pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetWindowRect().Width();
\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
1984 pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetWindowRect().Height();
\r
1987 // Redraw the docked windows
\r
1988 GetAncestor()->SetForegroundWindow();
\r
1989 GetTopmostDocker()->m_hOldFocus = pDocker->GetView()->GetHwnd();
\r
1990 pDocker->GetView()->SetFocus();
\r
1992 GetTopmostDocker()->SetRedraw(FALSE);
\r
1993 RecalcDockLayout();
\r
1994 GetTopmostDocker()->SetRedraw(TRUE);
\r
1995 GetTopmostDocker()->RedrawWindow();
\r
1998 inline void CDocker::DockInContainer(CDocker* pDock, DWORD dwDockStyle)
\r
1999 // Add a container to an existing container
\r
2001 if ((dwDockStyle & DS_DOCKED_CONTAINER) && (dynamic_cast<CDockContainer*>(pDock->GetView())))
\r
2003 // Transfer any dock children to this docker
\r
2004 pDock->MoveDockChildren(this);
\r
2006 // Transfer container children to the target container
\r
2007 CDockContainer* pContainer = (CDockContainer*)GetView();
\r
2008 CDockContainer* pContainerSource = (CDockContainer*)pDock->GetView();
\r
2010 if (pContainerSource->GetAllContainers().size() > 1)
\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
2017 // Remove child container from pContainerSource
\r
2018 CDockContainer* pContainerChild = (*riter).pContainer;
\r
2019 pContainerChild->ShowWindow(SW_HIDE);
\r
2020 pContainerSource->RemoveContainer(pContainerChild);
\r
2022 // Add child container to this container
\r
2023 pContainer->AddContainer(pContainerChild);
\r
2025 CDocker* pDockChild = GetDockFromView(pContainerChild);
\r
2026 pDockChild->SetParent(this);
\r
2027 pDockChild->m_pDockParent = this;
\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
2041 inline void CDocker::DockOuter(CDocker* pDocker, DWORD dwDockStyle)
\r
2042 // Docks the specified docker inside the dock ancestor
\r
2046 pDocker->m_pDockParent = GetDockAncestor();
\r
2048 DWORD OuterDocking = dwDockStyle & 0xF0000;
\r
2049 DWORD DockSide = OuterDocking / 0x10000;
\r
2050 dwDockStyle &= 0xFFF0FFFF;
\r
2051 dwDockStyle |= DockSide;
\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
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
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
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
2074 pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetDockAncestor()->GetWindowRect().Width();
\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
2083 pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetDockAncestor()->GetWindowRect().Height();
\r
2086 // Redraw the docked windows
\r
2087 GetAncestor()->SetFocus();
\r
2088 pDocker->GetView()->SetFocus();
\r
2089 RecalcDockLayout();
\r
2092 inline void CDocker::DrawAllCaptions()
\r
2094 std::vector<DockPtr>::iterator iter;
\r
2095 for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); iter++)
\r
2097 if ((*iter)->IsDocked())
\r
2098 (*iter)->GetDockClient().DrawCaption((WPARAM)1);
\r
2102 inline void CDocker::DrawHashBar(HWND hBar, POINT Pos)
\r
2103 // Draws a hashed bar while the splitter bar is being dragged
\r
2105 CDocker* pDock = ((CDockBar*)FromHandle(hBar))->GetDock();
\r
2106 if (NULL == pDock) return;
\r
2108 BOOL bVertical = ((pDock->GetDockStyle() & 0xF) == DS_DOCKED_LEFT) || ((pDock->GetDockStyle() & 0xF) == DS_DOCKED_RIGHT);
\r
2110 CClientDC dcBar(this);
\r
2112 WORD HashPattern[] = {0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA};
\r
2114 CBrush brDithered;
\r
2115 bmHash.CreateBitmap(8, 8, 1, 1, HashPattern);
\r
2116 brDithered.CreatePatternBrush(&bmHash);
\r
2117 dcBar.SelectObject(&brDithered);
\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
2126 dcBar.PatBlt(Pos.x - BarWidth/2, rc.top, BarWidth, cy, PATINVERT);
\r
2128 dcBar.PatBlt(rc.left, Pos.y - BarWidth/2, cx, BarWidth, PATINVERT);
\r
2131 inline CDockContainer* CDocker::GetContainer() const
\r
2133 CDockContainer* pContainer = NULL;
\r
2134 if (dynamic_cast<CDockContainer*>(GetView()))
\r
2135 pContainer = (CDockContainer*)GetView();
\r
2137 return pContainer;
\r
2140 inline CDocker* CDocker::GetActiveDocker() const
\r
2141 // Returns the docker whose child window has focus
\r
2143 CWnd* pWnd = GetFocus();
\r
2144 CDocker* pDock= NULL;
\r
2145 while (pWnd && (pDock == NULL))
\r
2147 if (IsRelated(pWnd))
\r
2148 pDock = (CDocker*)pWnd;
\r
2150 pWnd = pWnd->GetParent();
\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
2160 return m_pDockAncestor;
\r
2163 inline CDocker* CDocker::GetDockFromPoint(POINT pt) const
\r
2164 // Retrieves the Docker whose view window contains the specified point
\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
2170 // Iterate through all top level windows
\r
2171 CWnd* pWnd = GetWindow(GW_HWNDFIRST);
\r
2174 if (IsRelated(pWnd) || pWnd == pAncestor)
\r
2176 CDocker* pDockTest;
\r
2177 if (pWnd == pAncestor)
\r
2178 pDockTest = GetDockAncestor();
\r
2180 pDockTest = (CDocker*)pWnd;
\r
2182 CRect rc = pDockTest->GetClientRect();
\r
2183 pDockTest->ClientToScreen(rc);
\r
2184 if ((this != pDockTest) && rc.PtInRect(pt))
\r
2186 pDockTop = pDockTest;
\r
2191 pWnd = pWnd->GetWindow(GW_HWNDNEXT);
\r
2194 // Step 2: Find the docker child whose view window has the point
\r
2195 CDocker* pDockTarget = NULL;
\r
2198 CDocker* pDockParent = pDockTop;
\r
2199 CDocker* pDockTest = pDockParent;
\r
2201 while (IsRelated(pDockTest))
\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
2210 CRect rc = pDockParent->GetDockClient().GetWindowRect();
\r
2211 if (rc.PtInRect(pt)) pDockTarget = pDockParent;
\r
2214 return pDockTarget;
\r
2217 inline CDocker* CDocker::GetDockFromID(int n_DockID) const
\r
2219 std::vector <DockPtr>::iterator v;
\r
2221 if (GetDockAncestor())
\r
2223 for (v = GetDockAncestor()->m_vAllDockers.begin(); v != GetDockAncestor()->m_vAllDockers.end(); v++)
\r
2225 if (n_DockID == (*v)->GetDockID())
\r
2226 return (*v).get();
\r
2233 inline CDocker* CDocker::GetDockFromView(CWnd* pView) const
\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
2240 if ((*iter)->GetView() == pView)
\r
2241 pDock = (*iter).get();
\r
2244 if (GetDockAncestor()->GetView() == pView)
\r
2245 pDock = GetDockAncestor();
\r
2250 inline int CDocker::GetDockSize() const
\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
2256 if (GetDockParent())
\r
2257 rcParent = GetDockParent()->GetWindowRect();
\r
2259 rcParent = GetDockAncestor()->GetWindowRect();
\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
2269 return (int)DockSize;
\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
2276 CDocker* pDockTopLevel = (CDocker* const)this;
\r
2278 while(pDockTopLevel->GetDockParent())
\r
2280 assert (pDockTopLevel != pDockTopLevel->GetDockParent());
\r
2281 pDockTopLevel = pDockTopLevel->GetDockParent();
\r
2284 return pDockTopLevel;
\r
2287 inline CTabbedMDI* CDocker::GetTabbedMDI() const
\r
2289 CTabbedMDI* pTabbedMDI = NULL;
\r
2290 if (dynamic_cast<CTabbedMDI*>(GetView()))
\r
2291 pTabbedMDI = (CTabbedMDI*)GetView();
\r
2293 return pTabbedMDI;
\r
2296 inline int CDocker::GetTextHeight()
\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
2303 CClientDC dc(this);
\r
2304 dc.CreateFontIndirect(&lf);
\r
2305 CSize szText = dc.GetTextExtentPoint32(_T("Text"), lstrlen(_T("Text")));
\r
2309 inline void CDocker::Hide()
\r
2311 // Undocks a docker (if needed) and hides it.
\r
2312 // Do unhide the docker, dock it.
\r
2316 if (dynamic_cast<CDockContainer*>(GetView()))
\r
2318 CDockContainer* pContainer = GetContainer();
\r
2319 CDocker* pDock = GetDockFromView(pContainer->GetContainerParent());
\r
2320 pDock->UndockContainer(pContainer, GetCursorPos(), FALSE);
\r
2324 CDocker* pDockUndockedFrom = SeparateFromDock();
\r
2325 pDockUndockedFrom->RecalcDockLayout();
\r
2329 ShowWindow(SW_HIDE);
\r
2332 inline BOOL CDocker::IsChildOfDocker(CWnd* pWnd) const
\r
2333 // returns true if the specified window is a child of this docker
\r
2335 while ((pWnd != NULL) && (pWnd != GetDockAncestor()))
\r
2337 if (pWnd == (CWnd*)this) return TRUE;
\r
2338 if (IsRelated(pWnd)) break;
\r
2339 pWnd = pWnd->GetParent();
\r
2345 inline BOOL CDocker::IsDocked() const
\r
2347 return (((m_DockStyle&0xF) || (m_DockStyle & DS_DOCKED_CONTAINER)) && !m_Undocking); // Boolean expression
\r
2350 inline BOOL CDocker::IsDragAutoResize()
\r
2352 return m_bDragAutoResize;
\r
2355 inline BOOL CDocker::IsRelated(CWnd* pWnd) const
\r
2356 // Returns TRUE if the hWnd is a docker within this dock family
\r
2358 if (GetDockAncestor() == pWnd) return TRUE;
\r
2360 std::vector<DockPtr>::iterator iter;
\r
2361 for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
\r
2363 if ((*iter).get() == pWnd) return TRUE;
\r
2369 inline BOOL CDocker::IsUndocked() const
\r
2371 return (!((m_DockStyle&0xF)|| (m_DockStyle & DS_DOCKED_CONTAINER)) && !m_Undocking); // Boolean expression
\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
2378 BOOL bResult = FALSE;
\r
2380 if (szRegistryKeyName)
\r
2382 std::vector<DockInfo> vDockList;
\r
2383 std::vector<int> vActiveContainers;
\r
2385 CString strKey = _T("Software\\") + CString(szRegistryKeyName) + _T("\\Dock Windows");
\r
2387 RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey);
\r
2390 DWORD dwType = REG_BINARY;
\r
2391 DWORD BufferSize = sizeof(DockInfo);
\r
2394 TCHAR szNumber[20];
\r
2395 CString strSubKey = _T("DockChild");
\r
2396 strSubKey += _itot(i, szNumber, 10);
\r
2398 // Fill the DockList vector from the registry
\r
2399 while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&di, &BufferSize))
\r
2401 vDockList.push_back(di);
\r
2403 strSubKey = _T("DockChild");
\r
2404 strSubKey += _itot(i, szNumber, 10);
\r
2407 dwType = REG_DWORD;
\r
2408 BufferSize = sizeof(int);
\r
2411 strSubKey = _T("ActiveContainer");
\r
2412 strSubKey += _itot(i, szNumber, 10);
\r
2414 // Fill the DockList vector from the registry
\r
2415 while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&nID, &BufferSize))
\r
2417 vActiveContainers.push_back(nID);
\r
2419 strSubKey = _T("ActiveContainer");
\r
2420 strSubKey += _itot(i, szNumber, 10);
\r
2423 RegCloseKey(hKey);
\r
2424 if (vDockList.size() > 0) bResult = TRUE;
\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
2431 DockInfo di = (*iter);
\r
2432 if (di.DockParentID == 0)
\r
2434 CDocker* pDocker = NewDockerFromID(di.DockID);
\r
2437 if (di.DockStyle & 0xF)
\r
2438 AddDockedChild(pDocker, di.DockStyle, di.DockSize, di.DockID);
\r
2440 AddUndockedChild(pDocker, di.DockStyle, di.DockSize, di.Rect, di.DockID);
\r
2444 TRACE(_T("Failed to add dockers without parents from registry"));
\r
2450 // Remove dockers without parents from vDockList
\r
2451 for (UINT n = (UINT)vDockList.size(); n > 0; --n)
\r
2453 iter = vDockList.begin() + n-1;
\r
2454 if ((*iter).DockParentID == 0)
\r
2455 vDockList.erase(iter);
\r
2458 // Add remaining dockers
\r
2459 while (vDockList.size() > 0)
\r
2461 bool bFound = false;
\r
2462 std::vector<DockInfo>::iterator iter;
\r
2463 for (iter = vDockList.begin(); iter < vDockList.end(); ++iter)
\r
2465 DockInfo di = *iter;
\r
2466 CDocker* pDockParent = GetDockFromID(di.DockParentID);
\r
2468 if (pDockParent != 0)
\r
2470 CDocker* pDock = NewDockerFromID(di.DockID);
\r
2473 pDockParent->AddDockedChild(pDock, di.DockStyle, di.DockSize, di.DockID);
\r
2478 TRACE(_T("Failed to add dockers with parents from registry"));
\r
2482 vDockList.erase(iter);
\r
2489 TRACE(_T("Orphaned dockers stored in registry "));
\r
2495 std::vector<int>::iterator iterID;
\r
2496 for (iterID = vActiveContainers.begin(); iterID < vActiveContainers.end(); ++iterID)
\r
2498 CDocker* pDocker = GetDockFromID(*iterID);
\r
2501 CDockContainer* pContainer = pDocker->GetContainer();
\r
2504 int nPage = pContainer->GetContainerIndex(pContainer);
\r
2506 pContainer->SelectPage(nPage);
\r
2512 if (!bResult) CloseAllDockers();
\r
2516 inline void CDocker::MoveDockChildren(CDocker* pDockTarget)
\r
2517 // Used internally by Dock and Undock
\r
2519 assert(pDockTarget);
\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
2525 pDockTarget->GetDockChildren().push_back(*iter);
\r
2526 (*iter)->m_pDockParent = pDockTarget;
\r
2527 (*iter)->SetParent(pDockTarget);
\r
2528 (*iter)->GetDockBar().SetParent(pDockTarget);
\r
2530 GetDockChildren().clear();
\r
2533 inline CDocker* CDocker::NewDockerFromID(int nID)
\r
2534 // Used in LoadRegistrySettings. Creates a new Docker from the specified ID
\r
2536 UNREFERENCED_PARAMETER(nID);
\r
2538 // Override this function to create the Docker objects as shown below
\r
2540 CDocker* pDock = NULL;
\r
2544 pDock = new CDockClasses;
\r
2547 pDock = new CDockFiles;
\r
2550 TRACE(_T("Unknown Dock ID\n"));
\r
2557 inline void CDocker::OnActivate(WPARAM wParam, LPARAM lParam)
\r
2559 UNREFERENCED_PARAMETER(lParam);
\r
2561 // Only top level undocked dockers get this message
\r
2562 if (LOWORD(wParam) == WA_INACTIVE)
\r
2564 GetTopmostDocker()->m_hOldFocus = ::GetFocus();
\r
2566 // Send a notification of focus lost
\r
2567 int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
\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
2576 inline void CDocker::OnCaptionTimer(WPARAM wParam, LPARAM lParam)
\r
2578 UNREFERENCED_PARAMETER(lParam);
\r
2580 if (this == GetDockAncestor())
\r
2584 DrawAllCaptions();
\r
2586 if (m_nTimerCount == 10)
\r
2588 KillTimer(wParam);
\r
2589 m_nTimerCount = 0;
\r
2595 inline void CDocker::OnCreate()
\r
2598 #if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
\r
2599 if (GetParent()->GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
\r
2601 DWORD dwExStyle = (DWORD)GetWindowLongPtr(GWL_EXSTYLE);
\r
2602 SetWindowLongPtr(GWL_EXSTYLE, dwExStyle | WS_EX_LAYOUTRTL);
\r
2606 // Create the various child windows
\r
2607 GetDockClient().SetDock(this);
\r
2608 GetDockClient().Create(this);
\r
2610 assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
\r
2611 GetView()->Create(&GetDockClient());
\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
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
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
2628 if (pTheme && pTheme->UseThemes && pTheme->clrBkgnd2 != 0)
\r
2629 rgbColour =pTheme->clrBkgnd2;
\r
2631 SetBarColor(rgbColour);
\r
2633 // Set the caption height based on text height
\r
2634 m_NCHeight = MAX(20, GetTextHeight() + 5);
\r
2637 inline void CDocker::OnDestroy(WPARAM wParam, LPARAM lParam)
\r
2639 UNREFERENCED_PARAMETER(wParam);
\r
2640 UNREFERENCED_PARAMETER(lParam);
\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
2646 (*iter)->Destroy();
\r
2649 if (dynamic_cast<CDockContainer*>(GetView()) && IsUndocked())
\r
2651 CDockContainer* pContainer = (CDockContainer*)GetView();
\r
2652 if (pContainer->GetAllContainers().size() > 1)
\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
2659 if ((*iter).pContainer != pContainer)
\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
2672 GetDockBar().Destroy();
\r
2674 // Post a destroy docker message
\r
2675 if ( GetDockAncestor()->IsWindow() )
\r
2676 GetDockAncestor()->PostMessage(UWM_DOCK_DESTROYED, (WPARAM)this, 0L);
\r
2679 inline void CDocker::OnDockDestroyed(WPARAM wParam, LPARAM lParam)
\r
2681 UNREFERENCED_PARAMETER(lParam);
\r
2683 CDocker* pDock = (CDocker*)wParam;
\r
2685 assert( this == GetDockAncestor() );
\r
2686 std::vector<DockPtr>::iterator iter;
\r
2687 for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
\r
2689 if ((*iter).get() == pDock)
\r
2691 GetAllDockers().erase(iter);
\r
2697 inline void CDocker::OnExitSizeMove(WPARAM wParam, LPARAM lParam)
\r
2699 UNREFERENCED_PARAMETER(wParam);
\r
2700 UNREFERENCED_PARAMETER(lParam);
\r
2702 m_BlockMove = FALSE;
\r
2703 m_bIsDragging = FALSE;
\r
2704 SendNotify(UWM_DOCK_END);
\r
2707 inline LRESULT CDocker::OnNotify(WPARAM wParam, LPARAM lParam)
\r
2709 UNREFERENCED_PARAMETER(wParam);
\r
2710 LPDRAGPOS pdp = (LPDRAGPOS)lParam;
\r
2712 switch (((LPNMHDR)lParam)->code)
\r
2714 case UWM_DOCK_START:
\r
2718 Undock(GetCursorPos());
\r
2719 SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pdp->ptPos.x, pdp->ptPos.y));
\r
2724 case UWM_DOCK_MOVE:
\r
2726 CheckAllTargets((LPDRAGPOS)lParam);
\r
2730 case UWM_DOCK_END:
\r
2732 CDocker* pDock = (CDocker*)FromHandle(pdp->hdr.hwndFrom);
\r
2733 if (NULL == pDock) break;
\r
2735 UINT DockZone = pdp->DockZone;
\r
2736 CRect rc = pDock->GetWindowRect();
\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
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
2750 case DS_DOCKED_CONTAINER:
\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
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
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
2770 GetDockHint().Destroy();
\r
2771 CloseAllTargets();
\r
2775 case UWM_BAR_START:
\r
2777 CPoint pt = pdp->ptPos;
\r
2778 ScreenToClient(pt);
\r
2779 if (!IsDragAutoResize())
\r
2780 DrawHashBar(pdp->hdr.hwndFrom, pt);
\r
2785 case UWM_BAR_MOVE:
\r
2787 CPoint pt = pdp->ptPos;
\r
2788 ScreenToClient(pt);
\r
2790 if (pt != m_OldPoint)
\r
2792 if (IsDragAutoResize())
\r
2793 ResizeDockers(pdp);
\r
2796 DrawHashBar(pdp->hdr.hwndFrom, m_OldPoint);
\r
2797 DrawHashBar(pdp->hdr.hwndFrom, pt);
\r
2807 POINT pt = pdp->ptPos;
\r
2808 ScreenToClient(pt);
\r
2810 if (!IsDragAutoResize())
\r
2811 DrawHashBar(pdp->hdr.hwndFrom, pt);
\r
2813 ResizeDockers(pdp);
\r
2817 if (GetDockAncestor()->IsWindow())
\r
2818 GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
\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
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
2836 inline void CDocker::ResizeDockers(LPDRAGPOS pdp)
\r
2837 // Called when the docker's splitter bar is dragged
\r
2841 POINT pt = pdp->ptPos;
\r
2842 ScreenToClient(pt);
\r
2844 CDocker* pDock = ((CDockBar*)FromHandle(pdp->hdr.hwndFrom))->GetDock();
\r
2845 if (NULL == pDock) return;
\r
2847 RECT rcDock = pDock->GetWindowRect();
\r
2848 ScreenToClient(rcDock);
\r
2850 double dBarWidth = pDock->GetDockBar().GetWidth();
\r
2851 int iBarWidth = pDock->GetDockBar().GetWidth();
\r
2854 switch (pDock->GetDockStyle() & 0xF)
\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
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
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
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
2882 RecalcDockLayout();
\r
2885 inline void CDocker::OnSetFocus(WPARAM wParam, LPARAM lParam)
\r
2887 UNREFERENCED_PARAMETER(wParam);
\r
2888 UNREFERENCED_PARAMETER(lParam);
\r
2890 if (IsUndocked() && m_hOldFocus)
\r
2891 ::SetFocus(m_hOldFocus);
\r
2893 // Pass focus on the the view window
\r
2894 GetView()->SetFocus();
\r
2896 if ((this == GetTopmostDocker()) && (this != GetDockAncestor()))
\r
2898 // Send a notification to top level window
\r
2899 int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
\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
2908 inline void CDocker::OnSysColorChange(WPARAM wParam, LPARAM lParam)
\r
2910 UNREFERENCED_PARAMETER(wParam);
\r
2911 UNREFERENCED_PARAMETER(lParam);
\r
2913 if (this == GetDockAncestor())
\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
2919 if (pTheme && pTheme->UseThemes && pTheme->clrBand2 != 0)
\r
2920 rgbColour = pTheme->clrBkgnd2;
\r
2922 rgbColour = GetSysColor(COLOR_BTNFACE);
\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
2929 // Set the splitter bar colour for the docker ancestor
\r
2930 SetBarColor(rgbColour);
\r
2934 inline LRESULT CDocker::OnSysCommand(WPARAM wParam, LPARAM lParam)
\r
2936 switch(wParam&0xFFF0)
\r
2939 // An undocked docker is being moved
\r
2941 BOOL bResult = FALSE;
\r
2942 m_bIsDragging = TRUE;
\r
2943 SetCursor(LoadCursor(NULL, IDC_ARROW));
\r
2945 if (SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &bResult, 0))
\r
2947 // Turn on DragFullWindows for this move
\r
2948 SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, 0, 0);
\r
2950 // Process this message
\r
2951 DefWindowProc(WM_SYSCOMMAND, wParam, lParam);
\r
2953 // Return DragFullWindows to its previous state
\r
2954 SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, bResult, 0, 0);
\r
2960 // The close button is pressed on an undocked docker
\r
2961 m_bIsClosing = TRUE;
\r
2964 return CWnd::WndProcDefault(WM_SYSCOMMAND, wParam, lParam);
\r
2967 inline LRESULT CDocker::OnWindowPosChanging(WPARAM wParam, LPARAM lParam)
\r
2969 // Suspend dock drag moving while over dock zone
\r
2972 LPWINDOWPOS pWndPos = (LPWINDOWPOS)lParam;
\r
2973 pWndPos->flags |= SWP_NOMOVE|SWP_FRAMECHANGED;
\r
2977 return CWnd::WndProcDefault(WM_WINDOWPOSCHANGING, wParam, lParam);
\r
2980 inline void CDocker::OnWindowPosChanged(WPARAM wParam, LPARAM lParam)
\r
2982 UNREFERENCED_PARAMETER(wParam);
\r
2984 if (m_bIsDragging)
\r
2986 // Send a Move notification to the parent
\r
2987 if ( IsLeftButtonDown() )
\r
2989 LPWINDOWPOS wPos = (LPWINDOWPOS)lParam;
\r
2990 if ((!(wPos->flags & SWP_NOMOVE)) || m_BlockMove)
\r
2991 SendNotify(UWM_DOCK_MOVE);
\r
2995 CloseAllTargets();
\r
2996 m_BlockMove = FALSE;
\r
2999 else if (this == GetTopmostDocker())
\r
3001 // Reposition the dock children
\r
3002 if (IsUndocked() && IsWindowVisible() && !m_bIsClosing) RecalcDockLayout();
\r
3006 inline void CDocker::PreCreate(CREATESTRUCT &cs)
\r
3008 // Specify the WS_POPUP style to have this window owned
\r
3009 if (this != GetDockAncestor())
\r
3010 cs.style = WS_POPUP;
\r
3012 cs.dwExStyle = WS_EX_TOOLWINDOW;
\r
3015 inline void CDocker::PreRegisterClass(WNDCLASS &wc)
\r
3017 wc.lpszClassName = _T("Win32++ Docker");
\r
3018 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
\r
3021 inline void CDocker::RecalcDockChildLayout(CRect rc)
\r
3023 // This function positions the Docker's dock children, the Dockers client area
\r
3024 // and draws the dockbar bars.
\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
3032 // Note: All top level dockers are undocked, including the dock ancestor.
\r
3035 rc.OffsetRect(-rc.left, -rc.top);
\r
3038 HDWP hdwp = BeginDeferWindowPos((int)m_vDockChildren.size() +2);
\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
3044 CRect rcChild = rc;
\r
3045 double DockSize = m_vDockChildren[u]->m_DockStartSize;;
\r
3047 // Calculate the size of the Docker children
\r
3048 switch (m_vDockChildren[u]->GetDockStyle() & 0xF)
\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
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
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
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
3072 if (m_vDockChildren[u]->IsDocked())
\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
3078 rc.SubtractRect(rc, rcChild);
\r
3080 // Calculate the dimensions of the splitter bar
\r
3082 DWORD DockSide = m_vDockChildren[u]->GetDockStyle() & 0xF;
\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
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
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
3099 // Position the dockbar. Only docked dockers have a dock bar.
\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
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
3109 m_vDockChildren[v]->RecalcDockChildLayout(m_vDockChildren[v]->m_rcChild);
\r
3113 inline void CDocker::RecalcDockLayout()
\r
3114 // Repositions the dock children of a top level docker
\r
3116 if (GetDockAncestor()->IsWindow())
\r
3118 CRect rc = GetTopmostDocker()->GetClientRect();
\r
3119 GetTopmostDocker()->RecalcDockChildLayout(rc);
\r
3120 GetTopmostDocker()->UpdateWindow();
\r
3124 inline std::vector<CDocker*> CDocker::SortDockers()
\r
3125 // Returns a vector of sorted dockers, used by SaveRegistrySettings.
\r
3127 std::vector<CDocker*> vSorted;
\r
3128 std::vector<CDocker*>::iterator itSort;
\r
3129 std::vector<DockPtr>::iterator itAll;
\r
3131 // Add undocked top level dockers
\r
3132 for (itAll = GetAllDockers().begin(); itAll < GetAllDockers().end(); ++itAll)
\r
3134 if (!(*itAll)->GetDockParent())
\r
3135 vSorted.push_back((*itAll).get());
\r
3138 // Add dock ancestor's children
\r
3139 vSorted.insert(vSorted.end(), GetDockAncestor()->GetDockChildren().begin(), GetDockAncestor()->GetDockChildren().end());
\r
3141 // Add other dock children
\r
3143 itSort = vSorted.begin();
\r
3144 while (itSort < vSorted.end())
\r
3146 vSorted.insert(vSorted.end(), (*itSort)->GetDockChildren().begin(), (*itSort)->GetDockChildren().end());
\r
3147 itSort = vSorted.begin() + (++index);
\r
3150 // Add dockers docked in containers
\r
3151 std::vector<CDocker*> vDockContainers;
\r
3152 for (itSort = vSorted.begin(); itSort< vSorted.end(); ++itSort)
\r
3154 if ((*itSort)->GetContainer())
\r
3155 vDockContainers.push_back(*itSort);
\r
3158 for (itSort = vDockContainers.begin(); itSort < vDockContainers.end(); ++itSort)
\r
3160 CDockContainer* pContainer = (*itSort)->GetContainer();
\r
3162 for (UINT i = 1; i < pContainer->GetAllContainers().size(); ++i)
\r
3164 CDockContainer* pChild = pContainer->GetContainerFromIndex(i);
\r
3165 CDocker* pDock = GetDockFromView(pChild);
\r
3166 vSorted.push_back(pDock);
\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
3177 assert(VerifyDockers());
\r
3179 std::vector<CDocker*> vSorted = SortDockers();
\r
3180 std::vector<CDocker*>::iterator iter;
\r
3181 std::vector<DockInfo> vDockInfo;
\r
3183 if (szRegistryKeyName)
\r
3185 // Fill the DockInfo vector with the docking information
\r
3186 for (iter = vSorted.begin(); iter < vSorted.end(); ++iter)
\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
3196 vDockInfo.push_back(di);
\r
3199 CString strKeyName = _T("Software\\") + CString(szRegistryKeyName);
\r
3201 HKEY hKeyDock = NULL;
\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
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
3212 // Add the Dock windows information to the registry
\r
3213 for (UINT u = 0; u < vDockInfo.size(); ++u)
\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
3223 // Add Active Container to the registry
\r
3225 for (iter = vSorted.begin(); iter < vSorted.end(); ++iter)
\r
3227 CDockContainer* pContainer = (*iter)->GetContainer();
\r
3229 if (pContainer && (pContainer == pContainer->GetActiveContainer()))
\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
3240 RegCloseKey(hKeyDock);
\r
3241 RegCloseKey(hKey);
\r
3244 catch (const CWinException& e)
\r
3246 // Roll back the registry changes by deleting the subkeys
\r
3251 RegDeleteKey(hKeyDock, _T("Dock Windows"));
\r
3252 RegCloseKey(hKeyDock);
\r
3255 RegDeleteKey(HKEY_CURRENT_USER, strKeyName);
\r
3256 RegCloseKey(hKey);
\r
3267 inline void CDocker::SendNotify(UINT nMessageID)
\r
3268 // Sends a docking notification to the docker below the cursor
\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
3277 CDocker* pDock = GetDockFromPoint(DragPos.ptPos);
\r
3280 pDock->SendMessage(WM_NOTIFY, 0L, (LPARAM)&DragPos);
\r
3283 if (GetDockHint().IsWindow()) GetDockHint().Destroy();
\r
3284 CloseAllTargets();
\r
3285 m_BlockMove = FALSE;
\r
3289 inline void CDocker::SetDockStyle(DWORD dwDockStyle)
\r
3293 if ((dwDockStyle & DS_CLIENTEDGE) != (m_DockStyle & DS_CLIENTEDGE))
\r
3295 if (dwDockStyle & DS_CLIENTEDGE)
\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
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
3310 RecalcDockLayout();
\r
3313 m_DockStyle = dwDockStyle;
\r
3316 inline void CDocker::SetCaption(LPCTSTR szCaption)
\r
3317 // Sets the caption text
\r
3319 GetDockClient().SetCaption(szCaption);
\r
3322 SetWindowText(szCaption);
\r
3325 inline void CDocker::SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2)
\r
3327 GetDockClient().SetCaptionColors(Foregnd1, Backgnd1, ForeGnd2, BackGnd2);
\r
3330 inline void CDocker::SetCaptionHeight(int nHeight)
\r
3331 // Sets the height of the caption
\r
3333 m_NCHeight = nHeight;
\r
3335 RecalcDockLayout();
\r
3338 inline void CDocker::SetDockSize(int DockSize)
\r
3339 // Sets the size of a docked docker
\r
3343 assert (m_pDockParent);
\r
3344 switch (GetDockStyle() & 0xF)
\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
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
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
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
3364 RecalcDockLayout();
\r
3368 m_DockStartSize = DockSize;
\r
3369 m_DockSizeRatio = 1.0;
\r
3373 inline void CDocker::SetDragAutoResize(BOOL bAutoResize)
\r
3375 m_bDragAutoResize = bAutoResize;
\r
3378 inline void CDocker::SetView(CWnd& wndView)
\r
3379 // Assigns the view window to the docker
\r
3381 CWnd* pWnd = &wndView;
\r
3382 GetDockClient().SetView(wndView);
\r
3383 if (dynamic_cast<CDockContainer*>(pWnd))
\r
3385 CDockContainer* pContainer = (CDockContainer*)&wndView;
\r
3386 SetCaption(pContainer->GetDockCaption().c_str());
\r
3390 inline void CDocker::PromoteFirstChild()
\r
3391 // One of the steps required for undocking
\r
3393 // Promote our first child to replace ourself
\r
3394 if (m_pDockParent)
\r
3396 for (UINT u = 0 ; u < m_pDockParent->m_vDockChildren.size(); ++u)
\r
3398 if (m_pDockParent->m_vDockChildren[u] == this)
\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
3404 // remove ourself as a child of the parent
\r
3405 m_pDockParent->m_vDockChildren.erase(m_pDockParent->m_vDockChildren.begin() + u);
\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
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
3420 if (m_pDockParent)
\r
3422 pDockFirstChild->m_pDockParent = m_pDockParent;
\r
3423 pDockFirstChild->SetParent(m_pDockParent);
\r
3424 pDockFirstChild->GetDockBar().SetParent(m_pDockParent);
\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
3432 pDockFirstChild->ConvertToPopup(GetWindowRect());
\r
3433 pDockFirstChild->GetDockBar().ShowWindow(SW_HIDE);
\r
3436 m_vDockChildren.erase(m_vDockChildren.begin());
\r
3437 MoveDockChildren(pDockFirstChild);
\r
3441 inline void CDocker::ConvertToChild(HWND hWndParent)
\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
3449 inline void CDocker::ConvertToPopup(RECT rc)
\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
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
3461 SetWindowPos(NULL, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOOWNERZORDER);
\r
3462 GetDockClient().SetWindowPos(NULL, GetClientRect(), SWP_SHOWWINDOW);
\r
3464 SetWindowText(GetCaption().c_str());
\r
3467 inline CDocker* CDocker::SeparateFromDock()
\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
3475 GetTopmostDocker()->m_hOldFocus = 0;
\r
3476 PromoteFirstChild();
\r
3477 m_pDockParent = 0;
\r
3479 GetDockBar().ShowWindow(SW_HIDE);
\r
3480 m_DockStyle = m_DockStyle & 0xFFFFFFF0;
\r
3481 m_DockStyle &= ~DS_DOCKED_CONTAINER;
\r
3483 return pDockUndockedFrom;
\r
3486 inline void CDocker::SetUndockPosition(CPoint pt)
\r
3488 m_Undocking = TRUE;
\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
3496 ConvertToPopup(rc);
\r
3497 m_Undocking = FALSE;
\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
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
3513 inline void CDocker::Undock(CPoint pt, BOOL bShowUndocked)
\r
3515 // Return if we shouldn't undock
\r
3516 if (GetDockStyle() & DS_NO_UNDOCK) return;
\r
3518 // Undocking isn't supported on Win95
\r
3519 if (1400 == GetWinVersion()) return;
\r
3521 CDocker* pDockUndockedFrom = SeparateFromDock();
\r
3523 // Position and draw the undocked window, unless it is about to be closed
\r
3524 if (bShowUndocked)
\r
3526 SetUndockPosition(pt);
\r
3529 RecalcDockLayout();
\r
3530 if ((pDockUndockedFrom) && (pDockUndockedFrom->GetTopmostDocker() != GetTopmostDocker()))
\r
3531 pDockUndockedFrom->RecalcDockLayout();
\r
3534 inline void CDocker::UndockContainer(CDockContainer* pContainer, CPoint pt, BOOL bShowUndocked)
\r
3536 assert(pContainer);
\r
3537 assert(this == GetDockFromView(pContainer->GetContainerParent()));
\r
3539 // Return if we shouldn't undock
\r
3540 if (GetDockFromView(pContainer)->GetDockStyle() & DS_NO_UNDOCK) return;
\r
3542 if (GetDockFromView(pContainer) == GetDockAncestor()) return;
\r
3544 // Undocking isn't supported on Win95
\r
3545 if (1400 == GetWinVersion()) return;
\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
3552 // The parent container is being undocked, so we need
\r
3553 // to transfer our child containers to a different docker
\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
3562 if ((*iter).pContainer != pContainer)
\r
3563 pDockNew = (CDocker*)FromHandle(::GetParent((*iter).pContainer->GetParent()->GetHwnd()));
\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
3574 if ((*iter).pContainer != pContainer)
\r
3576 CDockContainer* pChildContainer = (CDockContainer*)(*iter).pContainer;
\r
3577 pContainer->RemoveContainer(pChildContainer);
\r
3578 if (pContainerNew != pChildContainer)
\r
3580 pContainerNew->AddContainer(pChildContainer);
\r
3581 CDocker* pDock = GetDockFromView(pChildContainer);
\r
3582 pDock->SetParent(pDockNew);
\r
3583 pDock->m_pDockParent = pDockNew;
\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
3595 pDockNew->m_pDockParent = pDockOld->m_pDockParent;
\r
3596 pDockNew->SetParent(pDockOld->GetParent());
\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
3608 pDockNew->GetDockBar().SetParent(pDockOld->GetParent());
\r
3609 pDockNew->GetView()->SetFocus();
\r
3611 // Transfer the Dock children to the new docker
\r
3612 pDockOld->MoveDockChildren(pDockNew);
\r
3614 // insert pDockNew into its DockParent's DockChildren vector
\r
3615 if (pDockNew->m_pDockParent)
\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
3622 pDockNew->m_pDockParent->m_vDockChildren.insert(p, pDockNew);
\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
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
3650 inline LRESULT CDocker::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
3655 OnActivate(wParam, lParam);
\r
3657 case WM_SYSCOMMAND:
\r
3658 return OnSysCommand(wParam, lParam);
\r
3660 case WM_EXITSIZEMOVE:
\r
3661 OnExitSizeMove(wParam, lParam);
\r
3663 case WM_WINDOWPOSCHANGING:
\r
3664 return OnWindowPosChanging(wParam, lParam);
\r
3666 case WM_WINDOWPOSCHANGED:
\r
3667 OnWindowPosChanged(wParam, lParam);
\r
3670 OnDestroy(wParam, lParam);
\r
3673 OnSetFocus(wParam, lParam);
\r
3676 OnCaptionTimer(wParam, lParam);
\r
3678 case UWM_DOCK_DESTROYED:
\r
3679 OnDockDestroyed(wParam, lParam);
\r
3681 case UWM_DOCK_ACTIVATED:
\r
3682 DrawAllCaptions();
\r
3683 SetTimer(1, 100, NULL);
\r
3685 case WM_SYSCOLORCHANGE:
\r
3686 OnSysColorChange(wParam, lParam);
\r
3688 case WM_NCLBUTTONDBLCLK :
\r
3689 m_bIsDragging = FALSE;
\r
3693 return CWnd::WndProcDefault(uMsg, wParam, lParam);
\r
3697 //////////////////////////////////////
\r
3698 // Declaration of the CDockContainer class
\r
3699 inline CDockContainer::CDockContainer() : m_iCurrentPage(0), m_hTabIcon(0), m_nTabPressed(-1)
\r
3701 m_pContainerParent = this;
\r
3704 inline CDockContainer::~CDockContainer()
\r
3707 DestroyIcon(m_hTabIcon);
\r
3710 inline void CDockContainer::AddContainer(CDockContainer* pContainer)
\r
3712 assert(pContainer);
\r
3714 if (this == m_pContainerParent)
\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
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
3734 pContainer->m_pContainerParent = this;
\r
3735 if (pContainer->IsWindow())
\r
3737 // Set the parent container relationships
\r
3738 pContainer->GetViewPage().SetParent(this);
\r
3739 pContainer->GetViewPage().ShowWindow(SW_HIDE);
\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
3748 GetToolBar().AddButton(nID, bEnabled);
\r
3751 inline CDockContainer* CDockContainer::GetContainerFromIndex(UINT nPage)
\r
3753 CDockContainer* pContainer = NULL;
\r
3754 if (nPage < m_vContainerInfo.size())
\r
3755 pContainer = (CDockContainer*)m_vContainerInfo[nPage].pContainer;
\r
3757 return pContainer;
\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
3763 CWnd* pWnd = NULL;
\r
3764 if (m_pContainerParent->m_vContainerInfo.size() > 0)
\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
3774 inline CDockContainer* CDockContainer::GetContainerFromView(CWnd* pView) const
\r
3778 std::vector<ContainerInfo>::iterator iter;
\r
3779 CDockContainer* pViewContainer = 0;
\r
3780 for (iter = GetAllContainers().begin(); iter != GetAllContainers().end(); ++iter)
\r
3782 CDockContainer* pContainer = (*iter).pContainer;
\r
3783 if (pContainer->GetView() == pView)
\r
3784 pViewContainer = pContainer;
\r
3787 return pViewContainer;
\r
3790 inline int CDockContainer::GetContainerIndex(CDockContainer* pContainer)
\r
3792 assert(pContainer);
\r
3795 for (int i = 0; i < (int)m_pContainerParent->m_vContainerInfo.size(); ++i)
\r
3797 if (m_pContainerParent->m_vContainerInfo[i].pContainer == pContainer)
\r
3804 inline SIZE CDockContainer::GetMaxTabTextSize()
\r
3808 // Allocate an iterator for the ContainerInfo vector
\r
3809 std::vector<ContainerInfo>::iterator iter;
\r
3811 for (iter = m_vContainerInfo.begin(); iter != m_vContainerInfo.end(); ++iter)
\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
3827 inline void CDockContainer::SetupToolBar()
\r
3829 // Use this function to set the Resource IDs for the toolbar(s).
\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
3846 inline void CDockContainer::OnCreate()
\r
3848 assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
\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
3856 // Create the page window
\r
3857 GetViewPage().Create(this);
\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
3865 if (GetToolBar().GetToolBarData().size() > 0)
\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
3872 GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);
\r
3875 GetToolBar().Destroy();
\r
3877 SetFixedWidth(TRUE);
\r
3878 SetOwnerDraw(TRUE);
\r
3880 // Add tabs for each container.
\r
3881 for (int i = 0; i < (int)m_vContainerInfo.size(); ++i)
\r
3883 // Add tabs for each view.
\r
3885 tie.mask = TCIF_TEXT | TCIF_IMAGE;
\r
3887 tie.pszText = m_vContainerInfo[i].szTitle;
\r
3888 TabCtrl_InsertItem(m_hWnd, i, &tie);
\r
3892 inline void CDockContainer::OnLButtonDown(WPARAM wParam, LPARAM lParam)
\r
3894 // Overrides CTab::OnLButtonDown
\r
3896 UNREFERENCED_PARAMETER(wParam);
\r
3898 CPoint pt((DWORD)lParam);
\r
3899 TCHITTESTINFO info = {0};
\r
3901 m_nTabPressed = HitTest(info);
\r
3904 inline void CDockContainer::OnLButtonUp(WPARAM wParam, LPARAM lParam)
\r
3906 // Overrides CTab::OnLButtonUp and takes no action
\r
3908 UNREFERENCED_PARAMETER(wParam);
\r
3909 UNREFERENCED_PARAMETER(lParam);
\r
3912 inline void CDockContainer::OnMouseLeave(WPARAM wParam, LPARAM lParam)
\r
3914 // Overrides CTab::OnMouseLeave
\r
3916 if (IsLeftButtonDown() && (m_nTabPressed >= 0))
\r
3918 CDocker* pDock = (CDocker*)FromHandle(::GetParent(GetParent()->GetHwnd()));
\r
3919 if (dynamic_cast<CDocker*>(pDock))
\r
3921 CDockContainer* pContainer = GetContainerFromIndex(m_iCurrentPage);
\r
3922 pDock->UndockContainer(pContainer, GetCursorPos(), TRUE);
\r
3926 m_nTabPressed = -1;
\r
3927 CTab::OnMouseLeave(wParam, lParam);
\r
3930 inline LRESULT CDockContainer::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
\r
3932 UNREFERENCED_PARAMETER(wParam);
\r
3934 switch (((LPNMHDR)lParam)->code)
\r
3936 case TCN_SELCHANGE:
\r
3938 // Display the newly selected tab page
\r
3939 int nPage = GetCurSel();
\r
3940 SelectPage(nPage);
\r
3948 inline void CDockContainer::PreCreate(CREATESTRUCT &cs)
\r
3950 // For Tabs on the bottom, add the TCS_BOTTOM style
\r
3951 CTab::PreCreate(cs);
\r
3952 cs.style |= TCS_BOTTOM;
\r
3955 inline void CDockContainer::RecalcLayout()
\r
3957 if (GetContainerParent() == this)
\r
3959 // Set the tab sizes
\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
3970 inline void CDockContainer::RemoveContainer(CDockContainer* pWnd)
\r
3975 int iTab = GetContainerIndex(pWnd);
\r
3978 // DeleteItem(iTab);
\r
3979 TabCtrl_DeleteItem(m_hWnd, iTab);
\r
3982 // Remove the ContainerInfo entry
\r
3983 std::vector<ContainerInfo>::iterator iter;
\r
3985 for (iter = m_vContainerInfo.begin(); iter != m_vContainerInfo.end(); ++iter)
\r
3987 if (iter->pContainer == pWnd)
\r
3989 iImage = (*iter).iImage;
\r
3991 TabCtrl_RemoveImage(m_hWnd, iImage);
\r
3993 m_vContainerInfo.erase(iter);
\r
3998 // Set the parent container relationships
\r
3999 pWnd->GetViewPage().SetParent(pWnd);
\r
4000 pWnd->m_pContainerParent = pWnd;
\r
4002 // Display the first page
\r
4003 m_iCurrentPage = 0;
\r
4008 inline void CDockContainer::SelectPage(int nPage)
\r
4010 if (this != m_pContainerParent)
\r
4011 m_pContainerParent->SelectPage(nPage);
\r
4014 if ((nPage >= 0) && (nPage < (int)m_vContainerInfo.size() ))
\r
4016 if (GetCurSel() != nPage)
\r
4019 // Create the new container window if required
\r
4020 if (!m_vContainerInfo[nPage].pContainer->IsWindow())
\r
4022 CDockContainer* pContainer = m_vContainerInfo[nPage].pContainer;
\r
4023 pContainer->Create(GetParent());
\r
4024 pContainer->GetViewPage().SetParent(this);
\r
4027 // Determine the size of the tab page's view area
\r
4028 CRect rc = GetClientRect();
\r
4029 AdjustRect(FALSE, &rc);
\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
4038 // Adjust the docking caption
\r
4039 CDocker* pDock = (CDocker*)FromHandle(::GetParent(::GetParent(m_hWnd)));
\r
4040 if (dynamic_cast<CDocker*>(pDock))
\r
4042 pDock->SetCaption(pNewContainer->GetDockCaption().c_str());
\r
4043 pDock->RedrawWindow();
\r
4046 m_iCurrentPage = nPage;
\r
4051 inline void CDockContainer::SetActiveContainer(CDockContainer* pContainer)
\r
4053 int nPage = GetContainerIndex(pContainer);
\r
4054 assert (0 <= nPage);
\r
4055 SelectPage(nPage);
\r
4058 inline void CDockContainer::SetTabIcon(UINT nID_Icon)
\r
4060 HICON hIcon = (HICON)LoadImage(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(nID_Icon), IMAGE_ICON, 0, 0, LR_SHARED);
\r
4061 SetTabIcon(hIcon);
\r
4064 inline void CDockContainer::SetTabSize()
\r
4066 CRect rc = GetClientRect();
\r
4067 AdjustRect(FALSE, &rc);
\r
4068 if (rc.Width() < 0 )
\r
4069 rc.SetRectEmpty();
\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
4076 inline void CDockContainer::SetTabText(UINT nTab, LPCTSTR szText)
\r
4078 CDockContainer* pContainer = GetContainerParent()->GetContainerFromIndex(nTab);
\r
4079 pContainer->SetTabText(szText);
\r
4081 CTab::SetTabText(nTab, szText);
\r
4084 inline void CDockContainer::SetView(CWnd& Wnd)
\r
4086 GetViewPage().SetView(Wnd);
\r
4089 inline LRESULT CDockContainer::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
4097 // The following are called in CTab::WndProcDefault
\r
4098 // case WM_LBUTTONDOWN:
\r
4099 // OnLButtonDown(wParam, lParam);
\r
4101 // case WM_LBUTTONUP:
\r
4102 // OnLButtonUp(wParam, lParam);
\r
4104 // case WM_MOUSELEAVE:
\r
4105 // OnMouseLeave(wParam, lParam);
\r
4110 // Pass focus on to the current view
\r
4111 GetActiveView()->SetFocus();
\r
4116 // pass unhandled messages on to CTab for processing
\r
4117 return CTab::WndProcDefault(uMsg, wParam, lParam);
\r
4121 ///////////////////////////////////////////
\r
4122 // Declaration of the nested CViewPage class
\r
4123 inline BOOL CDockContainer::CViewPage::OnCommand(WPARAM wParam, LPARAM lParam)
\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
4133 inline void CDockContainer::CViewPage::OnCreate()
\r
4136 m_pView->Create(this);
\r
4139 inline LRESULT CDockContainer::CViewPage::OnNotify(WPARAM wParam, LPARAM lParam)
\r
4141 UNREFERENCED_PARAMETER(wParam);
\r
4143 switch (((LPNMHDR)lParam)->code)
\r
4146 // Display tooltips for the toolbar
\r
4147 case TTN_GETDISPINFO:
\r
4149 int iIndex = GetToolBar().HitTest();
\r
4150 LPNMTTDISPINFO lpDispInfo = (LPNMTTDISPINFO)lParam;
\r
4153 int nID = GetToolBar().GetCommandID(iIndex);
\r
4156 m_strTooltip = LoadString(nID);
\r
4157 lpDispInfo->lpszText = (LPTSTR)m_strTooltip.c_str();
\r
4160 m_strTooltip = _T("");
\r
4164 } // switch LPNMHDR
\r
4169 inline void CDockContainer::CViewPage::PreRegisterClass(WNDCLASS &wc)
\r
4171 wc.lpszClassName = _T("Win32++ TabPage");
\r
4172 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
\r
4175 inline void CDockContainer::CViewPage::RecalcLayout()
\r
4177 CRect rc = GetClientRect();
\r
4178 if (GetToolBar().IsWindow())
\r
4180 GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);
\r
4181 CRect rcToolBar = m_ToolBar.GetClientRect();
\r
4182 rc.top += rcToolBar.Height();
\r
4185 GetView()->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);
\r
4188 inline void CDockContainer::CViewPage::SetView(CWnd& wndView)
\r
4189 // Sets or changes the View window displayed within the frame
\r
4191 // Assign the view window
\r
4192 m_pView = &wndView;
\r
4196 if (!m_pView->IsWindow())
\r
4198 // The container is already created, so create and position the new view too
\r
4199 GetView()->Create(this);
\r
4206 inline LRESULT CDockContainer::CViewPage::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
4214 switch (((LPNMHDR)lParam)->code)
\r
4216 // Send the focus change notifications to the grandparent
\r
4217 case NM_KILLFOCUS:
\r
4219 case UWM_FRAMELOSTFOCUS:
\r
4220 ::SendMessage(::GetParent(::GetParent(m_hWnd)), WM_NOTIFY, wParam, lParam);
\r
4227 // pass unhandled messages on for default processing
\r
4228 return CWnd::WndProcDefault(uMsg, wParam, lParam);
\r
4231 } // namespace Win32xx
\r
4233 #endif // _WIN32XX_DOCKING_H_
\r