sizecbar.cpp 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416
  1. /////////////////////////////////////////////////////////////////////////
  2. //
  3. // CSizingControlBar Version 2.43
  4. //
  5. // Created: Jan 24, 1998 Last Modified: August 03, 2000
  6. //
  7. // See the official site at www.datamekanix.com for documentation and
  8. // the latest news.
  9. //
  10. /////////////////////////////////////////////////////////////////////////
  11. // Copyright (C) 1998-2000 by Cristi Posea. All rights reserved.
  12. //
  13. // This code is free for personal and commercial use, providing this
  14. // notice remains intact in the source files and all eventual changes are
  15. // clearly marked with comments.
  16. //
  17. // You must obtain the author's consent before you can include this code
  18. // in a software library.
  19. //
  20. // No warrantee of any kind, express or implied, is included with this
  21. // software; use at your own risk, responsibility for damages (if any) to
  22. // anyone resulting from the use of this software rests entirely with the
  23. // user.
  24. //
  25. // Send bug reports, bug fixes, enhancements, requests, flames, etc. to
  26. // cristi@datamekanix.com or post them at the message board at the site.
  27. //
  28. // The sources and a short version of the docs are also available at
  29. // www.codeproject.com . Look for a "Docking Windows" section and check
  30. // the version to be sure you get the latest one ;)
  31. //
  32. // Hint: These classes are intended to be used as base classes. Do not
  33. // simply add your code to these file - instead create a new class
  34. // derived from one of CSizingControlBarXX classes and put there what
  35. // you need. See CMyBar classes in the demo projects for examples.
  36. // Modify this file only to fix bugs, and don't forget to send me a copy.
  37. /////////////////////////////////////////////////////////////////////////
  38. // Acknowledgements:
  39. // o Thanks to Harlan R. Seymour for his continuous support during
  40. // development of this code.
  41. // o Thanks to Dundas Software for the opportunity
  42. // to test this code on real-life applications.
  43. // o Some ideas for the gripper came from the CToolBarEx flat toolbar
  44. // by Joerg Koenig. Thanks, Joerg!
  45. // o Thanks to Robert Wolpow for the code on which CDockContext based
  46. // dialgonal resizing is based.
  47. // o Thanks to the following people for various bug fixes and/or
  48. // enhancements: Chris Maunder, Jakawan Ratiwanich, Udo Schaefer,
  49. // Anatoly Ivasyuk, Peter Hauptmann.
  50. // o And, of course, many thanks to all of you who used this code,
  51. // for the invaluable feedback I received.
  52. /////////////////////////////////////////////////////////////////////////
  53. // sizecbar.cpp : implementation file
  54. //
  55. #include "stdafx.h"
  56. #include "sizecbar.h"
  57. #ifdef _DEBUG
  58. #define new DEBUG_NEW
  59. #undef THIS_FILE
  60. static char THIS_FILE[] = __FILE__;
  61. #endif
  62. /////////////////////////////////////////////////////////////////////////
  63. // CSizingControlBar
  64. IMPLEMENT_DYNAMIC(CSizingControlBar, baseCSizingControlBar);
  65. BOOL CSizingControlBar::m_bTracking=FALSE;
  66. CSizingControlBar::CSizingControlBar()
  67. {
  68. m_szMinHorz = CSize(33, 32);
  69. m_szMinVert = CSize(33, 32);
  70. m_szMinFloat = CSize(37, 32);
  71. m_szHorz = CSize(500, 500);
  72. m_szVert = CSize(200, 200);
  73. m_szFloat = CSize(200, 200);
  74. m_bTracking = FALSE;
  75. m_bKeepSize = FALSE;
  76. m_bParentSizing = FALSE;
  77. m_cxEdge = 5;
  78. m_bDragShowContent = FALSE;
  79. m_nDockBarID = 0;
  80. m_dwSCBStyle = 0;
  81. }
  82. CSizingControlBar::~CSizingControlBar()
  83. {
  84. }
  85. BEGIN_MESSAGE_MAP(CSizingControlBar, baseCSizingControlBar)
  86. //{{AFX_MSG_MAP(CSizingControlBar)
  87. ON_WM_CREATE()
  88. ON_WM_PAINT()
  89. ON_WM_NCPAINT()
  90. ON_WM_NCCALCSIZE()
  91. ON_WM_WINDOWPOSCHANGING()
  92. ON_WM_CAPTURECHANGED()
  93. ON_WM_SETTINGCHANGE()
  94. ON_WM_LBUTTONUP()
  95. ON_WM_MOUSEMOVE()
  96. ON_WM_NCLBUTTONDOWN()
  97. ON_WM_LBUTTONDOWN()
  98. ON_WM_LBUTTONDBLCLK()
  99. ON_WM_RBUTTONDOWN()
  100. ON_WM_NCMOUSEMOVE()
  101. ON_WM_NCHITTEST()
  102. ON_WM_CLOSE()
  103. ON_WM_SIZE()
  104. //}}AFX_MSG_MAP
  105. ON_MESSAGE(WM_SETTEXT, OnSetText)
  106. END_MESSAGE_MAP()
  107. // old creation method, still here for compatibility reasons
  108. BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
  109. CSize sizeDefault, BOOL bHasGripper,
  110. UINT nID, DWORD dwStyle)
  111. {
  112. UNUSED_ALWAYS(bHasGripper);
  113. m_szHorz = m_szVert = m_szFloat = sizeDefault;
  114. return Create(lpszWindowName, pParentWnd, nID, dwStyle);
  115. }
  116. // preffered creation method
  117. BOOL CSizingControlBar::Create(LPCTSTR lpszWindowName,
  118. CWnd* pParentWnd, UINT nID,
  119. DWORD dwStyle)
  120. {
  121. // must have a parent
  122. ASSERT_VALID(pParentWnd);
  123. // cannot be both fixed and dynamic
  124. // (CBRS_SIZE_DYNAMIC is used for resizng when floating)
  125. ASSERT (!((dwStyle & CBRS_SIZE_FIXED) &&
  126. (dwStyle & CBRS_SIZE_DYNAMIC)));
  127. m_dwStyle = dwStyle & CBRS_ALL; // save the control bar styles
  128. // register and create the window - skip CControlBar::Create()
  129. CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS,
  130. ::LoadCursor(NULL, IDC_ARROW),
  131. ::GetSysColorBrush(COLOR_BTNFACE), 0);
  132. dwStyle &= ~CBRS_ALL; // keep only the generic window styles
  133. dwStyle |= WS_CLIPCHILDREN; // prevents flashing
  134. if (!CWnd::Create(wndclass, lpszWindowName, dwStyle,
  135. CRect(0, 0, 0, 0), pParentWnd, nID))
  136. return FALSE;
  137. return TRUE;
  138. }
  139. /////////////////////////////////////////////////////////////////////////
  140. // CSizingControlBar operations
  141. #if defined(_SCB_REPLACE_MINIFRAME) && !defined(_SCB_MINIFRAME_CAPTION)
  142. void CSizingControlBar::EnableDocking(DWORD dwDockStyle)
  143. {
  144. // must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
  145. ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
  146. // cannot have the CBRS_FLOAT_MULTI style
  147. ASSERT((dwDockStyle & CBRS_FLOAT_MULTI) == 0);
  148. // the bar must have CBRS_SIZE_DYNAMIC style
  149. ASSERT((m_dwStyle & CBRS_SIZE_DYNAMIC) != 0);
  150. m_dwDockStyle = dwDockStyle;
  151. if (m_pDockContext == NULL)
  152. m_pDockContext = new CSCBDockContext(this);
  153. // permanently wire the bar's owner to its current parent
  154. if (m_hWndOwner == NULL)
  155. m_hWndOwner = ::GetParent(m_hWnd);
  156. }
  157. #endif
  158. /////////////////////////////////////////////////////////////////////////
  159. // CSizingControlBar message handlers
  160. int CSizingControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
  161. {
  162. if (baseCSizingControlBar::OnCreate(lpCreateStruct) == -1)
  163. return -1;
  164. // query SPI_GETDRAGFULLWINDOWS system parameter
  165. // OnSettingChange() will update m_bDragShowContent
  166. m_bDragShowContent = FALSE;
  167. //Tony to avoid the window flashing
  168. //::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
  169. // &m_bDragShowContent, 0);
  170. // uncomment this line if you want raised borders
  171. // m_dwSCBStyle |= SCBS_SHOWEDGES;
  172. return 0;
  173. }
  174. LRESULT CSizingControlBar::OnSetText(WPARAM wParam, LPARAM lParam)
  175. {
  176. UNUSED_ALWAYS(wParam);
  177. LRESULT lResult = CWnd::Default();
  178. if (IsFloating() &&
  179. GetParentFrame()->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)))
  180. {
  181. m_pDockBar->SetWindowText((LPCTSTR) lParam); // update dockbar
  182. GetParentFrame()->DelayRecalcLayout(); // refresh miniframe
  183. }
  184. return lResult;
  185. }
  186. const BOOL CSizingControlBar::IsFloating() const
  187. {
  188. return !IsHorzDocked() && !IsVertDocked();
  189. }
  190. const BOOL CSizingControlBar::IsHorzDocked() const
  191. {
  192. return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
  193. m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
  194. }
  195. const BOOL CSizingControlBar::IsVertDocked() const
  196. {
  197. return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
  198. m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
  199. }
  200. const BOOL CSizingControlBar::IsSideTracking() const
  201. {
  202. // don't call this when not tracking
  203. ASSERT(m_bTracking && !IsFloating());
  204. return (m_htEdge == HTLEFT || m_htEdge == HTRIGHT) ?
  205. IsHorzDocked() : IsVertDocked();
  206. }
  207. CSize CSizingControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  208. {
  209. if (bStretch) // the bar is stretched (is not the child of a dockbar)
  210. if (bHorz)
  211. return CSize(32767, m_szHorz.cy);
  212. else
  213. return CSize(m_szVert.cx, 32767);
  214. // dirty cast - we need access to protected CDockBar members
  215. CSCBDockBar* pDockBar = (CSCBDockBar*) m_pDockBar;
  216. // force imediate RecalcDelayShow() for all sizing bars on the row
  217. // with delayShow/delayHide flags set to avoid IsVisible() problems
  218. CSCBArray arrSCBars;
  219. GetRowSizingBars(arrSCBars);
  220. AFX_SIZEPARENTPARAMS layout;
  221. layout.hDWP = pDockBar->m_bLayoutQuery ?
  222. NULL : ::BeginDeferWindowPos(arrSCBars.GetSize());
  223. for (int i = 0; i < arrSCBars.GetSize(); i++)
  224. if (arrSCBars[i]->m_nStateFlags & (delayHide|delayShow))
  225. arrSCBars[i]->RecalcDelayShow(&layout);
  226. if (layout.hDWP != NULL)
  227. ::EndDeferWindowPos(layout.hDWP);
  228. // get available length
  229. CRect rc = pDockBar->m_rectLayout;
  230. if (rc.IsRectEmpty())
  231. m_pDockSite->GetClientRect(&rc);
  232. int nLengthTotal = bHorz ? rc.Width() + 2 : rc.Height() - 2;
  233. if (IsVisible() && !IsFloating() &&
  234. m_bParentSizing && arrSCBars[0] == this)
  235. if (NegotiateSpace(nLengthTotal, (bHorz != FALSE)))
  236. AlignControlBars();
  237. m_bParentSizing = FALSE;
  238. if (bHorz)
  239. return CSize(max(m_szMinHorz.cx, m_szHorz.cx),
  240. max(m_szMinHorz.cy, m_szHorz.cy));
  241. return CSize(max(m_szMinVert.cx, m_szVert.cx),
  242. max(m_szMinVert.cy, m_szVert.cy));
  243. }
  244. CSize CSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
  245. {
  246. if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ?
  247. {
  248. if (nLength == -1)
  249. m_bParentSizing = TRUE;
  250. return baseCSizingControlBar::CalcDynamicLayout(nLength, dwMode);
  251. }
  252. if (dwMode & LM_MRUWIDTH) return m_szFloat;
  253. if (dwMode & LM_COMMIT) return m_szFloat; // already committed
  254. #ifndef _SCB_REPLACE_MINIFRAME
  255. // check for dialgonal resizing hit test
  256. int nHitTest = m_pDockContext->m_nHitTest;
  257. if (IsFloating() &&
  258. (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT ||
  259. nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT))
  260. {
  261. CPoint ptCursor;
  262. ::GetCursorPos(&ptCursor);
  263. CRect rFrame, rBar;
  264. GetParentFrame()->GetWindowRect(&rFrame);
  265. GetWindowRect(&rBar);
  266. if (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT)
  267. {
  268. m_szFloat.cx = rFrame.left + rBar.Width() - ptCursor.x;
  269. m_pDockContext->m_rectFrameDragHorz.left =
  270. min(ptCursor.x, rFrame.left + rBar.Width() - m_szMinFloat.cx);
  271. }
  272. if (nHitTest == HTTOPLEFT || nHitTest == HTTOPRIGHT)
  273. {
  274. m_szFloat.cy = rFrame.top + rBar.Height() - ptCursor.y;
  275. m_pDockContext->m_rectFrameDragHorz.top =
  276. min(ptCursor.y, rFrame.top + rBar.Height() - m_szMinFloat.cy);
  277. }
  278. if (nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT)
  279. m_szFloat.cx = rBar.Width() + ptCursor.x - rFrame.right;
  280. if (nHitTest == HTBOTTOMLEFT || nHitTest == HTBOTTOMRIGHT)
  281. m_szFloat.cy = rBar.Height() + ptCursor.y - rFrame.bottom;
  282. }
  283. else
  284. #endif //_SCB_REPLACE_MINIFRAME
  285. ((dwMode & LM_LENGTHY) ? m_szFloat.cy : m_szFloat.cx) = nLength;
  286. m_szFloat.cx = max(m_szFloat.cx, m_szMinFloat.cx);
  287. m_szFloat.cy = max(m_szFloat.cy, m_szMinFloat.cy);
  288. return m_szFloat;
  289. }
  290. void CSizingControlBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
  291. {
  292. // force non-client recalc if moved or resized
  293. lpwndpos->flags |= SWP_FRAMECHANGED;
  294. baseCSizingControlBar::OnWindowPosChanging(lpwndpos);
  295. // find on which side are we docked
  296. m_nDockBarID = GetParent()->GetDlgCtrlID();
  297. if (!IsFloating())
  298. if (lpwndpos->flags & SWP_SHOWWINDOW)
  299. m_bKeepSize = TRUE;
  300. }
  301. /////////////////////////////////////////////////////////////////////////
  302. // Mouse Handling
  303. //
  304. void CSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point)
  305. {
  306. if (m_pDockBar != NULL)
  307. {
  308. // start the drag
  309. ASSERT(m_pDockContext != NULL);
  310. ClientToScreen(&point);
  311. m_pDockContext->StartDrag(point);
  312. }
  313. else
  314. CWnd::OnLButtonDown(nFlags, point);
  315. }
  316. void CSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point)
  317. {
  318. if (m_pDockBar != NULL)
  319. {
  320. // toggle docking
  321. ASSERT(m_pDockContext != NULL);
  322. m_pDockContext->ToggleDocking();
  323. }
  324. else
  325. CWnd::OnLButtonDblClk(nFlags, point);
  326. }
  327. void CSizingControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point)
  328. {
  329. UNUSED_ALWAYS(point);
  330. if (m_bTracking || IsFloating())
  331. return;
  332. if ((nHitTest >= HTSIZEFIRST) && (nHitTest <= HTSIZELAST))
  333. StartTracking(nHitTest, point); // sizing edge hit
  334. }
  335. void CSizingControlBar::OnLButtonUp(UINT nFlags, CPoint point)
  336. {
  337. if (m_bTracking)
  338. StopTracking();
  339. baseCSizingControlBar::OnLButtonUp(nFlags, point);
  340. }
  341. void CSizingControlBar::OnRButtonDown(UINT nFlags, CPoint point)
  342. {
  343. if (m_bTracking)
  344. StopTracking();
  345. baseCSizingControlBar::OnRButtonDown(nFlags, point);
  346. }
  347. void CSizingControlBar::OnMouseMove(UINT nFlags, CPoint point)
  348. {
  349. if (m_bTracking)
  350. {
  351. CPoint ptScreen = point;
  352. ClientToScreen(&ptScreen);
  353. OnTrackUpdateSize(ptScreen);
  354. }
  355. baseCSizingControlBar::OnMouseMove(nFlags, point);
  356. }
  357. void CSizingControlBar::OnCaptureChanged(CWnd *pWnd)
  358. {
  359. if (m_bTracking && (pWnd != this))
  360. StopTracking();
  361. baseCSizingControlBar::OnCaptureChanged(pWnd);
  362. }
  363. void CSizingControlBar::OnNcCalcSize(BOOL bCalcValidRects,
  364. NCCALCSIZE_PARAMS FAR* lpncsp)
  365. {
  366. UNUSED_ALWAYS(bCalcValidRects);
  367. #ifndef _SCB_REPLACE_MINIFRAME
  368. // Enable diagonal resizing for floating miniframe
  369. if (IsFloating())
  370. {
  371. CFrameWnd* pFrame = GetParentFrame();
  372. if (pFrame != NULL &&
  373. pFrame->IsKindOf(RUNTIME_CLASS(CMiniFrameWnd)))
  374. {
  375. DWORD dwStyle = ::GetWindowLong(pFrame->m_hWnd, GWL_STYLE);
  376. if ((dwStyle & MFS_4THICKFRAME) != 0)
  377. {
  378. pFrame->ModifyStyle(MFS_4THICKFRAME, 0); // clear
  379. GetParent()->ModifyStyle(0, WS_CLIPCHILDREN);
  380. }
  381. }
  382. }
  383. #endif _SCB_REPLACE_MINIFRAME
  384. // compute the the client area
  385. m_dwSCBStyle &= ~SCBS_EDGEALL;
  386. // add resizing edges between bars on the same row
  387. if (!IsFloating() && m_pDockBar != NULL)
  388. {
  389. CSCBArray arrSCBars;
  390. int nThis;
  391. GetRowSizingBars(arrSCBars, nThis);
  392. BOOL bHorz = IsHorzDocked();
  393. if (nThis > 0)
  394. m_dwSCBStyle |= bHorz ? SCBS_EDGELEFT : SCBS_EDGETOP;
  395. if (nThis < arrSCBars.GetUpperBound())
  396. m_dwSCBStyle |= bHorz ? SCBS_EDGERIGHT : SCBS_EDGEBOTTOM;
  397. }
  398. NcCalcClient(&lpncsp->rgrc[0], m_nDockBarID);
  399. }
  400. void CSizingControlBar::NcCalcClient(LPRECT pRc, UINT nDockBarID)
  401. {
  402. CRect rc(pRc);
  403. rc.DeflateRect(0, 3, 1, 1);
  404. if (nDockBarID != AFX_IDW_DOCKBAR_FLOAT)
  405. rc.DeflateRect(2, 0, 2, 2);
  406. switch(nDockBarID)
  407. {
  408. case AFX_IDW_DOCKBAR_TOP:
  409. m_dwSCBStyle |= SCBS_EDGEBOTTOM;
  410. break;
  411. case AFX_IDW_DOCKBAR_BOTTOM:
  412. m_dwSCBStyle |= SCBS_EDGETOP;
  413. break;
  414. case AFX_IDW_DOCKBAR_LEFT:
  415. m_dwSCBStyle |= SCBS_EDGERIGHT;
  416. break;
  417. case AFX_IDW_DOCKBAR_RIGHT:
  418. m_dwSCBStyle |= SCBS_EDGELEFT;
  419. break;
  420. }
  421. // make room for edges only if they will be painted
  422. if (m_dwSCBStyle & SCBS_SHOWEDGES)
  423. rc.DeflateRect(
  424. (m_dwSCBStyle & SCBS_EDGELEFT) ? m_cxEdge : 0,
  425. (m_dwSCBStyle & SCBS_EDGETOP) ? m_cxEdge : 0,
  426. (m_dwSCBStyle & SCBS_EDGERIGHT) ? m_cxEdge : 0,
  427. (m_dwSCBStyle & SCBS_EDGEBOTTOM) ? m_cxEdge : 0);
  428. *pRc = rc;
  429. }
  430. void CSizingControlBar::OnNcPaint()
  431. {
  432. // get window DC that is clipped to the non-client area
  433. CWindowDC dc(this);
  434. CRect rcClient, rcBar;
  435. GetClientRect(rcClient);
  436. ClientToScreen(rcClient);
  437. GetWindowRect(rcBar);
  438. rcClient.OffsetRect(-rcBar.TopLeft());
  439. rcBar.OffsetRect(-rcBar.TopLeft());
  440. CDC mdc;
  441. mdc.CreateCompatibleDC(&dc);
  442. CBitmap bm;
  443. bm.CreateCompatibleBitmap(&dc, rcBar.Width(), rcBar.Height());
  444. CBitmap* pOldBm = mdc.SelectObject(&bm);
  445. // draw borders in non-client area
  446. CRect rcDraw = rcBar;
  447. DrawBorders(&mdc, rcDraw);
  448. // erase the NC background
  449. mdc.FillRect(rcDraw, CBrush::FromHandle(
  450. (HBRUSH) GetClassLong(m_hWnd, GCL_HBRBACKGROUND)));
  451. if (m_dwSCBStyle & SCBS_SHOWEDGES)
  452. {
  453. CRect rcEdge; // paint the sizing edges
  454. for (int i = 0; i < 4; i++)
  455. if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
  456. mdc.Draw3dRect(rcEdge, ::GetSysColor(COLOR_BTNHIGHLIGHT),
  457. ::GetSysColor(COLOR_BTNSHADOW));
  458. }
  459. NcPaintGripper(&mdc, rcClient);
  460. // client area is not our bussiness :)
  461. dc.IntersectClipRect(rcBar);
  462. dc.ExcludeClipRect(rcClient);
  463. dc.BitBlt(0, 0, rcBar.Width(), rcBar.Height(), &mdc, 0, 0, SRCCOPY);
  464. ReleaseDC(&dc);
  465. mdc.SelectObject(pOldBm);
  466. bm.DeleteObject();
  467. mdc.DeleteDC();
  468. }
  469. void CSizingControlBar::NcPaintGripper(CDC* pDC, CRect rcClient)
  470. {
  471. UNUSED_ALWAYS(pDC);
  472. UNUSED_ALWAYS(rcClient);
  473. }
  474. void CSizingControlBar::OnPaint()
  475. {
  476. // overridden to skip border painting based on clientrect
  477. CPaintDC dc(this);
  478. }
  479. LRESULT CSizingControlBar::OnNcHitTest(CPoint point)
  480. {
  481. CRect rcBar, rcEdge;
  482. GetWindowRect(rcBar);
  483. if (!IsFloating())
  484. for (int i = 0; i < 4; i++)
  485. if (GetEdgeRect(rcBar, GetEdgeHTCode(i), rcEdge))
  486. if (rcEdge.PtInRect(point))
  487. return GetEdgeHTCode(i);
  488. return HTCLIENT;
  489. }
  490. void CSizingControlBar::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
  491. {
  492. baseCSizingControlBar::OnSettingChange(uFlags, lpszSection);
  493. m_bDragShowContent = FALSE;
  494. // ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
  495. // &m_bDragShowContent, 0); // update
  496. }
  497. void CSizingControlBar::OnSize(UINT nType, int cx, int cy)
  498. {
  499. UNUSED_ALWAYS(nType);
  500. if ((m_dwSCBStyle & SCBS_SIZECHILD) != 0)
  501. {
  502. // automatic child resizing - only one child is allowed
  503. CWnd* pWnd = GetWindow(GW_CHILD);
  504. if (pWnd != NULL)
  505. {
  506. pWnd->MoveWindow(0, 0, cx, cy);
  507. ASSERT(pWnd->GetWindow(GW_HWNDNEXT) == NULL);
  508. }
  509. }
  510. }
  511. void CSizingControlBar::OnClose()
  512. {
  513. // do nothing: protection against accidentally destruction by the
  514. // child control (i.e. if user hits Esc in a child editctrl)
  515. }
  516. /////////////////////////////////////////////////////////////////////////
  517. // CSizingControlBar implementation helpers
  518. void CSizingControlBar::StartTracking(UINT nHitTest, CPoint point)
  519. {
  520. SetCapture();
  521. // make sure no updates are pending
  522. if (!m_bDragShowContent)
  523. RedrawWindow(NULL, NULL, RDW_ALLCHILDREN | RDW_UPDATENOW);
  524. m_htEdge = nHitTest;
  525. m_bTracking = TRUE;
  526. BOOL bHorz = IsHorzDocked();
  527. BOOL bHorzTracking = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
  528. m_nTrackPosOld = bHorzTracking ? point.x : point.y;
  529. CRect rcBar, rcEdge;
  530. GetWindowRect(rcBar);
  531. GetEdgeRect(rcBar, m_htEdge, rcEdge);
  532. m_nTrackEdgeOfs = m_nTrackPosOld -
  533. (bHorzTracking ? rcEdge.CenterPoint().x : rcEdge.CenterPoint().y);
  534. CSCBArray arrSCBars;
  535. int nThis;
  536. GetRowSizingBars(arrSCBars, nThis);
  537. m_nTrackPosMin = m_nTrackPosMax = m_nTrackPosOld;
  538. if (!IsSideTracking())
  539. {
  540. // calc minwidth as the max minwidth of the sizing bars on row
  541. int nMinWidth = bHorz ? m_szMinHorz.cy : m_szMinVert.cx;
  542. for (int i = 0; i < arrSCBars.GetSize(); i++)
  543. nMinWidth = max(nMinWidth, bHorz ?
  544. arrSCBars[i]->m_szMinHorz.cy :
  545. arrSCBars[i]->m_szMinVert.cx);
  546. int nExcessWidth = (bHorz ? m_szHorz.cy : m_szVert.cx) - nMinWidth;
  547. // the control bar cannot grow with more than the width of
  548. // remaining client area of the mainframe
  549. CRect rcT;
  550. m_pDockSite->RepositionBars(0, 0xFFFF, AFX_IDW_PANE_FIRST,
  551. reposQuery, &rcT, NULL, TRUE);
  552. int nMaxWidth = bHorz ? rcT.Height() - 2 : rcT.Width() - 2;
  553. BOOL bTopOrLeft = m_htEdge == HTTOP || m_htEdge == HTLEFT;
  554. m_nTrackPosMin -= bTopOrLeft ? nMaxWidth : nExcessWidth;
  555. m_nTrackPosMax += bTopOrLeft ? nExcessWidth : nMaxWidth;
  556. }
  557. else
  558. {
  559. // side tracking:
  560. // max size is the actual size plus the amount the other
  561. // sizing bars can be decreased until they reach their minsize
  562. if (m_htEdge == HTBOTTOM || m_htEdge == HTRIGHT)
  563. nThis++;
  564. for (int i = 0; i < arrSCBars.GetSize(); i++)
  565. {
  566. CSizingControlBar* pBar = arrSCBars[i];
  567. int nExcessWidth = bHorz ?
  568. pBar->m_szHorz.cx - pBar->m_szMinHorz.cx :
  569. pBar->m_szVert.cy - pBar->m_szMinVert.cy;
  570. if (i < nThis)
  571. m_nTrackPosMin -= nExcessWidth;
  572. else
  573. m_nTrackPosMax += nExcessWidth;
  574. }
  575. }
  576. OnTrackInvertTracker(); // draw tracker
  577. }
  578. void CSizingControlBar::StopTracking()
  579. {
  580. OnTrackInvertTracker(); // erase tracker
  581. m_bTracking = FALSE;
  582. ReleaseCapture();
  583. m_pDockSite->DelayRecalcLayout();
  584. }
  585. void CSizingControlBar::OnTrackUpdateSize(CPoint& point)
  586. {
  587. ASSERT(!IsFloating());
  588. BOOL bHorzTrack = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
  589. int nTrackPos = bHorzTrack ? point.x : point.y;
  590. nTrackPos = max(m_nTrackPosMin, min(m_nTrackPosMax, nTrackPos));
  591. int nDelta = nTrackPos - m_nTrackPosOld;
  592. if (nDelta == 0)
  593. return; // no pos change
  594. OnTrackInvertTracker(); // erase tracker
  595. m_nTrackPosOld = nTrackPos;
  596. BOOL bHorz = IsHorzDocked();
  597. CSize sizeNew = bHorz ? m_szHorz : m_szVert;
  598. switch (m_htEdge)
  599. {
  600. case HTLEFT: sizeNew -= CSize(nDelta, 0); break;
  601. case HTTOP: sizeNew -= CSize(0, nDelta); break;
  602. case HTRIGHT: sizeNew += CSize(nDelta, 0); break;
  603. case HTBOTTOM: sizeNew += CSize(0, nDelta); break;
  604. }
  605. CSCBArray arrSCBars;
  606. int nThis;
  607. GetRowSizingBars(arrSCBars, nThis);
  608. if (!IsSideTracking())
  609. for (int i = 0; i < arrSCBars.GetSize(); i++)
  610. {
  611. CSizingControlBar* pBar = arrSCBars[i];
  612. // make same width (or height)
  613. (bHorz ? pBar->m_szHorz.cy : pBar->m_szVert.cx) =
  614. bHorz ? sizeNew.cy : sizeNew.cx;
  615. }
  616. else
  617. {
  618. int nGrowingBar = nThis;
  619. BOOL bBefore = m_htEdge == HTTOP || m_htEdge == HTLEFT;
  620. if (bBefore && nDelta > 0)
  621. nGrowingBar--;
  622. if (!bBefore && nDelta < 0)
  623. nGrowingBar++;
  624. if (nGrowingBar != nThis)
  625. bBefore = !bBefore;
  626. // nGrowing is growing
  627. nDelta = abs(nDelta);
  628. CSizingControlBar* pBar = arrSCBars[nGrowingBar];
  629. (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) += nDelta;
  630. // the others are shrinking
  631. int nFirst = bBefore ? nGrowingBar - 1 : nGrowingBar + 1;
  632. int nLimit = bBefore ? -1 : arrSCBars.GetSize();
  633. for (int i = nFirst; nDelta != 0 && i != nLimit; i += (bBefore ? -1 : 1))
  634. {
  635. CSizingControlBar* pBar = arrSCBars[i];
  636. int nDeltaT = min(nDelta,
  637. (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -
  638. (bHorz ? pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy));
  639. (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) -= nDeltaT;
  640. nDelta -= nDeltaT;
  641. }
  642. }
  643. OnTrackInvertTracker(); // redraw tracker at new pos
  644. if (m_bDragShowContent)
  645. m_pDockSite->DelayRecalcLayout();
  646. }
  647. void CSizingControlBar::OnTrackInvertTracker()
  648. {
  649. ASSERT(m_bTracking);
  650. if (m_bDragShowContent)
  651. return; // don't show tracker if DragFullWindows is on
  652. BOOL bHorz = IsHorzDocked();
  653. CRect rc, rcBar, rcDock, rcFrame;
  654. GetWindowRect(rcBar);
  655. m_pDockBar->GetWindowRect(rcDock);
  656. m_pDockSite->GetWindowRect(rcFrame);
  657. VERIFY(GetEdgeRect(rcBar, m_htEdge, rc));
  658. if (!IsSideTracking())
  659. rc = bHorz ?
  660. CRect(rcDock.left + 1, rc.top, rcDock.right - 1, rc.bottom) :
  661. CRect(rc.left, rcDock.top + 1, rc.right, rcDock.bottom - 1);
  662. BOOL bHorzTracking = m_htEdge == HTLEFT || m_htEdge == HTRIGHT;
  663. int nOfs = m_nTrackPosOld - m_nTrackEdgeOfs;
  664. nOfs -= bHorzTracking ? rc.CenterPoint().x : rc.CenterPoint().y;
  665. rc.OffsetRect(bHorzTracking ? nOfs : 0, bHorzTracking ? 0 : nOfs);
  666. rc.OffsetRect(-rcFrame.TopLeft());
  667. CDC *pDC = m_pDockSite->GetDCEx(NULL,
  668. DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
  669. CBrush* pBrush = CDC::GetHalftoneBrush();
  670. CBrush* pBrushOld = pDC->SelectObject(pBrush);
  671. pDC->PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATINVERT);
  672. pDC->SelectObject(pBrushOld);
  673. m_pDockSite->ReleaseDC(pDC);
  674. }
  675. BOOL CSizingControlBar::GetEdgeRect(CRect rcWnd, UINT nHitTest,
  676. CRect& rcEdge)
  677. {
  678. rcEdge = rcWnd;
  679. if (m_dwSCBStyle & SCBS_SHOWEDGES)
  680. rcEdge.DeflateRect(1, 1);
  681. BOOL bHorz = IsHorzDocked();
  682. switch (nHitTest)
  683. {
  684. case HTLEFT:
  685. if (!(m_dwSCBStyle & SCBS_EDGELEFT)) return FALSE;
  686. rcEdge.right = rcEdge.left + m_cxEdge;
  687. rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
  688. break;
  689. case HTTOP:
  690. if (!(m_dwSCBStyle & SCBS_EDGETOP)) return FALSE;
  691. rcEdge.bottom = rcEdge.top + m_cxEdge;
  692. rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
  693. break;
  694. case HTRIGHT:
  695. if (!(m_dwSCBStyle & SCBS_EDGERIGHT)) return FALSE;
  696. rcEdge.left = rcEdge.right - m_cxEdge;
  697. rcEdge.DeflateRect(0, bHorz ? m_cxEdge: 0);
  698. break;
  699. case HTBOTTOM:
  700. if (!(m_dwSCBStyle & SCBS_EDGEBOTTOM)) return FALSE;
  701. rcEdge.top = rcEdge.bottom - m_cxEdge;
  702. rcEdge.DeflateRect(bHorz ? 0 : m_cxEdge, 0);
  703. break;
  704. default:
  705. ASSERT(FALSE); // invalid hit test code
  706. }
  707. return TRUE;
  708. }
  709. UINT CSizingControlBar::GetEdgeHTCode(int nEdge)
  710. {
  711. if (nEdge == 0) return HTLEFT;
  712. if (nEdge == 1) return HTTOP;
  713. if (nEdge == 2) return HTRIGHT;
  714. if (nEdge == 3) return HTBOTTOM;
  715. ASSERT(FALSE); // invalid edge code
  716. return HTNOWHERE;
  717. }
  718. void CSizingControlBar::GetRowInfo(int& nFirst, int& nLast, int& nThis)
  719. {
  720. ASSERT_VALID(m_pDockBar); // verify bounds
  721. nThis = m_pDockBar->FindBar(this);
  722. ASSERT(nThis != -1);
  723. int i, nBars = m_pDockBar->m_arrBars.GetSize();
  724. // find the first and the last bar in row
  725. for (nFirst = -1, i = nThis - 1; i >= 0 && nFirst == -1; i--)
  726. if (m_pDockBar->m_arrBars[i] == NULL)
  727. nFirst = i + 1;
  728. for (nLast = -1, i = nThis + 1; i < nBars && nLast == -1; i++)
  729. if (m_pDockBar->m_arrBars[i] == NULL)
  730. nLast = i - 1;
  731. ASSERT((nLast != -1) && (nFirst != -1));
  732. }
  733. void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars)
  734. {
  735. int nThis; // dummy
  736. GetRowSizingBars(arrSCBars, nThis);
  737. }
  738. void CSizingControlBar::GetRowSizingBars(CSCBArray& arrSCBars, int& nThis)
  739. {
  740. arrSCBars.RemoveAll();
  741. int nFirstT, nLastT, nThisT;
  742. GetRowInfo(nFirstT, nLastT, nThisT);
  743. nThis = -1;
  744. for (int i = nFirstT; i <= nLastT; i++)
  745. {
  746. CSizingControlBar* pBar =
  747. (CSizingControlBar*) m_pDockBar->m_arrBars[i];
  748. if (HIWORD(pBar) == 0) continue; // placeholder
  749. if (!pBar->IsVisible()) continue;
  750. if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  751. {
  752. if (pBar == this)
  753. nThis = arrSCBars.GetSize();
  754. arrSCBars.Add(pBar);
  755. }
  756. }
  757. }
  758. BOOL CSizingControlBar::NegotiateSpace(int nLengthTotal, BOOL bHorz)
  759. {
  760. ASSERT(bHorz == IsHorzDocked());
  761. int nFirst, nLast, nThis;
  762. GetRowInfo(nFirst, nLast, nThis);
  763. int nLengthAvail = nLengthTotal;
  764. int nLengthActual = 0;
  765. int nLengthMin = 2;
  766. int nWidthMax = 0;
  767. CSizingControlBar* pBar;
  768. for (int i = nFirst; i <= nLast; i++)
  769. {
  770. pBar = (CSizingControlBar*) m_pDockBar->m_arrBars[i];
  771. if (HIWORD(pBar) == 0) continue; // placeholder
  772. if (!pBar->IsVisible()) continue;
  773. BOOL bIsSizingBar =
  774. pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar));
  775. int nLengthBar; // minimum length of the bar
  776. if (bIsSizingBar)
  777. nLengthBar = bHorz ? pBar->m_szMinHorz.cx - 2 :
  778. pBar->m_szMinVert.cy - 2;
  779. else
  780. {
  781. CRect rcBar;
  782. pBar->GetWindowRect(&rcBar);
  783. nLengthBar = bHorz ? rcBar.Width() - 2 : rcBar.Height() - 2;
  784. }
  785. nLengthMin += nLengthBar;
  786. if (nLengthMin > nLengthTotal)
  787. {
  788. // split the row after fixed bar
  789. if (i < nThis)
  790. {
  791. m_pDockBar->m_arrBars.InsertAt(i + 1,
  792. (CControlBar*) NULL);
  793. return FALSE;
  794. }
  795. // only this sizebar remains on the row, adjust it to minsize
  796. if (i == nThis)
  797. {
  798. if (bHorz)
  799. m_szHorz.cx = m_szMinHorz.cx;
  800. else
  801. m_szVert.cy = m_szMinVert.cy;
  802. return TRUE; // the dockbar will split the row for us
  803. }
  804. // we have enough bars - go negotiate with them
  805. m_pDockBar->m_arrBars.InsertAt(i, (CControlBar*) NULL);
  806. nLast = i - 1;
  807. break;
  808. }
  809. if (bIsSizingBar)
  810. {
  811. //Tony
  812. nLengthActual += bHorz ? pBar->m_szHorz.cx /*- 2*/ :
  813. pBar->m_szVert.cy /*- 2*/;
  814. nWidthMax = max(nWidthMax, bHorz ? pBar->m_szHorz.cy :
  815. pBar->m_szVert.cx);
  816. }
  817. else
  818. nLengthAvail -= nLengthBar;
  819. }
  820. CSCBArray arrSCBars;
  821. GetRowSizingBars(arrSCBars);
  822. int nNumBars = arrSCBars.GetSize();
  823. int nDelta = nLengthAvail - nLengthActual;
  824. // return faster when there is only one sizing bar per row (this one)
  825. if (nNumBars == 1)
  826. {
  827. ASSERT(arrSCBars[0] == this);
  828. if (nDelta == 0)
  829. return TRUE;
  830. m_bKeepSize = FALSE;
  831. (bHorz ? m_szHorz.cx : m_szVert.cy) += nDelta;
  832. return TRUE;
  833. }
  834. // make all the bars the same width
  835. for (int i = 0; i < nNumBars; i++)
  836. if (bHorz)
  837. arrSCBars[i]->m_szHorz.cy = nWidthMax;
  838. else
  839. arrSCBars[i]->m_szVert.cx = nWidthMax;
  840. // distribute the difference between the bars,
  841. // but don't shrink them below their minsizes
  842. while (nDelta != 0)
  843. {
  844. int nDeltaOld = nDelta;
  845. for (int i = 0; i < nNumBars; i++)
  846. {
  847. pBar = arrSCBars[i];
  848. int nLMin = bHorz ?
  849. pBar->m_szMinHorz.cx : pBar->m_szMinVert.cy;
  850. int nL = bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy;
  851. if ((nL == nLMin) && (nDelta < 0) || // already at min length
  852. pBar->m_bKeepSize) // or wants to keep its size
  853. continue;
  854. // sign of nDelta
  855. int nDelta2 = (nDelta == 0) ? 0 : ((nDelta < 0) ? -1 : 1);
  856. (bHorz ? pBar->m_szHorz.cx : pBar->m_szVert.cy) += nDelta2;
  857. nDelta -= nDelta2;
  858. if (nDelta == 0) break;
  859. }
  860. // clear m_bKeepSize flags
  861. if ((nDeltaOld == nDelta) || (nDelta == 0))
  862. for (int i = 0; i < nNumBars; i++)
  863. arrSCBars[i]->m_bKeepSize = FALSE;
  864. }
  865. return TRUE;
  866. }
  867. void CSizingControlBar::AlignControlBars()
  868. {
  869. int nFirst, nLast, nThis;
  870. GetRowInfo(nFirst, nLast, nThis);
  871. BOOL bHorz = IsHorzDocked();
  872. BOOL bNeedRecalc = FALSE;
  873. int nAlign = 0;//bHorz ? -2 : 0; Tony
  874. CRect rc, rcDock;
  875. m_pDockBar->GetWindowRect(&rcDock);
  876. for (int i = nFirst; i <= nLast; i++)
  877. {
  878. CSizingControlBar* pBar =
  879. (CSizingControlBar*) m_pDockBar->m_arrBars[i];
  880. if (HIWORD(pBar) == 0) continue; // placeholder
  881. if (!pBar->IsVisible()) continue;
  882. pBar->GetWindowRect(&rc);
  883. rc.OffsetRect(-rcDock.TopLeft());
  884. if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  885. rc = CRect(rc.TopLeft(),
  886. bHorz ? pBar->m_szHorz : pBar->m_szVert);
  887. if ((bHorz ? rc.left : rc.top) != nAlign)
  888. {
  889. if (!bHorz)
  890. rc.OffsetRect(0, nAlign - rc.top - 2);
  891. else if (m_nDockBarID == AFX_IDW_DOCKBAR_TOP)
  892. rc.OffsetRect(nAlign - rc.left, -2);
  893. else
  894. rc.OffsetRect(nAlign - rc.left, 0);
  895. if(!m_bTracking)
  896. pBar->MoveWindow(rc);
  897. bNeedRecalc = TRUE;
  898. }
  899. nAlign += (bHorz ? rc.Width() : rc.Height()) - 2;
  900. }
  901. if (bNeedRecalc)
  902. m_pDockSite->DelayRecalcLayout();
  903. }
  904. void CSizingControlBar::OnUpdateCmdUI(CFrameWnd* pTarget,
  905. BOOL bDisableIfNoHndler)
  906. {
  907. UNUSED_ALWAYS(bDisableIfNoHndler);
  908. UNUSED_ALWAYS(pTarget);
  909. }
  910. void CSizingControlBar::LoadState(LPCTSTR lpszProfileName)
  911. {
  912. ASSERT_VALID(this);
  913. ASSERT(GetSafeHwnd()); // must be called after Create()
  914. #if defined(_SCB_REPLACE_MINIFRAME) && !defined(_SCB_MINIFRAME_CAPTION)
  915. // compensate the caption miscalculation in CFrameWnd::SetDockState()
  916. CDockState state;
  917. state.LoadState(lpszProfileName);
  918. UINT nID = GetDlgCtrlID();
  919. for (int i = 0; i < state.m_arrBarInfo.GetSize(); i++)
  920. {
  921. CControlBarInfo* pInfo = (CControlBarInfo*)state.m_arrBarInfo[i];
  922. ASSERT(pInfo != NULL);
  923. if (!pInfo->m_bFloating)
  924. continue;
  925. // this is a floating dockbar - check the ID array
  926. for (int j = 0; j < pInfo->m_arrBarID.GetSize(); j++)
  927. if ((DWORD) pInfo->m_arrBarID[j] == nID)
  928. {
  929. // found this bar - offset origin and save settings
  930. pInfo->m_pointPos.x++;
  931. pInfo->m_pointPos.y +=
  932. ::GetSystemMetrics(SM_CYSMCAPTION) + 1;
  933. pInfo->SaveState(lpszProfileName, i);
  934. }
  935. }
  936. #endif //_SCB_REPLACE_MINIFRAME && !_SCB_MINIFRAME_CAPTION
  937. CWinApp* pApp = AfxGetApp();
  938. TCHAR szSection[256];
  939. wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
  940. GetDlgCtrlID());
  941. m_szHorz.cx = max(m_szMinHorz.cx, (int) pApp->GetProfileInt(
  942. szSection, _T("sizeHorzCX"), m_szHorz.cx));
  943. m_szHorz.cy = max(m_szMinHorz.cy, (int) pApp->GetProfileInt(
  944. szSection, _T("sizeHorzCY"), m_szHorz.cy));
  945. m_szVert.cx = max(m_szMinVert.cx, (int) pApp->GetProfileInt(
  946. szSection, _T("sizeVertCX"), m_szVert.cx));
  947. m_szVert.cy = max(m_szMinVert.cy, (int) pApp->GetProfileInt(
  948. szSection, _T("sizeVertCY"), m_szVert.cy));
  949. m_szFloat.cx = max(m_szMinFloat.cx, (int) pApp->GetProfileInt(
  950. szSection, _T("sizeFloatCX"), m_szFloat.cx));
  951. m_szFloat.cy = max(m_szMinFloat.cy, (int) pApp->GetProfileInt(
  952. szSection, _T("sizeFloatCY"), m_szFloat.cy));
  953. }
  954. void CSizingControlBar::SaveState(LPCTSTR lpszProfileName)
  955. {
  956. // place your SaveState or GlobalSaveState call in
  957. // CMainFrame's OnClose() or DestroyWindow(), not in OnDestroy()
  958. ASSERT_VALID(this);
  959. ASSERT(GetSafeHwnd());
  960. CWinApp* pApp = AfxGetApp();
  961. TCHAR szSection[256];
  962. wsprintf(szSection, _T("%s-SCBar-%d"), lpszProfileName,
  963. GetDlgCtrlID());
  964. pApp->WriteProfileInt(szSection, _T("sizeHorzCX"), m_szHorz.cx);
  965. pApp->WriteProfileInt(szSection, _T("sizeHorzCY"), m_szHorz.cy);
  966. pApp->WriteProfileInt(szSection, _T("sizeVertCX"), m_szVert.cx);
  967. pApp->WriteProfileInt(szSection, _T("sizeVertCY"), m_szVert.cy);
  968. pApp->WriteProfileInt(szSection, _T("sizeFloatCX"), m_szFloat.cx);
  969. pApp->WriteProfileInt(szSection, _T("sizeFloatCY"), m_szFloat.cy);
  970. }
  971. void CSizingControlBar::GlobalLoadState(CFrameWnd* pFrame,
  972. LPCTSTR lpszProfileName)
  973. {
  974. POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
  975. while (pos != NULL)
  976. {
  977. CSizingControlBar* pBar =
  978. (CSizingControlBar*) pFrame->m_listControlBars.GetNext(pos);
  979. ASSERT(pBar != NULL);
  980. if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  981. pBar->LoadState(lpszProfileName);
  982. }
  983. }
  984. void CSizingControlBar::GlobalSaveState(CFrameWnd* pFrame,
  985. LPCTSTR lpszProfileName)
  986. {
  987. POSITION pos = pFrame->m_listControlBars.GetHeadPosition();
  988. while (pos != NULL)
  989. {
  990. CSizingControlBar* pBar =
  991. (CSizingControlBar*) pFrame->m_listControlBars.GetNext(pos);
  992. ASSERT(pBar != NULL);
  993. if (pBar->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  994. pBar->SaveState(lpszProfileName);
  995. }
  996. }
  997. #ifdef _SCB_REPLACE_MINIFRAME
  998. #ifndef _SCB_MINIFRAME_CAPTION
  999. /////////////////////////////////////////////////////////////////////////////
  1000. // CSCBDockContext Drag Operations
  1001. static void AdjustRectangle(CRect& rect, CPoint pt)
  1002. {
  1003. int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) :
  1004. (pt.x > rect.right) ? (pt.x - rect.right) : 0;
  1005. int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) :
  1006. (pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0;
  1007. rect.OffsetRect(nXOffset, nYOffset);
  1008. }
  1009. void CSCBDockContext::StartDrag(CPoint pt)
  1010. {
  1011. ASSERT_VALID(m_pBar);
  1012. m_bDragging = TRUE;
  1013. InitLoop();
  1014. ASSERT((m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) != 0);
  1015. // get true bar size (including borders)
  1016. CRect rect;
  1017. m_pBar->GetWindowRect(rect);
  1018. m_ptLast = pt;
  1019. CSize sizeHorz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK);
  1020. CSize sizeVert = m_pBar->CalcDynamicLayout(0, LM_VERTDOCK);
  1021. CSize sizeFloat = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH);
  1022. m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz);
  1023. m_rectDragVert = CRect(rect.TopLeft(), sizeVert);
  1024. // calculate frame dragging rectangle
  1025. m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat);
  1026. #ifdef _MAC
  1027. CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz,
  1028. WS_THICKFRAME, WS_EX_FORCESIZEBOX);
  1029. #else
  1030. CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz, WS_THICKFRAME);
  1031. #endif
  1032. m_rectFrameDragHorz.DeflateRect(2, 2);
  1033. m_rectFrameDragVert = m_rectFrameDragHorz;
  1034. // adjust rectangles so that point is inside
  1035. AdjustRectangle(m_rectDragHorz, pt);
  1036. AdjustRectangle(m_rectDragVert, pt);
  1037. AdjustRectangle(m_rectFrameDragHorz, pt);
  1038. AdjustRectangle(m_rectFrameDragVert, pt);
  1039. // initialize tracking state and enter tracking loop
  1040. m_dwOverDockStyle = CanDock();
  1041. Move(pt); // call it here to handle special keys
  1042. Track();
  1043. }
  1044. #endif //_SCB_MINIFRAME_CAPTION
  1045. /////////////////////////////////////////////////////////////////////////////
  1046. // CSCBMiniDockFrameWnd
  1047. IMPLEMENT_DYNCREATE(CSCBMiniDockFrameWnd, baseCSCBMiniDockFrameWnd);
  1048. BEGIN_MESSAGE_MAP(CSCBMiniDockFrameWnd, baseCSCBMiniDockFrameWnd)
  1049. //{{AFX_MSG_MAP(CSCBMiniDockFrameWnd)
  1050. ON_WM_NCLBUTTONDOWN()
  1051. ON_WM_GETMINMAXINFO()
  1052. ON_WM_WINDOWPOSCHANGING()
  1053. ON_WM_SIZE()
  1054. //}}AFX_MSG_MAP
  1055. END_MESSAGE_MAP()
  1056. BOOL CSCBMiniDockFrameWnd::Create(CWnd* pParent, DWORD dwBarStyle)
  1057. {
  1058. // set m_bInRecalcLayout to avoid flashing during creation
  1059. // RecalcLayout will be called once something is docked
  1060. m_bInRecalcLayout = TRUE;
  1061. DWORD dwStyle = WS_POPUP|WS_CAPTION|WS_SYSMENU|MFS_MOVEFRAME|
  1062. MFS_4THICKFRAME|MFS_SYNCACTIVE|MFS_BLOCKSYSMENU|
  1063. FWS_SNAPTOBARS;
  1064. if (dwBarStyle & CBRS_SIZE_DYNAMIC)
  1065. dwStyle &= ~MFS_MOVEFRAME;
  1066. DWORD dwExStyle = 0;
  1067. #ifdef _MAC
  1068. if (dwBarStyle & CBRS_SIZE_DYNAMIC)
  1069. dwExStyle |= WS_EX_FORCESIZEBOX;
  1070. else
  1071. dwStyle &= ~(MFS_MOVEFRAME|MFS_4THICKFRAME);
  1072. #endif
  1073. if (!CMiniFrameWnd::CreateEx(dwExStyle,
  1074. NULL, &afxChNil, dwStyle, rectDefault, pParent))
  1075. {
  1076. m_bInRecalcLayout = FALSE;
  1077. return FALSE;
  1078. }
  1079. dwStyle = dwBarStyle & (CBRS_ALIGN_LEFT|CBRS_ALIGN_RIGHT) ?
  1080. CBRS_ALIGN_LEFT : CBRS_ALIGN_TOP;
  1081. dwStyle |= dwBarStyle & CBRS_FLOAT_MULTI;
  1082. CMenu* pSysMenu = GetSystemMenu(FALSE);
  1083. //pSysMenu->DeleteMenu(SC_SIZE, MF_BYCOMMAND);
  1084. CString strHide;
  1085. if (strHide.LoadString(AFX_IDS_HIDE))
  1086. {
  1087. pSysMenu->DeleteMenu(SC_CLOSE, MF_BYCOMMAND);
  1088. pSysMenu->AppendMenu(MF_STRING|MF_ENABLED, SC_CLOSE, strHide);
  1089. }
  1090. // must initially create with parent frame as parent
  1091. if (!m_wndDockBar.Create(pParent, WS_CHILD | WS_VISIBLE | dwStyle,
  1092. AFX_IDW_DOCKBAR_FLOAT))
  1093. {
  1094. m_bInRecalcLayout = FALSE;
  1095. return FALSE;
  1096. }
  1097. // set parent to CMiniDockFrameWnd
  1098. m_wndDockBar.SetParent(this);
  1099. m_bInRecalcLayout = FALSE;
  1100. return TRUE;
  1101. }
  1102. void CSCBMiniDockFrameWnd::OnNcLButtonDown(UINT nHitTest, CPoint point)
  1103. {
  1104. if (nHitTest == HTCAPTION || nHitTest == HTCLOSE)
  1105. {
  1106. baseCSCBMiniDockFrameWnd::OnNcLButtonDown(nHitTest, point);
  1107. return;
  1108. }
  1109. if (GetSizingControlBar() != NULL)
  1110. CMiniFrameWnd::OnNcLButtonDown(nHitTest, point);
  1111. else
  1112. baseCSCBMiniDockFrameWnd::OnNcLButtonDown(nHitTest, point);
  1113. }
  1114. CSizingControlBar* CSCBMiniDockFrameWnd::GetSizingControlBar()
  1115. {
  1116. CWnd* pWnd = GetWindow(GW_CHILD); // get the dockbar
  1117. if (pWnd == NULL)
  1118. return NULL;
  1119. pWnd = pWnd->GetWindow(GW_CHILD); // get the controlbar
  1120. if (pWnd == NULL)
  1121. return NULL;
  1122. if (!pWnd->IsKindOf(RUNTIME_CLASS(CSizingControlBar)))
  1123. return NULL;
  1124. return (CSizingControlBar*) pWnd;
  1125. }
  1126. void CSCBMiniDockFrameWnd::OnSize(UINT nType, int cx, int cy)
  1127. {
  1128. CSizingControlBar* pBar = GetSizingControlBar();
  1129. if ((pBar != NULL) && (GetStyle() & MFS_4THICKFRAME) == 0
  1130. && pBar->IsVisible())
  1131. pBar->m_szFloat = CSize(cx + 4, cy + 4);
  1132. baseCSCBMiniDockFrameWnd::OnSize(nType, cx, cy);
  1133. }
  1134. void CSCBMiniDockFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
  1135. {
  1136. baseCSCBMiniDockFrameWnd::OnGetMinMaxInfo(lpMMI);
  1137. CSizingControlBar* pBar = GetSizingControlBar();
  1138. if (pBar != NULL)
  1139. {
  1140. CRect r(CPoint(0, 0), pBar->m_szMinFloat - CSize(4, 4));
  1141. #ifndef _SCB_MINIFRAME_CAPTION
  1142. CMiniFrameWnd::CalcBorders(&r, WS_THICKFRAME);
  1143. #else
  1144. CMiniFrameWnd::CalcBorders(&r, WS_THICKFRAME|WS_CAPTION);
  1145. #endif //_SCB_MINIFRAME_CAPTION
  1146. lpMMI->ptMinTrackSize.x = r.Width();
  1147. lpMMI->ptMinTrackSize.y = r.Height();
  1148. }
  1149. }
  1150. void CSCBMiniDockFrameWnd::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
  1151. {
  1152. if ((GetStyle() & MFS_4THICKFRAME) != 0)
  1153. {
  1154. CSizingControlBar* pBar = GetSizingControlBar();
  1155. if (pBar != NULL)
  1156. {
  1157. lpwndpos->flags |= SWP_NOSIZE; // don't size this time
  1158. // prevents flicker
  1159. pBar->m_pDockBar->ModifyStyle(0, WS_CLIPCHILDREN);
  1160. // enable diagonal resizing
  1161. ModifyStyle(MFS_4THICKFRAME, 0);
  1162. #ifndef _SCB_MINIFRAME_CAPTION
  1163. // remove caption
  1164. ModifyStyle(WS_SYSMENU|WS_CAPTION, 0);
  1165. #endif
  1166. DelayRecalcLayout();
  1167. pBar->PostMessage(WM_NCPAINT);
  1168. }
  1169. }
  1170. CMiniFrameWnd::OnWindowPosChanging(lpwndpos);
  1171. }
  1172. #endif //_SCB_REPLACE_MINIFRAME