1
/////////////////////////////////////////////////////////////////////////
2
// Copyright (C) 1998, 1999 by Cristi Posea
5
// Use and distribute freely, except: don't remove my name from the
6
// source or documentation (don't take credit for my work), mark your
7
// changes (don't get me blamed for your possible bugs), don't alter
8
// or remove this notice.
9
// No warrantee of any kind, express or implied, is included with this
10
// software; use at your own risk, responsibility for damages (if any) to
11
// anyone resulting from the use of this software rests entirely with the
14
// This class is intended to be used as a base class. Do not simply add
15
// your code to this file - instead create a new class derived from
16
// CSizingControlBar and put there what you need.
17
// Modify this file only to fix bugs, and don't forget to send me a copy.
19
// Send bug reports, bug fixes, enhancements, requests, flames, etc.,
20
// and I'll try to keep a version up to date. I can be reached at:
23
// More details at MFC Programmer's SourceBook
24
// http://www.codeguru.com/docking/docking_window.shtml or search
25
// www.codeguru.com for my name if the article was moved.
27
/////////////////////////////////////////////////////////////////////////
30
// o Thanks to Harlan R. Seymour (harlans@dundas.com) for his continuous
31
// support during development of this code.
32
// o Thanks to Dundas Software for the opportunity to test this code
33
// on real-life applications.
34
// If you don't know who they are, visit them at www.dundas.com .
35
// Their award winning components and development suites are
37
// o Thanks to Chris Maunder (chrism@dundas.com) who came with the
38
// simplest way to query "Show window content while dragging" system
40
// o Thanks to Zafir Anjum (zafir@codeguru.com) for publishing this
41
// code on his cool site (www.codeguru.com).
42
// o Some ideas for the gripper came from the CToolBarEx flat toolbar
43
// by Joerg Koenig (Joerg.Koenig@rhein-neckar.de). Also he inspired
44
// me on writing this notice:) . Thanks, Joerg!
45
// o Thanks to Jakawan Ratiwanich (jack@alpha.fsec.ucf.edu) and to
46
// Udo Schaefer (Udo.Schaefer@vcase.de) for the dwStyle bug fix under
48
// o And, of course, many thanks to all of you who used this code,
49
// for the invaluable feedback I received.
51
/////////////////////////////////////////////////////////////////////////
54
// sizecbar.cpp : implementation file
63
static char THIS_FILE[] = __FILE__;
66
/////////////////////////////////////////////////////////////////////////
69
CSCBArray CSizingControlBar::m_arrBars; // static member
71
IMPLEMENT_DYNAMIC(CSizingControlBar, baseCSizingControlBar);
73
CSizingControlBar::CSizingControlBar()
75
m_szMin = CSize(33, 32);
76
m_szHorz = CSize(200, 200);
77
m_szVert = CSize(200, 200);
78
m_szFloat = CSize(200, 200);
81
m_bParentSizing = FALSE;
83
m_bDragShowContent = FALSE;
88
CSizingControlBar::~CSizingControlBar()
92
BEGIN_MESSAGE_MAP(CSizingControlBar, baseCSizingControlBar)
93
//{{AFX_MSG_MAP(CSizingControlBar)
98
ON_WM_WINDOWPOSCHANGING()
99
ON_WM_CAPTURECHANGED()
100
ON_WM_SETTINGCHANGE()
103
ON_WM_NCLBUTTONDOWN()
105
ON_WM_LBUTTONDBLCLK()
113
BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
114
CSize sizeDefault, BOOL bHasGripper,
115
UINT nID, DWORD dwStyle)
117
// must have a parent
118
ASSERT_VALID(pParentWnd);
119
// cannot be both fixed and dynamic
120
// (CBRS_SIZE_DYNAMIC is used for resizng when floating)
121
ASSERT (!((dwStyle & CBRS_SIZE_FIXED) &&
122
(dwStyle & CBRS_SIZE_DYNAMIC)));
124
m_dwStyle = dwStyle & CBRS_ALL; // save the control bar styles
126
m_szHorz = sizeDefault; // set the size members
127
m_szVert = sizeDefault;
128
m_szFloat = sizeDefault;
130
m_cyGripper = bHasGripper ? 12 : 0; // set the gripper width
132
// register and create the window - skip CControlBar::Create()
133
CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS,
134
::LoadCursor(NULL, IDC_ARROW),
135
::GetSysColorBrush(COLOR_BTNFACE), 0);
137
dwStyle &= ~CBRS_ALL; // keep only the generic window styles
138
dwStyle |= WS_CLIPCHILDREN; // prevents flashing
139
if (!CWnd::Create(wndclass, lpszWindowName, dwStyle,
140
CRect(0, 0, 0, 0), pParentWnd, nID))
146
/////////////////////////////////////////////////////////////////////////
147
// CSizingControlBar message handlers
149
int CSizingControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
151
if (baseCSizingControlBar::OnCreate(lpCreateStruct) == -1)
154
// querry SPI_GETDRAGFULLWINDOWS system parameter
155
// OnSettingChange() will update m_bDragShowContent
156
m_bDragShowContent = FALSE;
157
::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
158
&m_bDragShowContent, 0);
160
m_arrBars.Add(this); // register
162
// m_dwSCBStyle |= SCBS_SHOWEDGES;
167
BOOL CSizingControlBar::DestroyWindow()
169
int nPos = FindSizingBar(this);
172
m_arrBars.RemoveAt(nPos); // unregister
174
return baseCSizingControlBar::DestroyWindow();
177
const BOOL CSizingControlBar::IsFloating() const
179
return !IsHorzDocked() && !IsVertDocked();
182
const BOOL CSizingControlBar::IsHorzDocked() const
184
return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
185
m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
188
const BOOL CSizingControlBar::IsVertDocked() const
190
return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
191
m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
194
const BOOL CSizingControlBar::IsSideTracking() const
196
// don't call this when not tracking
197
ASSERT(m_bTracking && !IsFloating());
199
return (m_htEdge == HTLEFT || m_htEdge == HTRIGHT) ?
200
IsHorzDocked() : IsVertDocked();
203
CSize CSizingControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
205
if (bStretch) // the bar is stretched (is not the child of a dockbar)
207
return CSize(32767, m_szHorz.cy);
209
return CSize(m_szVert.cx, 32767);
211
// dirty cast - using CSCBDockBar to access protected CDockBar members
212
CSCBDockBar* pDockBar = (CSCBDockBar*) m_pDockBar;
214
// force imediate RecalcDelayShow() for all sizing bars on the row
215
// with delayShow/delayHide flags set to avoid IsVisible() problems
217
GetRowSizingBars(arrSCBars);
218
AFX_SIZEPARENTPARAMS layout;
219
layout.hDWP = pDockBar->m_bLayoutQuery ?
220
NULL : ::BeginDeferWindowPos(arrSCBars.GetSize());
221
for (int i = 0; i < arrSCBars.GetSize(); i++)
222
arrSCBars[i]->RecalcDelayShow(&layout);
223
if (layout.hDWP != NULL)
224
::EndDeferWindowPos(layout.hDWP);
226
// get available length
227
CRect rc = pDockBar->m_rectLayout;
228
if (rc.IsRectEmpty())
229
m_pDockSite->GetClientRect(&rc);
230
int nLengthAvail = bHorz ? rc.Width() + 2 : rc.Height() - 2;
232
if (IsVisible() && !IsFloating() &&
233
m_bParentSizing && arrSCBars[0] == this)
234
if (NegociateSpace(nLengthAvail, (bHorz != FALSE)))
237
m_bParentSizing = FALSE;
239
CSize szRet = bHorz ? m_szHorz : m_szVert;
240
szRet.cx = max(m_szMin.cx, szRet.cx);
241
szRet.cy = max(m_szMin.cy, szRet.cy);
246
CSize CSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
248
if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ?
251
m_bParentSizing = TRUE;
253
return baseCSizingControlBar::CalcDynamicLayout(nLength, dwMode);
256
if (dwMode & LM_MRUWIDTH) return m_szFloat;
257
if (dwMode & LM_COMMIT) return m_szFloat; // already committed
259
((dwMode & LM_LENGTHY) ? m_szFloat.cy : m_szFloat.cx) = nLength;
261
m_szFloat.cx = max(m_szFloat.cx, m_szMin.cx);
262
m_szFloat.cy = max(m_szFloat.cy, m_szMin.cy);
267
void CSizingControlBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
269
// force non-client recalc if moved or resized
270
lpwndpos->flags |= SWP_FRAMECHANGED;
272
baseCSizingControlBar::OnWindowPosChanging(lpwndpos);
274
// find on which side are we docked
275
UINT nOldDockBarID = m_nDockBarID;
276
m_nDockBarID = GetParent()->GetDlgCtrlID();
279
if (lpwndpos->flags & SWP_SHOWWINDOW)
283
/////////////////////////////////////////////////////////////////////////
286
void CSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point)
288
if (m_pDockBar != NULL)
291
ASSERT(m_pDockContext != NULL);
292
ClientToScreen(&point);
293
m_pDockContext->StartDrag(point);
296
CWnd::OnLButtonDown(nFlags, point);
299
void CSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point)
301
if (m_pDockBar != NULL)
304
ASSERT(m_pDockContext != NULL);
305
m_pDockContext->ToggleDocking();
308
CWnd::OnLButtonDblClk(nFlags, point);
311
void CSizingControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point)
315
baseCSizingControlBar::OnNcLButtonDown(nHitTest, point);
319
if (m_bTracking) return;
321
if ((nHitTest >= HTSIZEFIRST) && (nHitTest <= HTSIZELAST))
322
StartTracking(nHitTest); // sizing edge hit
325
void CSizingControlBar::OnNcLButtonUp(UINT nHitTest, CPoint point)
327
if (nHitTest == HTCLOSE)
328
m_pDockSite->ShowControlBar(this, FALSE, FALSE); // hide
330
baseCSizingControlBar::OnNcLButtonUp(nHitTest, point);
333
void CSizingControlBar::OnLButtonUp(UINT nFlags, CPoint point)
338
baseCSizingControlBar::OnLButtonUp(nFlags, point);
341
void CSizingControlBar::OnRButtonDown(UINT nFlags, CPoint point)
346
baseCSizingControlBar::OnRButtonDown(nFlags, point);
349
void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point)
352
OnTrackUpdateSize(point);
354
baseCSizingControlBar::OnMouseMove(nFlags, point);
357
void CSizingControlBar::OnCaptureChanged(CWnd *pWnd)
359
if (m_bTracking && (pWnd != this))
362
baseCSizingControlBar::OnCaptureChanged(pWnd);
365
void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects,
366
NCCALCSIZE_PARAMS FAR* lpncsp)
368
// compute the the client area
369
CRect rcClient = lpncsp->rgrc[0];
370
rcClient.DeflateRect(5, 5);
372
m_dwSCBStyle &= ~SCBS_EDGEALL;
376
case AFX_IDW_DOCKBAR_TOP:
377
m_dwSCBStyle |= SCBS_EDGEBOTTOM;
378
rcClient.DeflateRect(m_cyGripper, 0, 0, 0);
380
case AFX_IDW_DOCKBAR_BOTTOM:
381
m_dwSCBStyle |= SCBS_EDGETOP;
382
rcClient.DeflateRect(m_cyGripper, 0, 0, 0);
384
case AFX_IDW_DOCKBAR_LEFT:
385
m_dwSCBStyle |= SCBS_EDGERIGHT;
386
rcClient.DeflateRect(0, m_cyGripper, 0, 0);
388
case AFX_IDW_DOCKBAR_RIGHT:
389
m_dwSCBStyle |= SCBS_EDGELEFT;
390
rcClient.DeflateRect(0, m_cyGripper, 0, 0);
396
if (!IsFloating() && m_pDockBar != NULL)
399
GetRowSizingBars(arrSCBars);
401
for (int i = 0; i < arrSCBars.GetSize(); i++)
402
if (arrSCBars[i] == this)
405
m_dwSCBStyle |= IsHorzDocked() ?
406
SCBS_EDGELEFT : SCBS_EDGETOP;
407
if (i < arrSCBars.GetSize() - 1)
408
m_dwSCBStyle |= IsHorzDocked() ?
409
SCBS_EDGERIGHT : SCBS_EDGEBOTTOM;
413
// make room for edges only if they will be painted
414
if (m_dwSCBStyle & SCBS_SHOWEDGES)
415
rcClient.DeflateRect(
416
(m_dwSCBStyle & SCBS_EDGELEFT) ? m_cxEdge : 0,
417
(m_dwSCBStyle & SCBS_EDGETOP) ? m_cxEdge : 0,
418
(m_dwSCBStyle & SCBS_EDGERIGHT) ? m_cxEdge : 0,
419
(m_dwSCBStyle & SCBS_EDGEBOTTOM) ? m_cxEdge : 0);
421
// "hide" button positioning
424
ptOrgBtn = CPoint(rcClient.left - m_cyGripper - 1,
427
ptOrgBtn = CPoint(rcClient.right - 11,
428
rcClient.top - m_cyGripper - 1);
430
m_biHide.Move(ptOrgBtn - CRect(lpncsp->rgrc[0]).TopLeft());
432
lpncsp->rgrc[0] = rcClient;
435
void CSizingControlBar::OnNcPaint()
437
// get window DC that is clipped to the non-client area
440
CRect rcClient, rcBar;
441
GetClientRect(rcClient);
442
ClientToScreen(rcClient);
443
GetWindowRect(rcBar);
444
rcClient.OffsetRect(-rcBar.TopLeft());
445
rcBar.OffsetRect(-rcBar.TopLeft());
447
// client area is not our bussiness :)
448
dc.ExcludeClipRect(rcClient);
450
// draw borders in non-client area
451
CRect rcDraw = rcBar;
452
DrawBorders(&dc, rcDraw);
454
// erase parts not drawn
455
dc.IntersectClipRect(rcDraw);
457
// erase NC background the hard way
458
HBRUSH hbr = (HBRUSH)GetClassLong(m_hWnd, GCL_HBRBACKGROUND);
459
::FillRect(dc.m_hDC, rcDraw, hbr);
461
if (m_dwSCBStyle & SCBS_SHOWEDGES)
463
CRect rcEdge; // paint the sizing edges
464
for (int i = 0; i < 4; i++)
465
if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
466
dc.Draw3dRect(rcEdge, ::GetSysColor(COLOR_BTNHIGHLIGHT),
467
::GetSysColor(COLOR_BTNSHADOW));
470
if (m_cyGripper && !IsFloating())
471
NcPaintGripper(&dc, rcClient);
476
void CSizingControlBar::NcPaintGripper(CDC* pDC, CRect rcClient)
478
// paints a simple "two raised lines" gripper
479
// override this if you want a more sophisticated gripper
480
CRect gripper = rcClient;
481
CRect rcbtn = m_biHide.GetRect();
482
BOOL bHorz = IsHorzDocked();
484
gripper.DeflateRect(1, 1);
487
gripper.left -= m_cyGripper;
488
gripper.right = gripper.left + 3;
489
gripper.top = rcbtn.bottom + 3;
493
gripper.top -= m_cyGripper;
494
gripper.bottom = gripper.top + 3;
495
gripper.right = rcbtn.left - 3;
498
pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
499
::GetSysColor(COLOR_BTNSHADOW));
501
gripper.OffsetRect(bHorz ? 3 : 0, bHorz ? 0 : 3);
503
pDC->Draw3dRect(gripper, ::GetSysColor(COLOR_BTNHIGHLIGHT),
504
::GetSysColor(COLOR_BTNSHADOW));
509
void CSizingControlBar::OnPaint()
511
// overridden to skip border painting based on clientrect
515
UINT CSizingControlBar::OnNcHitTest(CPoint point)
518
return baseCSizingControlBar::OnNcHitTest(point);
521
GetWindowRect(rcBar);
523
for (int i = 0; i < 4; i++)
524
if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
525
if (rcEdge.PtInRect(point)) return GetEdgeHTCode(i);
527
CRect rc = m_biHide.GetRect();
528
rc.OffsetRect(rcBar.TopLeft());
529
if (rc.PtInRect(point))
535
void CSizingControlBar::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
537
baseCSizingControlBar::OnSettingChange(uFlags, lpszSection);
539
m_bDragShowContent = FALSE;
540
::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
541
&m_bDragShowContent, 0); // update
544
/////////////////////////////////////////////////////////////////////////
545
// CSizingControlBar implementation helpers
547
void CSizingControlBar::StartTracking(UINT nHitTest)
551
// make sure no updates are pending
552
RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
554
BOOL bHorz = IsHorzDocked();
556
m_szOld = bHorz ? m_szHorz : m_szVert;
561
VERIFY(GetEdgeRect(rc, nHitTest, rcEdge));
562
m_ptOld = rcEdge.CenterPoint();
568
GetRowSizingBars(arrSCBars);
570
// compute the minsize as the max minsize of the sizing bars on row
572
for (int i = 0; i < arrSCBars.GetSize(); i++)
574
m_szMinT.cy = max(m_szMinT.cy, arrSCBars[i]->m_szMin.cy);
576
m_szMinT.cx = max(m_szMinT.cx, arrSCBars[i]->m_szMin.cx);
578
if (!IsSideTracking())
580
// the control bar cannot grow with more than the size of
581
// remaining client area of the mainframe
582
m_pDockSite->RepositionBars(0, 0xFFFF, AFX_IDW_PANE_FIRST,
583
reposQuery, &rc, NULL, TRUE);
584
m_szMaxT = m_szOld + rc.Size() - CSize(4, 4);
588
// side tracking: max size is the actual size plus the amount
589
// the neighbour bar can be decreased to reach its minsize
590
for (int i = 0; i < arrSCBars.GetSize(); i++)
591
if (arrSCBars[i] == this) break;
593
CSizingControlBar* pBar = arrSCBars[i +
594
((m_htEdge == HTTOP || m_htEdge == HTLEFT) ? -1 : 1)];
596
m_szMaxT = m_szOld + (bHorz ? pBar->m_szHorz :
597
pBar->m_szVert) - pBar->m_szMin;
600
OnTrackInvertTracker(); // draw tracker
603
void CSizingControlBar::StopTracking()
605
OnTrackInvertTracker(); // erase tracker
610
m_pDockSite->DelayRecalcLayout();
613
void CSizingControlBar::OnTrackUpdateSize(CPoint& point)
615
ASSERT(!IsFloating());
619
CSize szDelta = pt - m_ptOld;
621
CSize sizeNew = m_szOld;
624
case HTLEFT: sizeNew -= CSize(szDelta.cx, 0); break;
625
case HTTOP: sizeNew -= CSize(0, szDelta.cy); break;
626
case HTRIGHT: sizeNew += CSize(szDelta.cx, 0); break;
627
case HTBOTTOM: sizeNew += CSize(0, szDelta.cy); break;
630
// enforce the limits
631
sizeNew.cx = max(m_szMinT.cx, min(m_szMaxT.cx, sizeNew.cx));
632
sizeNew.cy = max(m_szMinT.cy, min(m_szMaxT.cy, sizeNew.cy));
634
BOOL bHorz = IsHorzDocked();
635
szDelta = sizeNew - (bHorz ? m_szHorz : m_szVert);
637
if (szDelta == CSize(0, 0)) return; // no size change
639
OnTrackInvertTracker(); // erase tracker
641
(bHorz ? m_szHorz : m_szVert) = sizeNew; // save the new size
644
GetRowSizingBars(arrSCBars);
646
for (int i = 0; i < arrSCBars.GetSize(); i++)
647
if (!IsSideTracking())
648
{ // track simultaneously
649
CSizingControlBar* pBar = arrSCBars[i];
650
(bHorz ? pBar->m_szHorz.cy : pBar->m_szVert.cx) =
651
bHorz ? sizeNew.cy : sizeNew.cx;
654
{ // adjust the neighbour's size too
655
if (arrSCBars[i] != this) continue;
657
CSizingControlBar* pBar = arrSCBars[i +
658
((m_htEdge == HTTOP || m_htEdge == HTLEFT) ? -1 : 1)];
660
(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -=
661
bHorz ? szDelta.cx : szDelta.cy;
664
OnTrackInvertTracker(); // redraw tracker at new pos
666
if (m_bDragShowContent)
667
m_pDockSite->DelayRecalcLayout();
670
void CSizingControlBar::OnTrackInvertTracker()
674
if (m_bDragShowContent)
675
return; // don't show tracker if DragFullWindows is on
677
BOOL bHorz = IsHorzDocked();
678
CRect rc, rcBar, rcDock, rcFrame;
679
GetWindowRect(rcBar);
680
m_pDockBar->GetWindowRect(rcDock);
681
m_pDockSite->GetWindowRect(rcFrame);
682
VERIFY(GetEdgeRect(rcBar, m_htEdge, rc));
683
if (!IsSideTracking())
685
CRect(rcDock.left + 1, rc.top, rcDock.right - 1, rc.bottom) :
686
CRect(rc.left, rcDock.top + 1, rc.right, rcDock.bottom - 1);
688
rc.OffsetRect(-rcFrame.TopLeft());
690
CSize sizeNew = bHorz ? m_szHorz : m_szVert;
691
CSize sizeDelta = sizeNew - m_szOld;
692
if (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT && m_htEdge == HTTOP ||
693
m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT && m_htEdge != HTBOTTOM ||
694
m_nDockBarID == AFX_IDW_DOCKBAR_TOP && m_htEdge == HTLEFT ||
695
m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM && m_htEdge != HTRIGHT)
696
sizeDelta = -sizeDelta;
697
rc.OffsetRect(sizeDelta);
699
CDC *pDC = m_pDockSite->GetDCEx(NULL,
700
DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
701
CBrush* pBrush = CDC::GetHalftoneBrush();
702
CBrush* pBrushOld = pDC->SelectObject(pBrush);
704
pDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
706
pDC->SelectObject(pBrushOld);
707
m_pDockSite->ReleaseDC(pDC);
710
BOOL CSizingControlBar::GetEdgeRect(CRect rcWnd, UINT nHitTest,
714
if (m_dwSCBStyle & SCBS_SHOWEDGES)
715
rcEdge.DeflateRect(1, 1);
716
BOOL bHorz = IsHorzDocked();
721
if (!(m_dwSCBStyle & SCBS_EDGELEFT)) return FALSE;
722
rcEdge.right = rcEdge.left + m_cxEdge;
723
rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
726
if (!(m_dwSCBStyle & SCBS_EDGETOP)) return FALSE;
727
rcEdge.bottom = rcEdge.top + m_cxEdge;
728
rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
731
if (!(m_dwSCBStyle & SCBS_EDGERIGHT)) return FALSE;
732
rcEdge.left = rcEdge.right - m_cxEdge;
733
rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
736
if (!(m_dwSCBStyle & SCBS_EDGEBOTTOM)) return FALSE;
737
rcEdge.top = rcEdge.bottom - m_cxEdge;
738
rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
741
ASSERT(FALSE); // invalid hit test code
746
UINT CSizingControlBar::GetEdgeHTCode(int nEdge)
748
if (nEdge == 0) return HTLEFT;
749
if (nEdge == 1) return HTTOP;
750
if (nEdge == 2) return HTRIGHT;
751
if (nEdge == 3) return HTBOTTOM;
752
ASSERT(FALSE); // invalid edge no
756
void CSizingControlBar::GetRowInfo(int& nFirst, int& nLast, int& nThis)
758
ASSERT_VALID(m_pDockBar); // verify bounds
760
nThis = m_pDockBar->FindBar(this);
763
int i, nBars = m_pDockBar->m_arrBars.GetSize();
765
// find the first and the last bar in row
766
for (nFirst = -1, i = nThis - 1; i >= 0 && nFirst == -1; i--)
767
if (m_pDockBar->m_arrBars[i] == NULL)
769
for (nLast = -1, i = nThis + 1; i < nBars && nLast == -1; i++)
770
if (m_pDockBar->m_arrBars[i] == NULL)
773
ASSERT((nLast != -1) && (nFirst != -1));
776
void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars)
778
arrSCBars.RemoveAll();
780
int nFirst, nLast, nThis;
781
GetRowInfo(nFirst, nLast, nThis);
783
for (int i = nFirst; i <= nLast; i++)
785
CControlBar* pBar = (CControlBar*)m_pDockBar->m_arrBars[i];
786
if (HIWORD(pBar) == 0) continue; // placeholder
787
if (!pBar->IsVisible()) continue;
788
if (FindSizingBar(pBar) >= 0)
789
arrSCBars.Add((CSizingControlBar*)pBar);
793
const int CSizingControlBar::FindSizingBar(CControlBar* pBar) const
795
for (int nPos = 0; nPos < m_arrBars.GetSize(); nPos++)
796
if (m_arrBars[nPos] == pBar)
797
return nPos; // got it
799
return -1; // not found
802
BOOL CSizingControlBar::NegociateSpace(int nLengthAvail, BOOL bHorz)
804
ASSERT(bHorz == IsHorzDocked());
806
int nFirst, nLast, nThis;
807
GetRowInfo(nFirst, nLast, nThis);
809
// step 1: subtract the visible fixed bars' lengths
810
for (int i = nFirst; i <= nLast; i++)
812
CControlBar* pFBar = (CControlBar*)m_pDockBar->m_arrBars[i];
813
if (HIWORD(pFBar) == 0) continue; // placeholder
814
if (!pFBar->IsVisible() || (FindSizingBar(pFBar) >= 0)) continue;
817
pFBar->GetWindowRect(&rcBar);
819
nLengthAvail -= (bHorz ? rcBar.Width() - 2 : rcBar.Height() - 2);
823
GetRowSizingBars(arrSCBars);
824
CSizingControlBar* pBar;
826
// step 2: compute actual and min lengths; also the common width
827
int nActualLength = 0;
830
for (i = 0; i < arrSCBars.GetSize(); i++)
833
nActualLength += bHorz ? pBar->m_szHorz.cx - 2 :
834
pBar->m_szVert.cy - 2;
835
nMinLength += bHorz ? pBar->m_szMin.cx - 2:
836
pBar->m_szMin.cy - 2;
837
nWidth = max(nWidth, bHorz ? pBar->m_szHorz.cy :
841
// step 3: pop the bar out of the row if not enough room
842
if (nMinLength > nLengthAvail)
844
if (nFirst < nThis || nThis < nLast)
845
{ // not enough room - create a new row
846
m_pDockBar->m_arrBars.InsertAt(nLast + 1, this);
847
m_pDockBar->m_arrBars.InsertAt(nLast + 1, (CControlBar*) NULL);
848
m_pDockBar->m_arrBars.RemoveAt(nThis);
853
// step 4: make the bars same width
854
for (i = 0; i < arrSCBars.GetSize(); i++)
856
arrSCBars[i]->m_szHorz.cy = nWidth;
858
arrSCBars[i]->m_szVert.cx = nWidth;
860
if (nActualLength == nLengthAvail)
861
return TRUE; // no change
863
// step 5: distribute the difference between the bars, but
864
// don't shrink them below minsize
865
int nDelta = nLengthAvail - nActualLength;
869
int nDeltaOld = nDelta;
870
for (i = 0; i < arrSCBars.GetSize(); i++)
873
int nLMin = bHorz ? pBar->m_szMin.cx : pBar->m_szMin.cy;
874
int nL = bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy;
876
if ((nL == nLMin) && (nDelta < 0) || // already at min length
877
pBar->m_bKeepSize) // or wants to keep its size
881
int nDelta2 = (nDelta == 0) ? 0 : ((nDelta < 0) ? -1 : 1);
883
(bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) += nDelta2;
885
if (nDelta == 0) break;
887
// clear m_bKeepSize flags
888
if ((nDeltaOld == nDelta) || (nDelta == 0))
889
for (i = 0; i < arrSCBars.GetSize(); i++)
890
arrSCBars[i]->m_bKeepSize = FALSE;
896
void CSizingControlBar::AlignControlBars()
898
int nFirst, nLast, nThis;
899
GetRowInfo(nFirst, nLast, nThis);
901
BOOL bHorz = IsHorzDocked();
902
BOOL bNeedRecalc = FALSE;
903
int nPos, nAlign = bHorz ? -2 : 0;
906
m_pDockBar->GetWindowRect(&rcDock);
908
for (int i = nFirst; i <= nLast; i++)
910
CControlBar* pBar = (CControlBar*)m_pDockBar->m_arrBars[i];
911
if (HIWORD(pBar) == 0) continue; // placeholder
912
if (!pBar->IsVisible()) continue;
914
pBar->GetWindowRect(&rc);
915
rc.OffsetRect(-rcDock.TopLeft());
917
if ((nPos = FindSizingBar(pBar)) >= 0)
918
rc = CRect(rc.TopLeft(), bHorz ?
919
m_arrBars[nPos]->m_szHorz : m_arrBars[nPos]->m_szVert);
921
if ((bHorz ? rc.left : rc.top) != nAlign)
924
rc.OffsetRect(0, nAlign - rc.top - 2);
925
else if (m_nDockBarID == AFX_IDW_DOCKBAR_TOP)
926
rc.OffsetRect(nAlign - rc.left, -2);
928
rc.OffsetRect(nAlign - rc.left, 0);
929
pBar->MoveWindow(rc);
932
nAlign += (bHorz ? rc.Width() : rc.Height()) - 2;
937
m_pDockSite->DelayRecalcLayout();
942
void CSizingControlBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
944
BOOL bNeedPaint = FALSE;
948
BOOL bHit = (OnNcHitTest(pt) == HTCLOSE);
949
BOOL bLButtonDown = (::GetKeyState(VK_LBUTTON) < 0);
951
BOOL bWasPushed = m_biHide.bPushed;
952
m_biHide.bPushed = bHit && bLButtonDown;
954
BOOL bWasRaised = m_biHide.bRaised;
955
m_biHide.bRaised = bHit && !bLButtonDown;
957
bNeedPaint |= (m_biHide.bPushed ^ bWasPushed) ||
958
(m_biHide.bRaised ^ bWasRaised);
961
SendMessage(WM_NCPAINT);
964
void CSizingControlBar::LoadState(LPCTSTR lpszProfileName)
967
ASSERT(GetSafeHwnd()); // must be called after Create()
969
CWinApp* pApp = AfxGetApp();
971
TCHAR szSection[256];
972
wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
975
m_szHorz.cx = max(m_szMin.cx, (int) pApp->GetProfileInt(szSection,
976
_T("sizeHorzCX"), m_szHorz.cx));
977
m_szHorz.cy = max(m_szMin.cy, (int) pApp->GetProfileInt(szSection,
978
_T("sizeHorzCY"), m_szHorz.cy));
980
m_szVert.cx = max(m_szMin.cx, (int) pApp->GetProfileInt(szSection,
981
_T("sizeVertCX"), m_szVert.cx));
982
m_szVert.cy = max(m_szMin.cy, (int) pApp->GetProfileInt(szSection,
983
_T("sizeVertCY"), m_szVert.cy));
985
m_szFloat.cx = max(m_szMin.cx, (int) pApp->GetProfileInt(szSection,
986
_T("sizeFloatCX"), m_szFloat.cx));
987
m_szFloat.cy = max(m_szMin.cy, (int) pApp->GetProfileInt(szSection,
988
_T("sizeFloatCY"), m_szFloat.cy));
991
void CSizingControlBar::SaveState(LPCTSTR lpszProfileName)
993
// place your SaveState or GlobalSaveState call in
994
// CMainFrame::DestroyWindow(), not in OnDestroy()
996
ASSERT(GetSafeHwnd());
998
CWinApp* pApp = AfxGetApp();
1000
TCHAR szSection[256];
1001
wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
1004
pApp->WriteProfileInt(szSection, _T("sizeHorzCX"), m_szHorz.cx);
1005
pApp->WriteProfileInt(szSection, _T("sizeHorzCY"), m_szHorz.cy);
1007
pApp->WriteProfileInt(szSection, _T("sizeVertCX"), m_szVert.cx);
1008
pApp->WriteProfileInt(szSection, _T("sizeVertCY"), m_szVert.cy);
1010
pApp->WriteProfileInt(szSection, _T("sizeFloatCX"), m_szFloat.cx);
1011
pApp->WriteProfileInt(szSection, _T("sizeFloatCY"), m_szFloat.cy);
1014
void CSizingControlBar::GlobalLoadState(LPCTSTR lpszProfileName)
1016
for (int i = 0; i < m_arrBars.GetSize(); i++)
1017
((CSizingControlBar*) m_arrBars[i])->LoadState(lpszProfileName);
1020
void CSizingControlBar::GlobalSaveState(LPCTSTR lpszProfileName)
1022
for (int i = 0; i < m_arrBars.GetSize(); i++)
1023
((CSizingControlBar*) m_arrBars[i])->SaveState(lpszProfileName);
1026
/////////////////////////////////////////////////////////////////////////
1029
CSCBButton::CSCBButton()
1035
void CSCBButton::Paint(CDC* pDC)
1037
CRect rc = GetRect();
1040
pDC->Draw3dRect(rc, ::GetSysColor(COLOR_BTNSHADOW),
1041
::GetSysColor(COLOR_BTNHIGHLIGHT));
1044
pDC->Draw3dRect(rc, ::GetSysColor(COLOR_BTNHIGHLIGHT),
1045
::GetSysColor(COLOR_BTNSHADOW));
1047
COLORREF clrOldTextColor = pDC->GetTextColor();
1048
pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
1049
int nPrevBkMode = pDC->SetBkMode(TRANSPARENT);
1051
int ppi = pDC->GetDeviceCaps(LOGPIXELSX);
1052
int pointsize = MulDiv(60, 96, ppi); // 6 points at 96 ppi
1053
font.CreatePointFont(pointsize, _T("Marlett"));
1054
CFont* oldfont = pDC->SelectObject(&font);
1056
pDC->TextOut(ptOrg.x + 2, ptOrg.y + 2, CString(_T("r"))); // x-like
1058
pDC->SelectObject(oldfont);
1059
pDC->SetBkMode(nPrevBkMode);
1060
pDC->SetTextColor(clrOldTextColor);