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 // [email protected] 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

Generated on Tue Dec 13 14:47:58 2005 for guliverkli by  doxygen 1.4.5