- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# sizecbar.cpp

    00001
    00002 //
    00003 // CSizingControlBar            Version 2.43
    00004 //
    00005 // Created: Jan 24, 1998        Last Modified: August 03, 2000
    00006 //
    00007 // See the official site at www.datamekanix.com for documentation and
    00008 // the latest news.
    00009 //
    00011 // Copyright (C) 1998-2000 by Cristi Posea. All rights reserved.
    00012 //
    00013 // This code is free for personal and commercial use, providing this
    00014 // notice remains intact in the source files and all eventual changes are
    00015 // clearly marked with comments.
    00016 //
    00017 // You must obtain the author's consent before you can include this code
    00018 // in a software library.
    00019 //
    00020 // No warrantee of any kind, express or implied, is included with this
    00021 // software; use at your own risk, responsibility for damages (if any) to
    00022 // anyone resulting from the use of this software rests entirely with the
    00023 // user.
    00024 //
    00025 // Send bug reports, bug fixes, enhancements, requests, flames, etc. to
    00026 // cristi@datamekanix.com or post them at the message board at the site.
    00027 //
    00028 // The sources and a short version of the docs are also available at
    00029 // www.codeproject.com . Look for a "Docking Windows" section and check
    00030 // the version to be sure you get the latest one ;)
    00031 //
    00032 // Hint: These classes are intended to be used as base classes. Do not
    00033 // simply add your code to these file - instead create a new class
    00034 // derived from one of CSizingControlBarXX classes and put there what
    00035 // you need. See CMyBar classes in the demo projects for examples.
    00036 // Modify this file only to fix bugs, and don't forget to send me a copy.
    00038 // Acknowledgements:
    00039 //  o   Thanks to Harlan R. Seymour for his continuous support during
    00040 //      development of this code.
    00041 //  o   Thanks to Dundas Software for the opportunity
    00042 //      to test this code on real-life applications.
    00043 //  o   Some ideas for the gripper came from the CToolBarEx flat toolbar
    00044 //      by Joerg Koenig. Thanks, Joerg!
    00045 //  o   Thanks to Robert Wolpow for the code on which CDockContext based
    00046 //      dialgonal resizing is based.
    00047 //  o   Thanks to the following people for various bug fixes and/or
    00048 //      enhancements: Chris Maunder, Jakawan Ratiwanich, Udo Schaefer,
    00049 //      Anatoly Ivasyuk, Peter Hauptmann.
    00050 //  o   And, of course, many thanks to all of you who used this code,
    00051 //      for the invaluable feedback I received.
    00053
    00054 // sizecbar.cpp : implementation file
    00055 //
    00056
    00057 #include "stdafx.h"
    00058 #include "sizecbar.h"
    00059
    00060 #ifdef _DEBUG
    00061 #define new DEBUG_NEW
    00062 #undef THIS_FILE
    00063 static char THIS_FILE[] = __FILE__;
    00064 #endif
    00065
    00067 // CSizingControlBar
    00068
    00069 IMPLEMENT_DYNAMIC(CSizingControlBar, baseCSizingControlBar);
    00070
    00071 CSizingControlBar::CSizingControlBar()
    00072 {
    00073     m_szMinHorz = CSize(33, 32);
    00074     m_szMinVert = CSize(33, 32);
    00075     m_szMinFloat = CSize(37, 32);
    00076     m_szHorz = CSize(200, 200);
    00077     m_szVert = CSize(200, 200);
    00078     m_szFloat = CSize(200, 200);
    00079     m_bTracking = FALSE;
    00080     m_bKeepSize = FALSE;
    00081     m_bParentSizing = FALSE;
    00082     m_cxEdge = 5;
    00083     m_bDragShowContent = FALSE;
    00084     m_nDockBarID = 0;
    00085     m_dwSCBStyle = 0;
    00086 }
    00087
    00088 CSizingControlBar::~CSizingControlBar()
    00089 {
    00090 }
    00091
    00092 BEGIN_MESSAGE_MAP(CSizingControlBar, baseCSizingControlBar)
    00093     //{{AFX_MSG_MAP(CSizingControlBar)
    00094     ON_WM_CREATE()
    00095     ON_WM_PAINT()
    00096     ON_WM_NCPAINT()
    00097     ON_WM_NCCALCSIZE()
    00098     ON_WM_WINDOWPOSCHANGING()
    00099     ON_WM_CAPTURECHANGED()
    00100     ON_WM_SETTINGCHANGE()
    00101     ON_WM_LBUTTONUP()
    00102     ON_WM_MOUSEMOVE()
    00103     ON_WM_NCLBUTTONDOWN()
    00104     ON_WM_LBUTTONDOWN()
    00105     ON_WM_LBUTTONDBLCLK()
    00106     ON_WM_RBUTTONDOWN()
    00107     ON_WM_NCMOUSEMOVE()
    00108     ON_WM_NCHITTEST()
    00109     ON_WM_CLOSE()
    00110     ON_WM_SIZE()
    00111     //}}AFX_MSG_MAP
    00112     ON_MESSAGE(WM_SETTEXT, OnSetText)
    00113 END_MESSAGE_MAP()
    00114
    00115 // old creation method, still here for compatibility reasons
    00116 BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
    00117                                CSize sizeDefault, BOOL bHasGripper,
    00118                                UINT nID, DWORD dwStyle)
    00119 {
    00120     UNUSED_ALWAYS(bHasGripper);
    00121
    00122     m_szHorz = m_szVert = m_szFloat = sizeDefault;
    00123     return Create(lpszWindowName, pParentWnd, nID, dwStyle);
    00124 }
    00125
    00126 // preffered creation method
    00127 BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName,
    00128                                CWnd* pParentWnd, UINT nID,
    00129                                DWORD dwStyle)
    00130 {
    00131     // must have a parent
    00132     ASSERT_VALID(pParentWnd);
    00133     // cannot be both fixed and dynamic
    00134     // (CBRS_SIZE_DYNAMIC is used for resizng when floating)
    00135     ASSERT (!((dwStyle & CBRS_SIZE_FIXED) &&
    00136               (dwStyle & CBRS_SIZE_DYNAMIC)));
    00137
    00138     m_dwStyle = dwStyle & CBRS_ALL; // save the control bar styles
    00139
    00140     // register and create the window - skip CControlBar::Create()
    00141     CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS,
    00142         ::LoadCursor(NULL, IDC_ARROW),
    00143         ::GetSysColorBrush(COLOR_BTNFACE), 0);
    00144
    00145     dwStyle &= ~CBRS_ALL; // keep only the generic window styles
    00146     dwStyle |= WS_CLIPCHILDREN; // prevents flashing
    00147     if (!CWnd::Create(wndclass, lpszWindowName, dwStyle,
    00148         CRect(0, 0, 0, 0), pParentWnd, nID))
    00149         return FALSE;
    00150
    00151     return TRUE;
    00152 }
    00153
    00155 // CSizingControlBar operations
    00156 #if defined(_SCB_REPLACE_MINIFRAME) && !defined(_SCB_MINIFRAME_CAPTION)
    00157 void CSizingControlBar::EnableDocking(DWORD dwDockStyle)
    00158 {
    00159     // must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
    00160     ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
    00161     // cannot have the CBRS_FLOAT_MULTI style
    00162     ASSERT((dwDockStyle & CBRS_FLOAT_MULTI) == 0);
    00163     // the bar must have CBRS_SIZE_DYNAMIC style
    00164     ASSERT((m_dwStyle & CBRS_SIZE_DYNAMIC) != 0);
    00165
    00166     m_dwDockStyle = dwDockStyle;
    00167     if (m_pDockContext == NULL)
    00168         m_pDockContext = new CSCBDockContext(this);
    00169
    00170     // permanently wire the bar's owner to its current parent
    00171     if (m_hWndOwner == NULL)
    00172         m_hWndOwner = ::GetParent(m_hWnd);
    00173 }
    00174 #endif
    00175
    00177 // CSizingControlBar message handlers
    00178
    00179 int CSizingControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
    00180 {
    00181     if (baseCSizingControlBar::OnCreate(lpCreateStruct) == -1)
    00182         return -1;
    00183
    00184     // query SPI_GETDRAGFULLWINDOWS system parameter
    00185     // OnSettingChange() will update m_bDragShowContent
    00186     m_bDragShowContent = FALSE;
    00187     ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
    00188         &m_bDragShowContent, 0);
    00189
    00190     // uncomment this line if you want raised borders
    00191 //    m_dwSCBStyle |= SCBS_SHOWEDGES;
    00192
    00193     return 0;
    00194 }
    00195
    00196
    00197 LRESULT CSizingControlBar::OnSetText(WPARAM wParam, LPARAM lParam)
    00198 {
    00199     UNUSED_ALWAYS(wParam);
    00200
    00201     LRESULT lResult = CWnd::Default();
    00202
    00203     if (IsFloating() &&
    00204         GetParentFrame()->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)))
    00205     {
    00206         m_pDockBar->SetWindowText((LPCTSTR) lParam); // update dockbar
    00207         GetParentFrame()->DelayRecalcLayout(); // refresh miniframe
    00208     }
    00209
    00210     return lResult;
    00211 }
    00212
    00213 const BOOL CSizingControlBar::IsFloating() const
    00214 {
    00215     return !IsHorzDocked() && !IsVertDocked();
    00216 }
    00217
    00218 const BOOL CSizingControlBar::IsHorzDocked() const
    00219 {
    00220     return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
    00221         m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
    00222 }
    00223
    00224 const BOOL CSizingControlBar::IsVertDocked() const
    00225 {
    00226     return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
    00227         m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
    00228 }
    00229
    00230 const BOOL CSizingControlBar::IsSideTracking() const
    00231 {
    00232     // don't call this when not tracking
    00233     ASSERT(m_bTracking && !IsFloating());
    00234
    00235     return (m_htEdge == HTLEFT || m_htEdge == HTRIGHT) ?
    00236         IsHorzDocked() : IsVertDocked();
    00237 }
    00238
    00239 CSize CSizingControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
    00240 {
    00241     if (bStretch) // the bar is stretched (is not the child of a dockbar)
    00242         if (bHorz)
    00243             return CSize(32767, m_szHorz.cy);
    00244         else
    00245             return CSize(m_szVert.cx, 32767);
    00246
    00247     // dirty cast - we need access to protected CDockBar members
    00248     CSCBDockBar* pDockBar = (CSCBDockBar*) m_pDockBar;
    00249
    00250     // force imediate RecalcDelayShow() for all sizing bars on the row
    00251     // with delayShow/delayHide flags set to avoid IsVisible() problems
    00252     CSCBArray arrSCBars;
    00253     GetRowSizingBars(arrSCBars);
    00254     AFX_SIZEPARENTPARAMS layout;
    00255     layout.hDWP = pDockBar->m_bLayoutQuery ?
    00256         NULL : ::BeginDeferWindowPos(arrSCBars.GetSize());
    00257     for (int i = 0; i < arrSCBars.GetSize(); i++)
    00258         if (arrSCBars[i]->m_nStateFlags & (delayHide|delayShow))
    00259             arrSCBars[i]->RecalcDelayShow(&layout);
    00260     if (layout.hDWP != NULL)
    00261         ::EndDeferWindowPos(layout.hDWP);
    00262
    00263     // get available length
    00264     CRect rc = pDockBar->m_rectLayout;
    00265     if (rc.IsRectEmpty())
    00266         m_pDockSite->GetClientRect(&rc);
    00267     int nLengthTotal = bHorz ? rc.Width() + 2 : rc.Height() - 2;
    00268
    00269     if (IsVisible() && !IsFloating() &&
    00270         m_bParentSizing && arrSCBars[0] == this)
    00271         if (NegotiateSpace(nLengthTotal, (bHorz != FALSE)))
    00272             AlignControlBars();
    00273
    00274     m_bParentSizing = FALSE;
    00275
    00276     if (bHorz)
    00277         return CSize(max(m_szMinHorz.cx, m_szHorz.cx),
    00278                      max(m_szMinHorz.cy, m_szHorz.cy));
    00279
    00280     return CSize(max(m_szMinVert.cx, m_szVert.cx),
    00281                  max(m_szMinVert.cy, m_szVert.cy));
    00282 }
    00283
    00284 CSize CSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
    00285 {
    00286     if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ?
    00287     {
    00288         if (nLength == -1)
    00289             m_bParentSizing = TRUE;
    00290
    00291         return baseCSizingControlBar::CalcDynamicLayout(nLength, dwMode);
    00292     }
    00293
    00294     if (dwMode & LM_MRUWIDTH) return m_szFloat;
    00295     if (dwMode & LM_COMMIT) return m_szFloat; // already committed
    00296
    00297 #ifndef _SCB_REPLACE_MINIFRAME
    00298     // check for dialgonal resizing hit test
    00299     int nHitTest = m_pDockContext->m_nHitTest;
    00300     if (IsFloating() &&
    00301         (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT ||
    00302         nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT))
    00303     {
    00304         CPoint ptCursor;
    00305         ::GetCursorPos(&ptCursor);
    00306
    00307         CRect rFrame, rBar;
    00308         GetParentFrame()->GetWindowRect(&rFrame);
    00309         GetWindowRect(&rBar);
    00310
    00311         if (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT)
    00312         {
    00313             m_szFloat.cx = rFrame.left + rBar.Width() - ptCursor.x;
    00314             m_pDockContext->m_rectFrameDragHorz.left =
    00315                 min(ptCursor.x, rFrame.left + rBar.Width() - m_szMinFloat.cx);
    00316         }
    00317
    00318         if (nHitTest == HTTOPLEFT || nHitTest == HTTOPRIGHT)
    00319         {
    00320             m_szFloat.cy = rFrame.top + rBar.Height() - ptCursor.y;
    00321             m_pDockContext->m_rectFrameDragHorz.top =
    00322                 min(ptCursor.y, rFrame.top + rBar.Height() - m_szMinFloat.cy);
    00323         }
    00324
    00325         if (nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT)
    00326             m_szFloat.cx = rBar.Width() + ptCursor.x - rFrame.right;
    00327
    00328         if (nHitTest == HTBOTTOMLEFT || nHitTest == HTBOTTOMRIGHT)
    00329             m_szFloat.cy = rBar.Height() + ptCursor.y - rFrame.bottom;
    00330     }
    00331     else
    00332 #endif //_SCB_REPLACE_MINIFRAME
    00333         ((dwMode & LM_LENGTHY) ? m_szFloat.cy : m_szFloat.cx) = nLength;
    00334
    00335     m_szFloat.cx = max(m_szFloat.cx, m_szMinFloat.cx);
    00336     m_szFloat.cy = max(m_szFloat.cy, m_szMinFloat.cy);
    00337
    00338     return m_szFloat;
    00339 }
    00340
    00341 void CSizingControlBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
    00342 {
    00343     // force non-client recalc if moved or resized
    00344     lpwndpos->flags |= SWP_FRAMECHANGED;
    00345
    00346     baseCSizingControlBar::OnWindowPosChanging(lpwndpos);
    00347
    00348     // find on which side are we docked
    00349     m_nDockBarID = GetParent()->GetDlgCtrlID();
    00350
    00351     if (!IsFloating())
    00352         if (lpwndpos->flags & SWP_SHOWWINDOW)
    00353             m_bKeepSize = TRUE;
    00354 }
    00355
    00357 // Mouse Handling
    00358 //
    00359 void CSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point)
    00360 {
    00361     if (m_pDockBar != NULL)
    00362     {
    00363         // start the drag
    00364         ASSERT(m_pDockContext != NULL);
    00365         ClientToScreen(&point);
    00366         m_pDockContext->StartDrag(point);
    00367     }
    00368     else
    00369         CWnd::OnLButtonDown(nFlags, point);
    00370 }
    00371
    00372 void CSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point)
    00373 {
    00374     if (m_pDockBar != NULL)
    00375     {
    00376         // toggle docking
    00377         ASSERT(m_pDockContext != NULL);
    00378         m_pDockContext->ToggleDocking();
    00379     }
    00380     else
    00381         CWnd::OnLButtonDblClk(nFlags, point);
    00382 }
    00383
    00384 void CSizingControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point)
    00385 {
    00386     UNUSED_ALWAYS(point);
    00387
    00388     if (m_bTracking || IsFloating())
    00389         return;
    00390
    00391     if ((nHitTest >= HTSIZEFIRST) && (nHitTest <= HTSIZELAST))
    00392         StartTracking(nHitTest, point); // sizing edge hit
    00393 }
    00394
    00395 void CSizingControlBar::OnLButtonUp(UINT nFlags, CPoint point)
    00396 {
    00397     if (m_bTracking)
    00398         StopTracking();
    00399
    00400     baseCSizingControlBar::OnLButtonUp(nFlags, point);
    00401 }
    00402
    00403 void CSizingControlBar::OnRButtonDown(UINT nFlags, CPoint point)
    00404 {
    00405     if (m_bTracking)
    00406         StopTracking();
    00407
    00408     baseCSizingControlBar::OnRButtonDown(nFlags, point);
    00409 }
    00410
    00411 void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point)
    00412 {
    00413     if (m_bTracking)
    00414     {
    00415         CPoint ptScreen = point;
    00416         ClientToScreen(&ptScreen);
    00417
    00418         OnTrackUpdateSize(ptScreen);
    00419     }
    00420
    00421     baseCSizingControlBar::OnMouseMove(nFlags, point);
    00422 }
    00423
    00424 void CSizingControlBar::OnCaptureChanged(CWnd *pWnd)
    00425 {
    00426     if (m_bTracking && (pWnd != this))
    00427         StopTracking();
    00428
    00429     baseCSizingControlBar::OnCaptureChanged(pWnd);
    00430 }
    00431
    00432 void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects,
    00433                                      NCCALCSIZE_PARAMS FAR* lpncsp)
    00434 {
    00435     UNUSED_ALWAYS(bCalcValidRects);
    00436
    00437 #ifndef _SCB_REPLACE_MINIFRAME
    00438     // Enable diagonal resizing for floating miniframe
    00439     if (IsFloating())
    00440     {
    00441         CFrameWnd* pFrame = GetParentFrame();
    00442         if (pFrame != NULL &&
    00443             pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)))
    00444         {
    00445             DWORD dwStyle = ::GetWindowLong(pFrame->m_hWnd, GWL_STYLE);
    00446             if ((dwStyle & MFS_4THICKFRAME) != 0)
    00447             {
    00448                 pFrame->ModifyStyle(MFS_4THICKFRAME, 0); // clear
    00449                 GetParent()->ModifyStyle(0, WS_CLIPCHILDREN);
    00450             }
    00451         }
    00452     }
    00453 #endif _SCB_REPLACE_MINIFRAME
    00454
    00455     // compute the the client area
    00456     m_dwSCBStyle &= ~SCBS_EDGEALL;
    00457
    00458     // add resizing edges between bars on the same row
    00459     if (!IsFloating() && m_pDockBar != NULL)
    00460     {
    00461         CSCBArray arrSCBars;
    00462         int nThis;
    00463         GetRowSizingBars(arrSCBars, nThis);
    00464
    00465         BOOL bHorz = IsHorzDocked();
    00466         if (nThis > 0)
    00467             m_dwSCBStyle |= bHorz ? SCBS_EDGELEFT : SCBS_EDGETOP;
    00468
    00469         if (nThis < arrSCBars.GetUpperBound())
    00470             m_dwSCBStyle |= bHorz ? SCBS_EDGERIGHT : SCBS_EDGEBOTTOM;
    00471     }
    00472
    00473     NcCalcClient(&lpncsp->rgrc[0], m_nDockBarID);
    00474 }
    00475
    00476 void CSizingControlBar::NcCalcClient(LPRECT pRc, UINT nDockBarID)
    00477 {
    00478     CRect rc(pRc);
    00479
    00480     rc.DeflateRect(3, 5, 3, 3);
    00481     if (nDockBarID != AFX_IDW_DOCKBAR_FLOAT)
    00482         rc.DeflateRect(2, 0, 2, 2);
    00483
    00484     switch(nDockBarID)
    00485     {
    00486     case AFX_IDW_DOCKBAR_TOP:
    00487         m_dwSCBStyle |= SCBS_EDGEBOTTOM;
    00488         break;
    00489     case AFX_IDW_DOCKBAR_BOTTOM:
    00490         m_dwSCBStyle |= SCBS_EDGETOP;
    00491         break;
    00492     case AFX_IDW_DOCKBAR_LEFT:
    00493         m_dwSCBStyle |= SCBS_EDGERIGHT;
    00494         break;
    00495     case AFX_IDW_DOCKBAR_RIGHT:
    00496         m_dwSCBStyle |= SCBS_EDGELEFT;
    00497         break;
    00498     }
    00499
    00500     // make room for edges only if they will be painted
    00501     if (m_dwSCBStyle & SCBS_SHOWEDGES)
    00502         rc.DeflateRect(
    00503             (m_dwSCBStyle & SCBS_EDGELEFT) ? m_cxEdge : 0,
    00504             (m_dwSCBStyle & SCBS_EDGETOP) ? m_cxEdge : 0,
    00505             (m_dwSCBStyle & SCBS_EDGERIGHT) ? m_cxEdge : 0,
    00506             (m_dwSCBStyle & SCBS_EDGEBOTTOM) ? m_cxEdge : 0);
    00507
    00508     *pRc = rc;
    00509 }
    00510
    00511 void CSizingControlBar::OnNcPaint()
    00512 {
    00513     // get window DC that is clipped to the non-client area
    00514     CWindowDC dc(this);
    00515
    00516     CRect rcClient, rcBar;
    00517     GetClientRect(rcClient);
    00518     ClientToScreen(rcClient);
    00519     GetWindowRect(rcBar);
    00520     rcClient.OffsetRect(-rcBar.TopLeft());
    00521     rcBar.OffsetRect(-rcBar.TopLeft());
    00522
    00523     CDC mdc;
    00524     mdc.CreateCompatibleDC(&dc);
    00525
    00526     CBitmap bm;
    00527     bm.CreateCompatibleBitmap(&dc, rcBar.Width(), rcBar.Height());
    00528     CBitmap* pOldBm = mdc.SelectObject(&bm);
    00529
    00530     // draw borders in non-client area
    00531     CRect rcDraw = rcBar;
    00532     DrawBorders(&mdc, rcDraw);
    00533
    00534     // erase the NC background
    00535     mdc.FillRect(rcDraw, CBrush::FromHandle(
    00536         (HBRUSH) GetClassLong(m_hWnd, GCL_HBRBACKGROUND)));
    00537
    00538     if (m_dwSCBStyle & SCBS_SHOWEDGES)
    00539     {
    00540         CRect rcEdge; // paint the sizing edges
    00541         for (int i = 0; i < 4; i++)
    00542             if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
    00543                 mdc.Draw3dRect(rcEdge, ::GetSysColor(COLOR_BTNHIGHLIGHT),
    00544                     ::GetSysColor(COLOR_BTNSHADOW));
    00545     }
    00546
    00547     NcPaintGripper(&mdc, rcClient);
    00548
    00549     // client area is not our bussiness :)
    00550     dc.IntersectClipRect(rcBar);
    00551     dc.ExcludeClipRect(rcClient);
    00552
    00553     dc.BitBlt(0, 0, rcBar.Width(), rcBar.Height(), &mdc, 0, 0, SRCCOPY);
    00554
    00555     ReleaseDC(&dc);
    00556
    00557     mdc.SelectObject(pOldBm);
    00558     bm.DeleteObject();
    00559     mdc.DeleteDC();
    00560 }
    00561
    00562 void CSizingControlBar::NcPaintGripper(CDC* pDC, CRect rcClient)
    00563 {
    00564     UNUSED_ALWAYS(pDC);
    00565     UNUSED_ALWAYS(rcClient);
    00566 }
    00567
    00568 void CSizingControlBar::OnPaint()
    00569 {
    00570     // overridden to skip border painting based on clientrect
    00571     CPaintDC dc(this);
    00572 }
    00573
    00574 LRESULT CSizingControlBar::OnNcHitTest(CPoint point)
    00575 {
    00576     CRect rcBar, rcEdge;
    00577     GetWindowRect(rcBar);
    00578
    00579     if (!IsFloating())
    00580         for (int i = 0; i < 4; i++)
    00581             if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
    00582                 if (rcEdge.PtInRect(point))
    00583                     return GetEdgeHTCode(i);
    00584
    00585     return HTCLIENT;
    00586 }
    00587
    00588 void CSizingControlBar::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
    00589 {
    00590     baseCSizingControlBar::OnSettingChange(uFlags, lpszSection);
    00591
    00592     m_bDragShowContent = FALSE;
    00593     ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
    00594         &m_bDragShowContent, 0); // update
    00595 }
    00596
    00597 void CSizingControlBar::OnSize(UINT nType, int cx, int cy)
    00598 {
    00599     UNUSED_ALWAYS(nType);
    00600
    00601     if ((m_dwSCBStyle & SCBS_SIZECHILD) != 0)
    00602     {
    00603         // automatic child resizing - only one child is allowed
    00604         CWnd* pWnd = GetWindow(GW_CHILD);
    00605         if (pWnd != NULL)
    00606         {
    00607             pWnd->MoveWindow(0, 0, cx, cy);
    00608             ASSERT(pWnd->GetWindow(GW_HWNDNEXT) == NULL);
    00609         }
    00610     }
    00611 }
    00612
    00613 void CSizingControlBar::OnClose()
    00614 {
    00615     // do nothing: protection against accidentally destruction by the
    00616     //   child control (i.e. if user hits Esc in a child editctrl)
    00617 }
    00618
    00620 // CSizingControlBar implementation helpers
    00621
    00622 void CSizingControlBar::StartTracking(UINT nHitTest, CPoint point)
    00623 {
    00624     SetCapture();
    00625
    00626     // make sure no updates are pending
    00627     if (!m_bDragShowContent)
    00628         RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
    00629
    00630     m_htEdge = nHitTest;
    00631     m_bTracking = TRUE;
    00632
    00633     BOOL bHorz = IsHorzDocked();
    00634     BOOL bHorzTracking = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
    00635
    00636     m_nTrackPosOld = bHorzTracking ? point.x : point.y;
    00637
    00638     CRect rcBar, rcEdge;
    00639     GetWindowRect(rcBar);
    00640     GetEdgeRect(rcBar, m_htEdge, rcEdge);
    00641     m_nTrackEdgeOfs = m_nTrackPosOld -
    00642         (bHorzTracking ? rcEdge.CenterPoint().x : rcEdge.CenterPoint().y);
    00643
    00644     CSCBArray arrSCBars;
    00645     int nThis;
    00646     GetRowSizingBars(arrSCBars, nThis);
    00647
    00648     m_nTrackPosMin = m_nTrackPosMax = m_nTrackPosOld;
    00649     if (!IsSideTracking())
    00650     {
    00651         // calc minwidth as the max minwidth of the sizing bars on row
    00652         int nMinWidth = bHorz ? m_szMinHorz.cy : m_szMinVert.cx;
    00653         for (int i = 0; i < arrSCBars.GetSize(); i++)
    00654             nMinWidth = max(nMinWidth, bHorz ?
    00655                 arrSCBars[i]->m_szMinHorz.cy :
    00656                 arrSCBars[i]->m_szMinVert.cx);
    00657         int nExcessWidth = (bHorz ? m_szHorz.cy : m_szVert.cx) - nMinWidth;
    00658
    00659         // the control bar cannot grow with more than the width of
    00660         // remaining client area of the mainframe
    00661         CRect rcT;
    00662         m_pDockSite->RepositionBars(0, 0xFFFF, AFX_IDW_PANE_FIRST,
    00663             reposQuery, &rcT, NULL, TRUE);
    00664         int nMaxWidth = bHorz ? rcT.Height() - 2 : rcT.Width() - 2;
    00665
    00666         BOOL bTopOrLeft = m_htEdge == HTTOP || m_htEdge == HTLEFT;
    00667
    00668         m_nTrackPosMin -= bTopOrLeft ? nMaxWidth : nExcessWidth;
    00669         m_nTrackPosMax += bTopOrLeft ? nExcessWidth : nMaxWidth;
    00670     }
    00671     else
    00672     {
    00673         // side tracking:
    00674         // max size is the actual size plus the amount the other
    00675         // sizing bars can be decreased until they reach their minsize
    00676         if (m_htEdge == HTBOTTOM || m_htEdge == HTRIGHT)
    00677             nThis++;
    00678
    00679         for (int i = 0; i < arrSCBars.GetSize(); i++)
    00680         {
    00681             CSizingControlBar* pBar = arrSCBars[i];
    00682
    00683             int nExcessWidth = bHorz ?
    00684                 pBar->m_szHorz.cx - pBar->m_szMinHorz.cx :
    00685                 pBar->m_szVert.cy - pBar->m_szMinVert.cy;
    00686
    00687             if (i < nThis)
    00688                 m_nTrackPosMin -= nExcessWidth;
    00689             else
    00690                 m_nTrackPosMax += nExcessWidth;
    00691         }
    00692     }
    00693
    00694     OnTrackInvertTracker(); // draw tracker
    00695 }
    00696
    00697 void CSizingControlBar::StopTracking()
    00698 {
    00699     OnTrackInvertTracker(); // erase tracker
    00700
    00701     m_bTracking = FALSE;
    00702     ReleaseCapture();
    00703
    00704     m_pDockSite->DelayRecalcLayout();
    00705 }
    00706
    00707 void CSizingControlBar::OnTrackUpdateSize(CPoint& point)
    00708 {
    00709     ASSERT(!IsFloating());
    00710
    00711     BOOL bHorzTrack = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
    00712
    00713     int nTrackPos = bHorzTrack ? point.x : point.y;
    00714     nTrackPos = max(m_nTrackPosMin, min(m_nTrackPosMax, nTrackPos));
    00715
    00716     int nDelta = nTrackPos - m_nTrackPosOld;
    00717
    00718     if (nDelta == 0)
    00719         return; // no pos change
    00720
    00721     OnTrackInvertTracker(); // erase tracker
    00722
    00723     m_nTrackPosOld = nTrackPos;
    00724
    00725     BOOL bHorz = IsHorzDocked();
    00726
    00727     CSize sizeNew = bHorz ? m_szHorz : m_szVert;
    00728     switch (m_htEdge)
    00729     {
    00730     case HTLEFT:    sizeNew -= CSize(nDelta, 0); break;
    00731     case HTTOP:     sizeNew -= CSize(0, nDelta); break;
    00732     case HTRIGHT:   sizeNew += CSize(nDelta, 0); break;
    00733     case HTBOTTOM:  sizeNew += CSize(0, nDelta); break;
    00734     }
    00735
    00736     CSCBArray arrSCBars;
    00737     int nThis;
    00738     GetRowSizingBars(arrSCBars, nThis);
    00739
    00740     if (!IsSideTracking())
    00741         for (int i = 0; i < arrSCBars.GetSize(); i++)
    00742         {
    00743             CSizingControlBar* pBar = arrSCBars[i];
    00744             // make same width (or height)
    00745             (bHorz ? pBar->m_szHorz.cy : pBar->m_szVert.cx) =
    00746                 bHorz ? sizeNew.cy : sizeNew.cx;
    00747         }
    00748     else
    00749     {
    00750         int nGrowingBar = nThis;
    00751         BOOL bBefore = m_htEdge == HTTOP || m_htEdge == HTLEFT;
    00752         if (bBefore && nDelta > 0)
    00753             nGrowingBar--;
    00754         if (!bBefore && nDelta < 0)
    00755             nGrowingBar++;
    00756         if (nGrowingBar != nThis)
    00757             bBefore = !bBefore;
    00758
    00759         // nGrowing is growing
    00760         nDelta = abs(nDelta);
    00761         CSizingControlBar* pBar = arrSCBars[nGrowingBar];
    00762         (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) += nDelta;
    00763
    00764         // the others are shrinking
    00765         int nFirst = bBefore ? nGrowingBar - 1 : nGrowingBar + 1;
    00766         int nLimit = bBefore ? -1 : arrSCBars.GetSize();
    00767
    00768         for (int i = nFirst; nDelta != 0 && i != nLimit; i += (bBefore ? -1 : 1))
    00769         {
    00770             CSizingControlBar* pBar = arrSCBars[i];
    00771
    00772             int nDeltaT = min(nDelta,
    00773                 (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -
    00774                 (bHorz ? pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy));
    00775
    00776             (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -= nDeltaT;
    00777             nDelta -= nDeltaT;
    00778         }
    00779     }
    00780
    00781     OnTrackInvertTracker(); // redraw tracker at new pos
    00782
    00783     if (m_bDragShowContent)
    00784         m_pDockSite->DelayRecalcLayout();
    00785 }
    00786
    00787 void CSizingControlBar::OnTrackInvertTracker()
    00788 {
    00789     ASSERT(m_bTracking);
    00790
    00791     if (m_bDragShowContent)
    00792         return; // don't show tracker if DragFullWindows is on
    00793
    00794     BOOL bHorz = IsHorzDocked();
    00795     CRect rc, rcBar, rcDock, rcFrame;
    00796     GetWindowRect(rcBar);
    00797     m_pDockBar->GetWindowRect(rcDock);
    00798     m_pDockSite->GetWindowRect(rcFrame);
    00799     VERIFY(GetEdgeRect(rcBar, m_htEdge, rc));
    00800     if (!IsSideTracking())
    00801         rc = bHorz ?
    00802             CRect(rcDock.left + 1, rc.top, rcDock.right - 1, rc.bottom) :
    00803             CRect(rc.left, rcDock.top + 1, rc.right, rcDock.bottom - 1);
    00804
    00805     BOOL bHorzTracking = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
    00806     int nOfs = m_nTrackPosOld - m_nTrackEdgeOfs;
    00807     nOfs -= bHorzTracking ? rc.CenterPoint().x : rc.CenterPoint().y;
    00808     rc.OffsetRect(bHorzTracking ? nOfs : 0, bHorzTracking ? 0 : nOfs);
    00809     rc.OffsetRect(-rcFrame.TopLeft());
    00810
    00811     CDC *pDC = m_pDockSite->GetDCEx(NULL,
    00812         DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
    00813     CBrush* pBrush = CDC::GetHalftoneBrush();
    00814     CBrush* pBrushOld = pDC->SelectObject(pBrush);
    00815
    00816     pDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
    00817
    00818     pDC->SelectObject(pBrushOld);
    00819     m_pDockSite->ReleaseDC(pDC);
    00820 }
    00821
    00822 BOOL CSizingControlBar::GetEdgeRect(CRect rcWnd, UINT nHitTest,
    00823                                     CRect& rcEdge)
    00824 {
    00825     rcEdge = rcWnd;
    00826     if (m_dwSCBStyle & SCBS_SHOWEDGES)
    00827         rcEdge.DeflateRect(1, 1);
    00828     BOOL bHorz = IsHorzDocked();
    00829
    00830     switch (nHitTest)
    00831     {
    00832     case HTLEFT:
    00833         if (!(m_dwSCBStyle & SCBS_EDGELEFT)) return FALSE;
    00834         rcEdge.right = rcEdge.left + m_cxEdge;
    00835         rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
    00836         break;
    00837     case HTTOP:
    00838         if (!(m_dwSCBStyle & SCBS_EDGETOP)) return FALSE;
    00839         rcEdge.bottom = rcEdge.top + m_cxEdge;
    00840         rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
    00841         break;
    00842     case HTRIGHT:
    00843         if (!(m_dwSCBStyle & SCBS_EDGERIGHT)) return FALSE;
    00844         rcEdge.left = rcEdge.right - m_cxEdge;
    00845         rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
    00846         break;
    00847     case HTBOTTOM:
    00848         if (!(m_dwSCBStyle & SCBS_EDGEBOTTOM)) return FALSE;
    00849         rcEdge.top = rcEdge.bottom - m_cxEdge;
    00850         rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
    00851         break;
    00852     default:
    00853         ASSERT(FALSE); // invalid hit test code
    00854     }
    00855     return TRUE;
    00856 }
    00857
    00858 UINT CSizingControlBar::GetEdgeHTCode(int nEdge)
    00859 {
    00860     if (nEdge == 0) return HTLEFT;
    00861     if (nEdge == 1) return HTTOP;
    00862     if (nEdge == 2) return HTRIGHT;
    00863     if (nEdge == 3) return HTBOTTOM;
    00864     ASSERT(FALSE); // invalid edge code
    00865     return HTNOWHERE;
    00866 }
    00867
    00868 void CSizingControlBar::GetRowInfo(int& nFirst, int& nLast, int& nThis)
    00869 {
    00870     ASSERT_VALID(m_pDockBar); // verify bounds
    00871
    00872     nThis = m_pDockBar->FindBar(this);
    00873     ASSERT(nThis != -1);
    00874
    00875     int i, nBars = m_pDockBar->m_arrBars.GetSize();
    00876
    00877     // find the first and the last bar in row
    00878     for (nFirst = -1, i = nThis - 1; i >= 0 && nFirst == -1; i--)
    00879         if (m_pDockBar->m_arrBars[i] == NULL)
    00880             nFirst = i + 1;
    00881     for (nLast = -1, i = nThis + 1; i < nBars && nLast == -1; i++)
    00882         if (m_pDockBar->m_arrBars[i] == NULL)
    00883             nLast = i - 1;
    00884
    00885     ASSERT((nLast != -1) && (nFirst != -1));
    00886 }
    00887
    00888 void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars)
    00889 {
    00890     int nThis; // dummy
    00891     GetRowSizingBars(arrSCBars, nThis);
    00892 }
    00893
    00894 void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars, int& nThis)
    00895 {
    00896     arrSCBars.RemoveAll();
    00897
    00898     int nFirstT, nLastT, nThisT;
    00899     GetRowInfo(nFirstT, nLastT, nThisT);
    00900
    00901     nThis = -1;
    00902     for (int i = nFirstT; i <= nLastT; i++)
    00903     {
    00904         CSizingControlBar* pBar =
    00905             (CSizingControlBar*) m_pDockBar->m_arrBars[i];
    00906         if (HIWORD(pBar) == 0) continue; // placeholder
    00907         if (!pBar->IsVisible()) continue;
    00908         if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
    00909         {
    00910             if (pBar == this)
    00911                 nThis = arrSCBars.GetSize();
    00912
    00913             arrSCBars.Add(pBar);
    00914         }
    00915     }
    00916 }
    00917
    00918 BOOL CSizingControlBar::NegotiateSpace(int nLengthTotal, BOOL bHorz)
    00919 {
    00920     ASSERT(bHorz == IsHorzDocked());
    00921
    00922     int nFirst, nLast, nThis;
    00923     GetRowInfo(nFirst, nLast, nThis);
    00924
    00925     int nLengthAvail = nLengthTotal;
    00926     int nLengthActual = 0;
    00927     int nLengthMin = 2;
    00928     int nWidthMax = 0;
    00929     CSizingControlBar* pBar;
    00930
    00931     for (int i = nFirst; i <= nLast; i++)
    00932     {
    00933         pBar = (CSizingControlBar*) m_pDockBar->m_arrBars[i];
    00934         if (HIWORD(pBar) == 0) continue; // placeholder
    00935         if (!pBar->IsVisible()) continue;
    00936         BOOL bIsSizingBar =
    00937             pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar));
    00938
    00939         int nLengthBar; // minimum length of the bar
    00940         if (bIsSizingBar)
    00941             nLengthBar = bHorz ? pBar->m_szMinHorz.cx - 2 :
    00942                 pBar->m_szMinVert.cy - 2;
    00943         else
    00944         {
    00945             CRect rcBar;
    00946             pBar->GetWindowRect(&rcBar);
    00947             nLengthBar = bHorz ? rcBar.Width() - 2 : rcBar.Height() - 2;
    00948         }
    00949
    00950         nLengthMin += nLengthBar;
    00951         if (nLengthMin > nLengthTotal)
    00952         {
    00953             // split the row after fixed bar
    00954             if (i < nThis)
    00955             {
    00956                 m_pDockBar->m_arrBars.InsertAt(i + 1,
    00957                     (CControlBar*) NULL);
    00958                 return FALSE;
    00959             }
    00960
    00961             // only this sizebar remains on the row, adjust it to minsize
    00962             if (i == nThis)
    00963             {
    00964                 if (bHorz)
    00965                     m_szHorz.cx = m_szMinHorz.cx;
    00966                 else
    00967                     m_szVert.cy = m_szMinVert.cy;
    00968
    00969                 return TRUE; // the dockbar will split the row for us
    00970             }
    00971
    00972             // we have enough bars - go negotiate with them
    00973             m_pDockBar->m_arrBars.InsertAt(i, (CControlBar*) NULL);
    00974             nLast = i - 1;
    00975             break;
    00976         }
    00977
    00978         if (bIsSizingBar)
    00979         {
    00980             nLengthActual += bHorz ? pBar->m_szHorz.cx - 2 :
    00981                 pBar->m_szVert.cy - 2;
    00982             nWidthMax = max(nWidthMax, bHorz ? pBar->m_szHorz.cy :
    00983                 pBar->m_szVert.cx);
    00984         }
    00985         else
    00986             nLengthAvail -= nLengthBar;
    00987     }
    00988
    00989     CSCBArray arrSCBars;
    00990     GetRowSizingBars(arrSCBars);
    00991     int nNumBars = arrSCBars.GetSize();
    00992     int nDelta = nLengthAvail - nLengthActual;
    00993
    00994     // return faster when there is only one sizing bar per row (this one)
    00995     if (nNumBars == 1)
    00996     {
    00997         ASSERT(arrSCBars[0] == this);
    00998
    00999         if (nDelta == 0)
    01000             return TRUE;
    01001
    01002         m_bKeepSize = FALSE;
    01003         (bHorz ? m_szHorz.cx : m_szVert.cy) += nDelta;
    01004
    01005         return TRUE;
    01006     }
    01007
    01008     // make all the bars the same width
    01009     for (int i = 0; i < nNumBars; i++)
    01010         if (bHorz)
    01011             arrSCBars[i]->m_szHorz.cy = nWidthMax;
    01012         else
    01013             arrSCBars[i]->m_szVert.cx = nWidthMax;
    01014
    01015     // distribute the difference between the bars,
    01016     // but don't shrink them below their minsizes
    01017     while (nDelta != 0)
    01018     {
    01019         int nDeltaOld = nDelta;
    01020         for (int i = 0; i < nNumBars; i++)
    01021         {
    01022             pBar = arrSCBars[i];
    01023             int nLMin = bHorz ?
    01024                 pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy;
    01025             int nL = bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy;
    01026
    01027             if ((nL == nLMin) && (nDelta < 0) || // already at min length
    01028                 pBar->m_bKeepSize) // or wants to keep its size
    01029                 continue;
    01030
    01031             // sign of nDelta
    01032             int nDelta2 = (nDelta == 0) ? 0 : ((nDelta < 0) ? -1 : 1);
    01033
    01034             (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) += nDelta2;
    01035             nDelta -= nDelta2;
    01036             if (nDelta == 0) break;
    01037         }
    01038         // clear m_bKeepSize flags
    01039         if ((nDeltaOld == nDelta) || (nDelta == 0))
    01040             for (int i = 0; i < nNumBars; i++)
    01041                 arrSCBars[i]->m_bKeepSize = FALSE;
    01042     }
    01043
    01044     return TRUE;
    01045 }
    01046
    01047 void CSizingControlBar::AlignControlBars()
    01048 {
    01049     int nFirst, nLast, nThis;
    01050     GetRowInfo(nFirst, nLast, nThis);
    01051
    01052     BOOL bHorz = IsHorzDocked();
    01053     BOOL bNeedRecalc = FALSE;
    01054     int nAlign = bHorz ? -2 : 0;
    01055
    01056     CRect rc, rcDock;
    01057     m_pDockBar->GetWindowRect(&rcDock);
    01058
    01059     for (int i = nFirst; i <= nLast; i++)
    01060     {
    01061         CSizingControlBar* pBar =
    01062             (CSizingControlBar*) m_pDockBar->m_arrBars[i];
    01063         if (HIWORD(pBar) == 0) continue; // placeholder
    01064         if (!pBar->IsVisible()) continue;
    01065
    01066         pBar->GetWindowRect(&rc);
    01067         rc.OffsetRect(-rcDock.TopLeft());
    01068
    01069         if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
    01070             rc = CRect(rc.TopLeft(),
    01071                 bHorz ? pBar->m_szHorz : pBar->m_szVert);
    01072
    01073         if ((bHorz ? rc.left : rc.top) != nAlign)
    01074         {
    01075             if (!bHorz)
    01076                 rc.OffsetRect(0, nAlign - rc.top - 2);
    01077             else if (m_nDockBarID == AFX_IDW_DOCKBAR_TOP)
    01078                 rc.OffsetRect(nAlign - rc.left, -2);
    01079             else
    01080                 rc.OffsetRect(nAlign - rc.left, 0);
    01081             pBar->MoveWindow(rc);
    01082             bNeedRecalc = TRUE;
    01083         }
    01084         nAlign += (bHorz ? rc.Width() : rc.Height()) - 2;
    01085     }
    01086
    01087     if (bNeedRecalc)
    01088         m_pDockSite->DelayRecalcLayout();
    01089 }
    01090
    01091 void CSizingControlBar::OnUpdateCmdUI(CFrameWnd* pTarget,
    01092                                       BOOL bDisableIfNoHndler)
    01093 {
    01094     UNUSED_ALWAYS(bDisableIfNoHndler);
    01095     UNUSED_ALWAYS(pTarget);
    01096 }
    01097
    01098 void CSizingControlBar::LoadState(LPCTSTR lpszProfileName)
    01099 {
    01100     ASSERT_VALID(this);
    01101     ASSERT(GetSafeHwnd()); // must be called after Create()
    01102
    01103 #if defined(_SCB_REPLACE_MINIFRAME) && !defined(_SCB_MINIFRAME_CAPTION)
    01104     // compensate the caption miscalculation in CFrameWnd::SetDockState()
    01105     CDockState state;
    01106     state.LoadState(lpszProfileName);
    01107
    01108     UINT nID = GetDlgCtrlID();
    01109     for (int i = 0; i < state.m_arrBarInfo.GetSize(); i++)
    01110     {
    01111         CControlBarInfo* pInfo = (CControlBarInfo*)state.m_arrBarInfo[i];
    01112         ASSERT(pInfo != NULL);
    01113         if (!pInfo->m_bFloating)
    01114             continue;
    01115
    01116         // this is a floating dockbar - check the ID array
    01117         for (int j = 0; j < pInfo->m_arrBarID.GetSize(); j++)
    01118             if ((DWORD) pInfo->m_arrBarID[j] == nID)
    01119             {
    01120                 // found this bar - offset origin and save settings
    01121                 pInfo->m_pointPos.x++;
    01122                 pInfo->m_pointPos.y +=
    01123                     ::GetSystemMetrics(SM_CYSMCAPTION) + 1;
    01124                 pInfo->SaveState(lpszProfileName, i);
    01125             }
    01126     }
    01127 #endif //_SCB_REPLACE_MINIFRAME && !_SCB_MINIFRAME_CAPTION
    01128
    01129     CWinApp* pApp = AfxGetApp();
    01130
    01131     TCHAR szSection[256];
    01132     wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
    01133         GetDlgCtrlID());
    01134
    01135     m_szHorz.cx = max(m_szMinHorz.cx, (int) pApp->GetProfileInt(
    01136         szSection, _T("sizeHorzCX"), m_szHorz.cx));
    01137     m_szHorz.cy = max(m_szMinHorz.cy, (int) pApp->GetProfileInt(
    01138         szSection, _T("sizeHorzCY"), m_szHorz.cy));
    01139
    01140     m_szVert.cx = max(m_szMinVert.cx, (int) pApp->GetProfileInt(
    01141         szSection, _T("sizeVertCX"), m_szVert.cx));
    01142     m_szVert.cy = max(m_szMinVert.cy, (int) pApp->GetProfileInt(
    01143         szSection, _T("sizeVertCY"), m_szVert.cy));
    01144
    01145     m_szFloat.cx = max(m_szMinFloat.cx, (int) pApp->GetProfileInt(
    01146         szSection, _T("sizeFloatCX"), m_szFloat.cx));
    01147     m_szFloat.cy = max(m_szMinFloat.cy, (int) pApp->GetProfileInt(
    01148         szSection, _T("sizeFloatCY"), m_szFloat.cy));
    01149 }
    01150
    01151 void CSizingControlBar::SaveState(LPCTSTR lpszProfileName)
    01152 {
    01153     // place your SaveState or GlobalSaveState call in
    01154     // CMainFrame's OnClose() or DestroyWindow(), not in OnDestroy()
    01155     ASSERT_VALID(this);
    01156     ASSERT(GetSafeHwnd());
    01157
    01158     CWinApp* pApp = AfxGetApp();
    01159
    01160     TCHAR szSection[256];
    01161     wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
    01162         GetDlgCtrlID());
    01163
    01164     pApp->WriteProfileInt(szSection, _T("sizeHorzCX"), m_szHorz.cx);
    01165     pApp->WriteProfileInt(szSection, _T("sizeHorzCY"), m_szHorz.cy);
    01166
    01167     pApp->WriteProfileInt(szSection, _T("sizeVertCX"), m_szVert.cx);
    01168     pApp->WriteProfileInt(szSection, _T("sizeVertCY"), m_szVert.cy);
    01169
    01170     pApp->WriteProfileInt(szSection, _T("sizeFloatCX"), m_szFloat.cx);
    01171     pApp->WriteProfileInt(szSection, _T("sizeFloatCY"), m_szFloat.cy);
    01172 }
    01173
    01174 void CSizingControlBar::GlobalLoadState(CFrameWnd* pFrame,
    01175                                         LPCTSTR lpszProfileName)
    01176 {
    01177     POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
    01178     while (pos != NULL)
    01179     {
    01180         CSizingControlBar* pBar =
    01181             (CSizingControlBar*) pFrame->m_listControlBars.GetNext(pos);
    01182         ASSERT(pBar != NULL);
    01183         if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
    01184             pBar->LoadState(lpszProfileName);
    01185     }
    01186 }
    01187
    01188 void CSizingControlBar::GlobalSaveState(CFrameWnd* pFrame,
    01189                                         LPCTSTR lpszProfileName)
    01190 {
    01191     POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
    01192     while (pos != NULL)
    01193     {
    01194         CSizingControlBar* pBar =
    01195             (CSizingControlBar*) pFrame->m_listControlBars.GetNext(pos);
    01196         ASSERT(pBar != NULL);
    01197         if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
    01198             pBar->SaveState(lpszProfileName);
    01199     }
    01200 }
    01201
    01202 #ifdef _SCB_REPLACE_MINIFRAME
    01203 #ifndef _SCB_MINIFRAME_CAPTION
    01204
    01205 // CSCBDockContext Drag Operations
    01206
    01207 static void AdjustRectangle(CRect& rect, CPoint pt)
    01208 {
    01209     int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) :
    01210                     (pt.x > rect.right) ? (pt.x - rect.right) : 0;
    01211     int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) :
    01212                     (pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0;
    01213     rect.OffsetRect(nXOffset, nYOffset);
    01214 }
    01215
    01216 void CSCBDockContext::StartDrag(CPoint pt)
    01217 {
    01218     ASSERT_VALID(m_pBar);
    01219     m_bDragging = TRUE;
    01220
    01221     InitLoop();
    01222
    01223     ASSERT((m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) != 0);
    01224
    01225     // get true bar size (including borders)
    01226     CRect rect;
    01227     m_pBar->GetWindowRect(rect);
    01228     m_ptLast = pt;
    01229     CSize sizeHorz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK);
    01230     CSize sizeVert = m_pBar->CalcDynamicLayout(0, LM_VERTDOCK);
    01231     CSize sizeFloat = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
    01232
    01233     m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
    01234     m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
    01235
    01236     // calculate frame dragging rectangle
    01237     m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat);
    01238
    01239 #ifdef _MAC
    01240     CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz,
    01241         WS_THICKFRAME, WS_EX_FORCESIZEBOX);
    01242 #else
    01243     CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz, WS_THICKFRAME);
    01244 #endif
    01245     m_rectFrameDragHorz.DeflateRect(2, 2);
    01246     m_rectFrameDragVert = m_rectFrameDragHorz;
    01247
    01248     // adjust rectangles so that point is inside
    01249     AdjustRectangle(m_rectDragHorz, pt);
    01250     AdjustRectangle(m_rectDragVert, pt);
    01251     AdjustRectangle(m_rectFrameDragHorz, pt);
    01252     AdjustRectangle(m_rectFrameDragVert, pt);
    01253
    01254     // initialize tracking state and enter tracking loop
    01255     m_dwOverDockStyle = CanDock();
    01256     Move(pt);   // call it here to handle special keys
    01257     Track();
    01258 }
    01259 #endif //_SCB_MINIFRAME_CAPTION
    01260
    01262 // CSCBMiniDockFrameWnd
    01263
    01264 IMPLEMENT_DYNCREATE(CSCBMiniDockFrameWnd, baseCSCBMiniDockFrameWnd);
    01265
    01266 BEGIN_MESSAGE_MAP(CSCBMiniDockFrameWnd, baseCSCBMiniDockFrameWnd)
    01267     //{{AFX_MSG_MAP(CSCBMiniDockFrameWnd)
    01268     ON_WM_NCLBUTTONDOWN()
    01269     ON_WM_GETMINMAXINFO()
    01270     ON_WM_WINDOWPOSCHANGING()
    01271     ON_WM_SIZE()
    01272     //}}AFX_MSG_MAP
    01273 END_MESSAGE_MAP()
    01274
    01275 BOOL CSCBMiniDockFrameWnd::Create(CWnd* pParent, DWORD dwBarStyle)
    01276 {
    01277     // set m_bInRecalcLayout to avoid flashing during creation
    01278     // RecalcLayout will be called once something is docked
    01279     m_bInRecalcLayout = TRUE;
    01280
    01281     DWORD dwStyle = WS_POPUP|WS_CAPTION|WS_SYSMENU|MFS_MOVEFRAME|
    01282         MFS_4THICKFRAME|MFS_SYNCACTIVE|MFS_BLOCKSYSMENU|
    01283         FWS_SNAPTOBARS;
    01284
    01285     if (dwBarStyle & CBRS_SIZE_DYNAMIC)
    01286         dwStyle &= ~MFS_MOVEFRAME;
    01287
    01288     DWORD dwExStyle = 0;
    01289 #ifdef _MAC
    01290     if (dwBarStyle & CBRS_SIZE_DYNAMIC)
    01291         dwExStyle |= WS_EX_FORCESIZEBOX;
    01292     else
    01293         dwStyle &= ~(MFS_MOVEFRAME|MFS_4THICKFRAME);
    01294 #endif
    01295
    01296     if (!CMiniFrameWnd::CreateEx(dwExStyle,
    01297         NULL, &afxChNil, dwStyle, rectDefault, pParent))
    01298     {
    01299         m_bInRecalcLayout = FALSE;
    01300         return FALSE;
    01301     }
    01302     dwStyle = dwBarStyle & (CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT) ?
    01303         CBRS_ALIGN_LEFT : CBRS_ALIGN_TOP;
    01304     dwStyle |= dwBarStyle & CBRS_FLOAT_MULTI;
    01305     CMenu* pSysMenu = GetSystemMenu(FALSE);
    01306     //pSysMenu->DeleteMenu(SC_SIZE, MF_BYCOMMAND);
    01307     CString strHide;
    01308     if (strHide.LoadString(AFX_IDS_HIDE))
    01309     {
    01310         pSysMenu->DeleteMenu(SC_CLOSE, MF_BYCOMMAND);
    01311         pSysMenu->AppendMenu(MF_STRING|MF_ENABLED, SC_CLOSE, strHide);
    01312     }
    01313
    01314     // must initially create with parent frame as parent
    01315     if (!m_wndDockBar.Create(pParent, WS_CHILD | WS_VISIBLE | dwStyle,
    01316         AFX_IDW_DOCKBAR_FLOAT))
    01317     {
    01318         m_bInRecalcLayout = FALSE;
    01319         return FALSE;
    01320     }
    01321
    01322     // set parent to CMiniDockFrameWnd
    01323     m_wndDockBar.SetParent(this);
    01324     m_bInRecalcLayout = FALSE;
    01325
    01326     return TRUE;
    01327 }
    01328
    01329 void CSCBMiniDockFrameWnd::OnNcLButtonDown(UINT nHitTest, CPoint point)
    01330 {
    01331     if (nHitTest == HTCAPTION || nHitTest == HTCLOSE)
    01332     {
    01333         baseCSCBMiniDockFrameWnd::OnNcLButtonDown(nHitTest, point);
    01334         return;
    01335     }
    01336
    01337     if (GetSizingControlBar() != NULL)
    01338         CMiniFrameWnd::OnNcLButtonDown(nHitTest, point);
    01339     else
    01340         baseCSCBMiniDockFrameWnd::OnNcLButtonDown(nHitTest, point);
    01341 }
    01342
    01343 CSizingControlBar* CSCBMiniDockFrameWnd::GetSizingControlBar()
    01344 {
    01345     CWnd* pWnd = GetWindow(GW_CHILD); // get the dockbar
    01346     if (pWnd == NULL)
    01347         return NULL;
    01348
    01349     pWnd = pWnd->GetWindow(GW_CHILD); // get the controlbar
    01350     if (pWnd == NULL)
    01351         return NULL;
    01352
    01353     if (!pWnd->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
    01354         return NULL;
    01355
    01356     return (CSizingControlBar*) pWnd;
    01357 }
    01358
    01359 void CSCBMiniDockFrameWnd::OnSize(UINT nType, int cx, int cy)
    01360 {
    01361     CSizingControlBar* pBar = GetSizingControlBar();
    01362     if ((pBar != NULL) && (GetStyle() & MFS_4THICKFRAME) == 0
    01363         && pBar->IsVisible())
    01364         pBar->m_szFloat = CSize(cx + 4, cy + 4);
    01365
    01366     baseCSCBMiniDockFrameWnd::OnSize(nType, cx, cy);
    01367 }
    01368
    01369 void CSCBMiniDockFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
    01370 {
    01371     baseCSCBMiniDockFrameWnd::OnGetMinMaxInfo(lpMMI);
    01372
    01373     CSizingControlBar* pBar = GetSizingControlBar();
    01374     if (pBar != NULL)
    01375     {
    01376         CRect r(CPoint(0, 0), pBar->m_szMinFloat - CSize(4, 4));
    01377 #ifndef _SCB_MINIFRAME_CAPTION
    01378         CMiniFrameWnd::CalcBorders(&r, WS_THICKFRAME);
    01379 #else
    01380         CMiniFrameWnd::CalcBorders(&r, WS_THICKFRAME|WS_CAPTION);
    01381 #endif //_SCB_MINIFRAME_CAPTION
    01382         lpMMI->ptMinTrackSize.x = r.Width();
    01383         lpMMI->ptMinTrackSize.y = r.Height();
    01384
    01385                 if(pBar->m_bFixedFloat)
    01386                 {
    01387                         lpMMI->ptMinTrackSize.x = pBar->m_szFixedFloat.cx;
    01388                         lpMMI->ptMinTrackSize.y = pBar->m_szFixedFloat.cy;
    01389                         lpMMI->ptMaxTrackSize.x = pBar->m_szFixedFloat.cx;
    01390                         lpMMI->ptMaxTrackSize.y = pBar->m_szFixedFloat.cy;
    01391                 }
    01392     }
    01393 }
    01394
    01395 void CSCBMiniDockFrameWnd::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
    01396 {
    01397     if ((GetStyle() & MFS_4THICKFRAME) != 0)
    01398     {
    01399         CSizingControlBar* pBar = GetSizingControlBar();
    01400         if (pBar != NULL)
    01401         {
    01402             lpwndpos->flags |= SWP_NOSIZE; // don't size this time
    01403             // prevents flicker
    01404             pBar->m_pDockBar->ModifyStyle(0, WS_CLIPCHILDREN);
    01405             // enable diagonal resizing
    01406             ModifyStyle(MFS_4THICKFRAME, 0);
    01407 #ifndef _SCB_MINIFRAME_CAPTION
    01408             // remove caption
    01409             ModifyStyle(WS_SYSMENU|WS_CAPTION, 0);
    01410 #endif
    01411             DelayRecalcLayout();
    01412             pBar->PostMessage(WM_NCPAINT);
    01413         }
    01414     }
    01415
    01416     CMiniFrameWnd::OnWindowPosChanging(lpwndpos);
    01417 }
    01418
    01419 #endif //_SCB_REPLACE_MINIFRAME