gripdialogbar.cpp
上传用户:libwxy
上传日期:2007-01-02
资源大小:200k
文件大小:32k
源码类别:

工具条

开发平台:

Visual C++

  1. /////////////////////////////////////////////////////////////////////////////
  2. // This is an extension to the MFC C++ library.
  3. // Copyright (C) 1997-1998 ACPSoft
  4. // All rights reserved.
  5. //
  6. // This source code is only intended as a building
  7. // tool to aid your own development.  This code is
  8. // under the license agreement provided with the
  9. // software. By using this code in your own project(s)
  10. // you agree to the terms in that license.
  11. /////////////////////////////////////////////////////////////////////////////
  12. // MFC includes
  13. #include "stdafx.h"
  14. #include <afxpriv.h> 
  15. #include <..srcafximpl.h> 
  16. // Local includes
  17. #include "GripDialogBar.h" 
  18. #ifdef _DEBUG 
  19. #undef THIS_FILE 
  20. static char THIS_FILE[]=__FILE__; 
  21. #define new DEBUG_NEW 
  22. #endif
  23. /////////////////////////////////////////////////////////////////// 
  24. // Class CInitDialogBar 
  25. // 
  26. // Class provides new behavior for OnInitDialogBar() 
  27. // and DDX support for common CDialogBar
  28. //  
  29. /////////////////////////////////////////////////////////////////// 
  30. //////////////////////////////////////////////////////////////////////
  31. // Construction/Destruction
  32. //////////////////////////////////////////////////////////////////////
  33. IMPLEMENT_DYNAMIC(CInitDialogBar, CDialogBar)
  34. CInitDialogBar::CInitDialogBar()
  35. {
  36. // In derived classes set intial
  37. // state of control(s) in the derived
  38. // constructor
  39. }
  40. CInitDialogBar::~CInitDialogBar()
  41. {
  42. }
  43. BEGIN_MESSAGE_MAP(CInitDialogBar, CDialogBar)
  44. //{{AFX_MSG_MAP(CInitDialogBar)
  45. //}}AFX_MSG_MAP
  46. END_MESSAGE_MAP()
  47. BOOL CInitDialogBar::Create(CWnd * pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID)
  48. {
  49. ASSERT(pParentWnd);
  50. m_dwStyle = nStyle;
  51. //Let MFC Create the control
  52. if(!CDialogBar::Create(pParentWnd,
  53. nIDTemplate,
  54. nStyle,
  55. nID))
  56. return FALSE;
  57. // Since there is no WM_INITDIALOG message we have to call
  58. // our own InitDialog function ourselves after m_hWnd is valid
  59. if(!OnInitDialogBar())
  60. return FALSE;
  61. return TRUE;
  62. }
  63. BOOL CInitDialogBar::Create(CWnd * pParentWnd, LPCTSTR lpszTemplateName, UINT nStyle, UINT nID)
  64. {
  65. ASSERT(pParentWnd);
  66. m_dwStyle = nStyle;
  67. //Let MFC Create the control
  68. if(!CDialogBar::Create(pParentWnd,
  69. lpszTemplateName,
  70. nStyle,
  71. nID))
  72. return 0;
  73. // Since there is no WM_INITDIALOG message we have to call
  74. // our own InitDialog function ourselves after m_hWnd is valid
  75. if(!OnInitDialogBar())
  76. return FALSE;
  77. return TRUE;
  78. }
  79. BOOL CInitDialogBar::OnInitDialogBar()
  80. {
  81. // Support for the MFC DDX model
  82. // If you do not want this do not 
  83. // call the base class from derived 
  84. // classes
  85. UpdateData(FALSE);
  86. return TRUE;
  87. }
  88. void CInitDialogBar::DoDataExchange(CDataExchange* pDX) 
  89. {
  90. //Derived Classes Overide this function
  91. ASSERT(pDX);
  92. // In derived class call the DDX_???
  93. // functions to set retrieve values
  94. // of your controls
  95. // See example derived class for how
  96. // to do this.
  97. CDialogBar::DoDataExchange(pDX);
  98. }
  99. //////////////////////////////////////////////////////////////////////
  100. // Class CGripDialogBar 
  101. // 
  102. // Class provides new behavior for drawing the 
  103. // CDialog Bar make it like a DevStudio workspace
  104. //  
  105. //////////////////////////////////////////////////////////////////////
  106. //////////////////////////////////////////////////////////////////////
  107. // Construction/Destruction 
  108. //////////////////////////////////////////////////////////////////////
  109. IMPLEMENT_DYNAMIC(CGripDialogBar, CInitDialogBar) 
  110. CGripDialogBar::CGripDialogBar()
  111. {
  112. // Default style Gripper bars and
  113. // close button only to add text
  114. // dockbutton or title use the
  115. // GBS_??? flags
  116. m_GripBar = new CGripControl();
  117. m_bActive = -1;
  118. }
  119. CGripDialogBar::CGripDialogBar(UINT nID, DWORD Style, COLORREF clr)
  120. {
  121. // To use color be sure to
  122. // Set the GBS_USECOLOR bit
  123. // GBS_DOCKAPPST - Display App String
  124. // GBS_DOCKBUTTON - Display the dock button
  125. // GBS_DOCKCLOSE - Display the close button
  126. // GBS_DOCKTITLE - Displays window title
  127. // GBS_NOGRADIENT - Use solid color
  128. // GBS_NOGRIPBARS - Do not display grip bars
  129. // GBS_USECOLOR - Use user defined color
  130. m_GripBar = new CGripControl(nID, Style, clr);
  131. m_bActive = -1;
  132. }
  133. CGripDialogBar::~CGripDialogBar() 
  134. // Cleanup
  135. if(m_GripBar)
  136. delete m_GripBar;
  137. }
  138. BEGIN_MESSAGE_MAP(CGripDialogBar, CInitDialogBar) 
  139. //{{AFX_MSG_MAP(CInitDialogBar)
  140. ON_WM_CLOSE()
  141. ON_WM_ERASEBKGND()
  142. ON_WM_NCACTIVATE()
  143. ON_WM_NCPAINT() 
  144. ON_WM_PAINT()
  145. //}}AFX_MSG_MAP 
  146. END_MESSAGE_MAP()
  147. void CGripDialogBar::GetCaptionRect(CRect* rect)
  148. {
  149. // Get the frame size
  150. DWORD style = GetStyle();
  151. CSize frame;
  152. if(style & WS_BORDER)
  153. frame = CSize(GetSystemMetrics(SM_CXFIXEDFRAME),
  154. GetSystemMetrics(SM_CXFIXEDFRAME));
  155. else
  156. frame = CSize(GetSystemMetrics(SM_CXFIXEDFRAME),
  157. GetSystemMetrics(SM_CYFIXEDFRAME));
  158. // Compute caption area
  159. GetWindowRect(rect);
  160. CPoint pt(rect->left, rect->top);
  161. // Our DC has 0,0 as it origin
  162. *rect -= pt;
  163. // Adjust for window frame
  164. rect->left  += frame.cx;
  165. rect->right -= frame.cx;
  166. rect->top   += frame.cy;
  167. rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION)
  168. - GetSystemMetrics(SM_CYBORDER);
  169. return;
  170. }
  171. inline
  172. DWORD CGripDialogBar::GetGripStyle()
  173. {
  174. return m_GripBar->m_GBStyle;
  175. }
  176. void CGripDialogBar::ModifyGripStyle(DWORD remove, DWORD add)
  177. {
  178. m_GripBar->m_GBStyle = m_GripBar->m_GBStyle | add;
  179. m_GripBar->m_GBStyle = m_GripBar->m_GBStyle & ~remove;
  180. m_GripBar->Abolish();
  181. }
  182. void CGripDialogBar::SetActiveState(UINT nState)
  183. {
  184. if(!IsWindow(m_hWnd))
  185. return;
  186. WPARAM state;
  187. // Call this function from your main frame
  188. // OnActivate Handler. Example:
  189. // void CMainFrame::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
  190. // {
  191. //      m_YourObject.SetActiveState(nState); <-- Add this line
  192. //      CMDIFrameWnd::OnActivate(nState, pWndOther, bMinimized);
  193. //      return;
  194. // }
  195. if(nState == WA_INACTIVE)
  196. state = FALSE;
  197. else
  198. state = TRUE;
  199. SendMessage(WM_NCACTIVATE, state, 0);
  200. return;
  201. }
  202. void CGripDialogBar::StartDrag(CPoint point)
  203. {
  204. ASSERT(m_pDockContext != NULL);
  205. m_pDockContext->StartDrag(point);
  206. Invalidate(TRUE);
  207. }
  208. void CGripDialogBar::ToggleDocking()
  209. {
  210.  ASSERT(m_pDockContext != NULL); 
  211.      m_pDockContext->ToggleDocking(); 
  212. }
  213. void CGripDialogBar::View(CFrameWnd* fWnd, BOOL state)
  214. {
  215. ASSERT(fWnd);
  216. // Put this function in your handler
  217. // which toggles the view of the control
  218. fWnd->ShowControlBar(this, state, FALSE);
  219. }
  220. BOOL CGripDialogBar::OnInitDialogBar() 
  221. // To display a title modify your resource
  222. // select the title checkbox, the grip bar will
  223. // take the title of the window. Set your
  224. // margin at 16 or more dialog units. See below.
  225. m_GripBar->Fasten(this);
  226. // To avoid MFC bugs with edit controls we need
  227. // to turn off the caption style and provide our
  228. // own caption. This means in your resource you
  229. // need to leave a little space at the top for
  230. // the caption. Set the top margin at 16 DLG Units
  231. // This works well.
  232. ModifyStyle(WS_CAPTION, 0);
  233. // Setup the overidden context for Docking.
  234. // We will use this context to provide our own 
  235. // docking functionality.  By doing this ourselves
  236. // now instead of during Enable docking we are
  237. // able to replace the original member variable
  238. // with our new class. All changes MUST occur
  239. // in virtual functions. 
  240.      if (m_pDockContext == NULL) 
  241.           m_pDockContext = new CExDockContext(this); 
  242.      ASSERT(m_pDockContext); 
  243.      // Call Base Class. You must do this
  244.      CInitDialogBar::OnInitDialogBar(); 
  245.      return TRUE; 
  246. }
  247. void CGripDialogBar::ExcludeCaption(CDC* pDC) 
  248. // Compute caption area
  249. CRect capRect;
  250. CRect rcWin;
  251. GetWindowRect(rcWin);
  252. GetCaptionRect(&capRect);
  253. // There is no need to paint the caption
  254. // area twice so only our provided caption
  255. // paint it. The parent need not paint
  256. // the same area. This helps to prevent
  257. // flicker in drawing.
  258. pDC->ExcludeClipRect(&capRect);
  259. void CGripDialogBar::PaintRect(CDC* pDC, int x, int y, int w, int h, COLORREF color)
  260. {
  261. CBrush brush(color);
  262. CBrush* pOldBrush = pDC->SelectObject(&brush);
  263. pDC->PatBlt(x, y, w, h, PATCOPY);
  264. pDC->SelectObject(pOldBrush);
  265. }
  266. void CGripDialogBar::RecalcLayout() 
  267. // If we are floating we do not want 
  268. // our new caption to be visible, 
  269. // so we move our window up so our 
  270. // caption is underneath the CMiniFrameWnd 
  271. // caption 
  272. if(IsFloating()) 
  273. {
  274. CRect rect; 
  275. GetWindowRect(rect); 
  276. SetWindowPos(NULL, 
  277. 0, 
  278. -(GetSystemMetrics(SM_CYCAPTION) 
  279. + GetSystemMetrics(SM_CYFRAME)), 
  280. rect.Width(), 
  281. rect.Height(), 
  282. NULL); 
  283. void CGripDialogBar::OnClose() 
  284. {
  285. CFrameWnd* wnd;
  286. wnd = (CFrameWnd*) AfxGetMainWnd();
  287. ASSERT(wnd);
  288. // Make sure your main Wnd is really a 
  289. // Frame Wnd Object else we do nothing
  290. // This protects us from apps which do not
  291. // use CFrameWnd for their main window.
  292. // Those apps will need to override to
  293. // provide their own support for close.
  294. if(wnd->IsKindOf(RUNTIME_CLASS(CFrameWnd)))
  295. {
  296. // Close (really hide) our control bar
  297. wnd->ShowControlBar(this, FALSE, FALSE);
  298. }
  299. return;
  300. }
  301. BOOL CGripDialogBar::OnEraseBkgnd(CDC* pDC)
  302. {
  303. ExcludeCaption(pDC);
  304. CInitDialogBar::OnEraseBkgnd(pDC);
  305. return TRUE;
  306. }
  307. BOOL CGripDialogBar::OnNcActivate(BOOL bActive) 
  308. // Tell the control which of our two
  309. // caption bitmaps to paint
  310. m_bActive = bActive;
  311. m_GripBar->Invalidate(TRUE);
  312. return TRUE;
  313. }
  314. void CGripDialogBar::OnPaint() 
  315. // Notice here we break the do not call 
  316. // the base class OnPaint Rule. This is 
  317. // because we do not set up our own DC 
  318. // here so calling the base is OK and
  319. // also required otherwise we need to
  320. // redo what the base already does for us 
  321. RecalcLayout(); 
  322. CDialogBar::OnPaint(); 
  323. /////////////////////////////////////////////////////////////////// 
  324. // Class CGripControl 
  325. // 
  326. // Class provides new behavior for drawing the 
  327. // CDialog Bar make it like a DevStudio workspace
  328. //  
  329. /////////////////////////////////////////////////////////////////// 
  330. // Local defines
  331. #define WHITE RGB(255,255,255)
  332. #define BLACK RGB(0,0,0)
  333. #define GRADBOXWIDTH 80
  334. #define HLSMAX 240
  335. #define RGBMAX 255
  336. // Local functions
  337. // The following function is
  338. /////////////////////////////////////////////////
  339. // Copyright (1997) Microsoft Systems Journal
  340. /////////////////////////////////////////////////
  341. static int GetLuminosity(COLORREF color)
  342. {
  343. int r = GetRValue(color);
  344. int g = GetGValue(color);
  345. int b = GetBValue(color);
  346. int rgbMax = max( max(r,g), b);
  347. int rgbMin = min( min(r,g), b);
  348. return (((rgbMax+rgbMin) * HLSMAX) + RGBMAX ) / (2*RGBMAX);
  349. }
  350. /////////////////////////////////////////////////
  351. // End MSJ code
  352. /////////////////////////////////////////////////
  353. ////////////////////////////////////////////////////////////////////// 
  354. // Construction/Destruction 
  355. ////////////////////////////////////////////////////////////////////// 
  356. IMPLEMENT_DYNCREATE(CGripControl, CEdit)
  357. CGripControl::CGripControl()
  358. {
  359. // Default style
  360. // Gripper bars and close
  361. // button only to add text
  362. // dockbutton or title use
  363. // the GBS flags
  364. m_nID = 0;
  365. m_GBStyle = GBS_DOCKCLOSE;
  366. m_prevHitTest = -1;
  367. // DevStudio Generated String
  368. // for application title
  369. UINT id = AFX_IDS_APP_TITLE;
  370. m_appString.LoadString(id);
  371. }
  372. CGripControl::CGripControl(UINT nID, DWORD Style, COLORREF clr)
  373. {
  374. m_ColorCap = clr;
  375. m_GBStyle = Style;
  376. m_prevHitTest = -1;
  377. m_nID = nID;
  378. // DevStudio Generated String
  379. // for application title
  380. UINT id = AFX_IDS_APP_TITLE;
  381. m_appString.LoadString(id);
  382. }
  383. CGripControl::~CGripControl()
  384. {
  385. }
  386. BEGIN_MESSAGE_MAP(CGripControl, CEdit)
  387. //{{AFX_MSG_MAP(CGripControl)
  388. ON_WM_ERASEBKGND()
  389. ON_WM_PAINT()
  390. ON_WM_LBUTTONDOWN()
  391. ON_WM_SETCURSOR()
  392. ON_WM_LBUTTONDBLCLK()
  393. ON_WM_LBUTTONUP()
  394. ON_WM_MOUSEMOVE()
  395. ON_WM_SETTINGCHANGE()
  396. ON_WM_SYSCOLORCHANGE()
  397. //}}AFX_MSG_MAP
  398. END_MESSAGE_MAP()
  399. /////////////////////////////////////////////////////////////////////////////
  400. // CGripControl message handlers
  401. void CGripControl::Abolish()
  402. {
  403. // Next time we paint use the newly
  404. // seleted settings.
  405. m_fontCap.DeleteObject();
  406. m_fontTitle.DeleteObject();
  407. m_rcCap.SetRectEmpty();
  408. }
  409. void CGripControl::Fasten(CGripDialogBar* pControlBar)
  410. {
  411. ASSERT(pControlBar);
  412. ASSERT(pControlBar->IsKindOf(RUNTIME_CLASS(CGripDialogBar)));
  413. m_pControlBar = pControlBar;
  414. // Setup the Grip Bar Control
  415. // using the parms from the control
  416. // Get the text and rect from control
  417. CString str;
  418. m_pControlBar->GetWindowText(str);
  419. // Dummy Rect for Creation purposes
  420. // The window is moved to the proper
  421. // location during erase background
  422. CRect rc(0,0,10,50);
  423. Create(WS_VISIBLE,
  424. rc,
  425. m_pControlBar,
  426. m_nID);
  427. ASSERT(IsWindow(m_hWnd));
  428. SetWindowText(str);
  429. }
  430. inline
  431. CString CGripControl::GetBarTitle()
  432. {
  433. CString str;
  434. GetWindowText(str);
  435. return str;
  436. }
  437. inline 
  438. void CGripControl::GetCaptionRect(CRect* rect)
  439. {
  440. GetClientRect(rect);
  441. return;
  442. }
  443. void CGripControl::CreateFonts()
  444. {
  445. NONCLIENTMETRICS ncm;
  446. ncm.cbSize = sizeof(ncm);
  447. VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
  448. 0,
  449. &ncm,
  450. 0));
  451. // Derived classes can esily override to provide
  452. // their own font support
  453. m_fontCap.CreateFontIndirect(&ncm.lfCaptionFont);
  454. m_fontTitle.CreateFontIndirect(&ncm.lfCaptionFont);
  455. void CGripControl::OnNcDraw(CDC* pDC)
  456. {
  457. // We will draw on a MemDC then BitBlt
  458. // the bmp to the window DC
  459. CDC memDC;
  460. memDC.CreateCompatibleDC(pDC);
  461. // See if we need a new bitmap
  462. UpdateBitmap(m_pControlBar->m_bActive,
  463. &memDC,
  464. pDC);
  465. // Get paint area 
  466. // It's set by update bitmap
  467. CRect& rc = m_rcCap;
  468. // OK Paint
  469. pDC->BitBlt(rc.left,
  470. rc.top,
  471. rc.Width(),
  472. rc.Height(),
  473. &memDC,
  474. 0,
  475. 0,
  476. SRCCOPY);
  477. return;
  478. }
  479. void CGripControl::DrawOnBitmap(BOOL bActive, CDC* pMemDC, CRect* pRC)
  480. {
  481. int w = pRC->Width();
  482. int cxIcon = GetSystemMetrics(SM_CXSIZE);
  483. int cyIcon = GetSystemMetrics(SM_CYSIZE);
  484. // Paint our inactive bmp
  485. if (!bActive)
  486. {
  487. // Let's not get fancy; when we are inactive
  488. // The window is probably out of view anyway.
  489. // Don't waste CPU cycles on something no one
  490. // may ever see. So we will just fill the caption
  491. // Rect with the default inactive color
  492. PaintRect(pMemDC,
  493. 0,
  494. 0,
  495. pRC->Width(),
  496. pRC->Height(),
  497. GetSysColor(COLOR_INACTIVECAPTION));
  498. }
  499. else
  500. {
  501. // Active : We paint according to
  502. // which flags are set
  503. COLORREF clr;
  504. // Do we use windows default
  505. // or user supplied color
  506. if(m_GBStyle & GBS_USECOLOR)
  507. {
  508. // user supplied
  509. clr = m_ColorCap;
  510. }
  511. else
  512. {
  513. // widnows default
  514. clr = GetSysColor(COLOR_ACTIVECAPTION); 
  515. }
  516. // Do we use quadratic gradient
  517. // or solid Fill
  518. if(m_GBStyle & GBS_NOGRADIENT)
  519. {
  520. // If you prefer not to have a color gradient
  521. // use this flag
  522. PaintRect(pMemDC,
  523. 0,
  524. 0,
  525. pRC->Width(),
  526. pRC->Height(),
  527. clr);
  528. }
  529. else
  530. {
  531. // Use the quadratic gradient
  532. // The following gradient:
  533. /////////////////////////////////////////////////
  534. // Copyright (1997) Microsoft Systems Journal
  535. /////////////////////////////////////////////////
  536. // Note: future version of this code will replace
  537. // this gradient with a new one.
  538. int r = GetRValue(clr);
  539. int g = GetGValue(clr);
  540. int b = GetBValue(clr);
  541. int x = 7 * pRC->right / 8;
  542. int w = x - pRC->left;
  543. int xDelta= max((w / GRADBOXWIDTH),1);
  544. int h = pRC->Height();
  545. PaintRect(pMemDC,
  546. x,
  547. 0,
  548. pRC->right - x,
  549. h,
  550. clr);
  551. int w2  = w*w;
  552. while (x > xDelta)
  553. {
  554. x -= xDelta;
  555. int wmx2 = (w-x)*(w-x);
  556. PaintRect(pMemDC,
  557. x,
  558. 0,
  559. xDelta,
  560. h,
  561. RGB(r-(r*wmx2)/w2,
  562. g-(g*wmx2)/w2,
  563. b-(b*wmx2)/w2));
  564. }
  565. // Remainder paint black
  566. PaintRect(pMemDC,0,0,x,h,BLACK);
  567. /////////////////////////////////////////////////
  568. // End MSJ code
  569. /////////////////////////////////////////////////
  570. }
  571. }
  572. // Draw icon and caption buttons.
  573. // Note if you do not want these
  574. // buttons use the GBS_??? flags
  575. // to turn on/off. See constructor
  576. // comments for more details
  577. CRect rcButn(0,0,cxIcon,cyIcon);
  578. rcButn.DeflateRect(0,2);
  579. rcButn.left += 2;
  580. // Do we want the dock button?
  581. if(m_GBStyle & GBS_DOCKBUTTON)
  582. {
  583. m_rcIcon = rcButn;
  584. pMemDC->DrawFrameControl(&rcButn,
  585. DFC_CAPTION,
  586. DFCS_CAPTIONRESTORE);
  587. }
  588. else
  589. m_rcIcon.SetRect(-1,-1,-1,-1);
  590. rcButn += CPoint(w-cxIcon-2,0);
  591. // Do we want the close button?
  592. if(m_GBStyle & GBS_DOCKCLOSE)
  593. {
  594. m_rcClose = rcButn;
  595. pMemDC->DrawFrameControl(&rcButn,
  596. DFC_CAPTION,
  597. DFCS_CAPTIONCLOSE);
  598. }
  599. else
  600. m_rcClose.SetRect(-1,-1,-1,-1);
  601. CString str;
  602. // Do we want the application string?
  603. if((m_GBStyle & GBS_DOCKAPPST))
  604. {
  605. str = m_appString;
  606. if(m_GBStyle & GBS_DOCKTITLE)
  607. {
  608. str += _T(" - ");
  609. }
  610. }
  611. else
  612. str = _T(" ");
  613. CRect rcText = CRect(pRC->TopLeft(),
  614. pMemDC->GetTextExtent(str));
  615. // Use old fonts or create new if user
  616. // has changed system settings
  617. if (!m_fontCap.m_hObject)
  618. CreateFonts();
  619. CFont* pOldFont = pMemDC->SelectObject(&m_fontTitle);
  620. if(!(m_GBStyle & GBS_DOCKBUTTON))
  621. {
  622. rcText.left += 2;  
  623. rcText.right += 2;
  624. }
  625. else
  626. {
  627. rcText.left += cxIcon+2;  
  628. rcText.right += cxIcon+2;
  629. }
  630. // Set our text color
  631. COLORREF clrText;
  632. if (bActive)
  633. {
  634. clrText = GetSysColor(COLOR_CAPTIONTEXT);
  635. if(m_GBStyle & GBS_NOGRADIENT)
  636. {
  637. // If the current color will not show
  638. // up in the window let's brighten it
  639. // until it will
  640. while(GetLuminosity(clrText) < 90)
  641. {
  642. int r = GetRValue(clrText);
  643. int g = GetGValue(clrText);
  644. int b = GetBValue(clrText);
  645. r+= 20;
  646. g+= 20;
  647. b+= 20;
  648. clrText = RGB(r,
  649. g,
  650. b);
  651. }
  652. }
  653. } else
  654. clrText = GetSysColor(COLOR_INACTIVECAPTIONTEXT);
  655. pMemDC->SetBkMode(TRANSPARENT);
  656. pMemDC->SetTextColor(clrText);
  657. pMemDC->DrawText(str,
  658. &rcText,
  659. DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
  660. if(m_GBStyle & GBS_DOCKTITLE)
  661. {
  662. pMemDC->SelectObject(&m_fontCap);
  663. rcText.left += pMemDC->GetTextExtent(str).cx;
  664. str = GetBarTitle();
  665. rcText.right += pMemDC->GetTextExtent(str).cx + 4;
  666. if (rcText.right > rcText.left)
  667. {
  668. pMemDC->DrawText(GetBarTitle(),
  669. &rcText,
  670. DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
  671. }
  672. if(!(m_GBStyle & GBS_NOGRIPBARS))
  673. {
  674. // Draw the docking grippers
  675. CRect rect(5, 6, (5+w) - 30, 9);
  676. if((m_GBStyle & GBS_DOCKTITLE) ||
  677. (m_GBStyle & GBS_DOCKAPPST))
  678. {
  679. rect.left += rcText.right;
  680. }
  681. else
  682. {
  683. if(m_GBStyle & GBS_DOCKBUTTON)
  684. {
  685. rect.left = m_rcIcon.right + 2;
  686. }
  687. else
  688. {
  689. rect.left = 2;
  690. }
  691. }
  692. if(m_GBStyle & GBS_DOCKCLOSE)
  693. {
  694. rect.right = m_rcClose.left - 2;
  695. }
  696. else
  697. {
  698. rect.right = rcButn.right;
  699. }
  700. if (rect.right > rect.left)
  701. {
  702. pMemDC->Draw3dRect(rect,
  703. RGB(255,255,255),
  704. RGB(128,128,128));
  705. rect += CPoint(0, 4);
  706. pMemDC->Draw3dRect(rect,
  707. RGB(255,255,255),
  708. RGB(128,128,128));
  709. }
  710. }
  711. // Restore DC
  712. pMemDC->SelectObject(pOldFont);
  713. return;
  714. }
  715. DWORD CGripControl::HitTest(CPoint pt)
  716. {
  717. if(m_rcClose.PtInRect(pt))
  718. return (DWORD) GHT_CLOSE;
  719. else if(m_rcIcon.PtInRect(pt))
  720. return (DWORD) GHT_DOCKBUT;
  721. else
  722. return (DWORD) GHT_CAPTION;
  723. }
  724. void CGripControl::PaintRect(CDC* pDC, int x, int y, int w, int h, COLORREF color)
  725. {
  726. CBrush brush(color);
  727. CBrush* pOldBrush = pDC->SelectObject(&brush);
  728. pDC->PatBlt(x, y, w, h, PATCOPY);
  729. pDC->SelectObject(pOldBrush);
  730. }
  731. void CGripControl::UpdateBitmap(BOOL bActive, CDC * pMemDC, CDC * pWinDC)
  732. {
  733. // Get our Active or inactive bmp
  734. CBitmap& bmp = m_bmpCap[bActive != 0];
  735. // Get our draw region
  736. CRect rcCap;
  737. GetCaptionRect(&rcCap);
  738. // If we have a new Rect redraw
  739. // bmp otherwise use the old one
  740. if (rcCap != m_rcCap) {
  741. m_bmpCap[0].DeleteObject();
  742. m_bmpCap[1].DeleteObject();
  743. m_rcCap = rcCap;
  744. }
  745. // Make sure there is a valid bmp
  746. if (bmp.m_hObject)
  747. {
  748. pMemDC->SelectObject(&bmp);
  749. return;
  750. }
  751. // Erase old bmp
  752. bmp.DeleteObject();
  753. // Create new bmp
  754. bmp.CreateCompatibleBitmap(pWinDC,
  755. m_rcCap.Width(),
  756. m_rcCap.Height());
  757. pMemDC->SelectObject(&bmp);
  758. DrawOnBitmap(bActive, pMemDC, &m_rcCap);
  759. return;
  760. }
  761. BOOL CGripControl::OnEraseBkgnd(CDC* pDC)
  762. {
  763. CRect rect;
  764. m_pControlBar->GetCaptionRect(&rect);
  765. MoveWindow(rect, TRUE);
  766. return TRUE;
  767. }
  768. void CGripControl::OnLButtonDblClk(UINT nFlags, CPoint point) 
  769. {
  770. DWORD hitTest = HitTest(point);
  771. switch(hitTest)
  772. {
  773. case GHT_CAPTION:
  774. {
  775. m_pControlBar->ToggleDocking();
  776. }
  777. default:
  778. break;
  779. }
  780. }
  781. void CGripControl::OnLButtonDown(UINT nFlags, CPoint point) 
  782. {
  783. // Make sure if parent is app
  784. // when we click on ControlBar
  785. CWnd* Wnd = GetActiveWindow();
  786. CWnd* frm = AfxGetMainWnd();
  787. if(Wnd != frm)
  788. frm->SetActiveWindow();
  789. DWORD hitTest = HitTest(point);
  790. switch(hitTest)
  791. {
  792. case GHT_CAPTION:
  793. {
  794. CPoint pt = point;
  795. ClientToScreen(&point);
  796. m_pControlBar->StartDrag(point);
  797. return;
  798. }
  799. break;
  800. case GHT_CLOSE:
  801. {
  802. CClientDC dc(this);
  803. DrawFrameControl(dc.m_hDC,
  804. m_rcClose,
  805. DFC_CAPTION,
  806. DFCS_CAPTIONCLOSE | DFCS_PUSHED);
  807. }
  808. break;
  809. case GHT_DOCKBUT:
  810. {
  811. CClientDC dc(this);
  812. DrawFrameControl(dc.m_hDC,
  813. m_rcIcon,
  814. DFC_CAPTION,
  815. DFCS_CAPTIONRESTORE | DFCS_PUSHED);
  816. }
  817. break;
  818. default:
  819. break;
  820. }
  821. SetCapture();
  822. }
  823. void CGripControl::OnLButtonUp(UINT nFlags, CPoint point) 
  824. {
  825. if(this != GetCapture())
  826. return;
  827. DWORD hitTest = HitTest(point);
  828. switch(hitTest)
  829. {
  830. case GHT_CAPTION:
  831. {
  832. }
  833. break;
  834. case GHT_CLOSE:
  835. {
  836. CClientDC dc(this);
  837. DrawFrameControl(dc.m_hDC,
  838. m_rcClose,
  839. DFC_CAPTION,
  840. DFCS_CAPTIONCLOSE);
  841. ReleaseCapture();
  842. m_pControlBar->SendMessage(WM_CLOSE, 0,0);
  843. }
  844. break;
  845. case GHT_DOCKBUT:
  846. {
  847. CClientDC dc(this);
  848. DrawFrameControl(dc.m_hDC,
  849. m_rcIcon,
  850. DFC_CAPTION,
  851. DFCS_CAPTIONRESTORE);
  852. ReleaseCapture();
  853. m_pControlBar->ToggleDocking();
  854. return;
  855. }
  856. default:
  857. break;
  858. }
  859. ReleaseCapture();
  860. }
  861. void CGripControl::OnMouseMove(UINT nFlags, CPoint point) 
  862. {
  863. if(this != GetCapture())
  864. return;
  865. DWORD hitTest = HitTest(point);
  866. if(hitTest == m_prevHitTest)
  867. return;
  868. m_prevHitTest = hitTest;
  869. CClientDC dc(this);
  870. switch(hitTest)
  871. {
  872. case GHT_CAPTION:
  873. {
  874. DrawFrameControl(dc.m_hDC,
  875. m_rcClose,
  876. DFC_CAPTION,
  877. DFCS_CAPTIONCLOSE);
  878. DrawFrameControl(dc.m_hDC,
  879. m_rcIcon,
  880. DFC_CAPTION,
  881. DFCS_CAPTIONRESTORE);
  882. }
  883. break;
  884. case GHT_CLOSE:
  885. {
  886. DrawFrameControl(dc.m_hDC,
  887. m_rcClose,
  888. DFC_CAPTION,
  889. DFCS_CAPTIONCLOSE | DFCS_PUSHED);
  890. }
  891. break;
  892. case GHT_DOCKBUT:
  893. {
  894. CClientDC dc(this);
  895. DrawFrameControl(dc.m_hDC,
  896. m_rcIcon,
  897. DFC_CAPTION,
  898. DFCS_CAPTIONRESTORE | DFCS_PUSHED);
  899. }
  900. default:
  901. break;
  902. }
  903. }
  904. void CGripControl::OnPaint() 
  905. {
  906. CPaintDC dc(this); // device context for painting
  907. OnNcDraw(&dc);
  908. }
  909. BOOL CGripControl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
  910. {
  911. ::SetCursor((HCURSOR) ::LoadCursor(NULL, IDC_ARROW));
  912. return TRUE;
  913. }
  914. void CGripControl::OnSettingChange(UINT uFlags, LPCTSTR lpszSection) 
  915. {
  916. OnSysColorChange();
  917. return;
  918. }
  919. void CGripControl::OnSysColorChange() 
  920. {
  921. Abolish();
  922. }
  923. /////////////////////////////////////////////////////////////////// 
  924. // Class CExDocContext 
  925. // 
  926. // Class provides new behaviour for drawing the 
  927. // track frame when floating 
  928. // Rem out the code inside AdjustWindowForFloat() 
  929. // to see original behaviour 
  930. /////////////////////////////////////////////////////////////////// 
  931. // Local defines
  932. // Gain Access to MFC private DATA 
  933. // Could change without warning 
  934. #undef AFX_DATA 
  935. #define AFX_DATA AFX_CORE_DATA 
  936. extern AFX_DATA AUX_DATA afxData; 
  937. // Macros from orginal DockCont.cpp 
  938. #define HORZF(dw) (dw & CBRS_ORIENT_HORZ) 
  939. #define VERTF(dw) (dw & CBRS_ORIENT_VERT) 
  940. // Local functions
  941. // Function from original DockCont.cpp 
  942. static void AdjustRectangle(CRect& rect, CPoint pt) 
  943.  int nXOffset = (pt.x < rect.left) ? (pt.x - rect.left) : 
  944.      (pt.x > rect.right) ? (pt.x - rect.right) : 0; 
  945.  int nYOffset = (pt.y < rect.top) ? (pt.y - rect.top) : 
  946.      (pt.y > rect.bottom) ? (pt.y - rect.bottom) : 0; 
  947.  rect.OffsetRect(nXOffset, nYOffset); 
  948. ////////////////////////////////////////////////////////////////////// 
  949. // Construction/Destruction 
  950. ////////////////////////////////////////////////////////////////////// 
  951. CExDockContext::CExDockContext(CControlBar* pBar) : CDockContext(pBar) 
  952.      // Default constructor passes control object 
  953.      // to base class 
  954. CExDockContext::~CExDockContext() 
  955. void CExDockContext::StartDrag(CPoint pt) 
  956.      ASSERT_VALID(m_pBar); 
  957.  m_bDragging = TRUE; 
  958.      InitLoop(); 
  959.      if (m_pBar->m_dwStyle & CBRS_SIZE_DYNAMIC) 
  960.      { 
  961.           // get true bar size (including borders) 
  962.           CRect rect; 
  963.           m_pBar->GetWindowRect(rect); 
  964.           // This is our added funtionality 
  965.           // This overridable allows you 
  966.           // to adjust the window rect so that 
  967.           // you can hide controls like a caption 
  968.           // bar from view 
  969.           AdjustWindowForFloat(rect); 
  970.           m_ptLast = pt; 
  971.           CSize sizeHorz = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK); 
  972.           CSize sizeVert = m_pBar->CalcDynamicLayout(0, LM_VERTDOCK); 
  973.           CSize sizeFloat = m_pBar->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH); 
  974.           m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz); 
  975.           m_rectDragVert = CRect(rect.TopLeft(), sizeVert); 
  976.           // calculate frame dragging rectangle 
  977.           m_rectFrameDragHorz = CRect(rect.TopLeft(), sizeFloat); 
  978.           m_rectFrameDragVert = CRect(rect.TopLeft(), sizeFloat); 
  979. #ifdef _MAC 
  980.           CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz, 
  981.                WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX); 
  982.           CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert, 
  983.                WS_THICKFRAME | WS_CAPTION, WS_EX_FORCESIZEBOX); 
  984. #else 
  985.           CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz); 
  986.           CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert); 
  987. #endif 
  988.           m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
  989.           m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
  990.      } 
  991.      else if (m_pBar->m_dwStyle & CBRS_SIZE_FIXED) 
  992.      { 
  993.           // get true bar size (including borders) 
  994.           CRect rect; 
  995.           m_pBar->GetWindowRect(rect); 
  996.           // This is our added funtionality 
  997.           // This overridable allows you 
  998.           // to adjust the window rect so that 
  999.           // you can hide controls like a caption 
  1000.           // bar from view 
  1001.           AdjustWindowForFloat(rect); 
  1002.           m_ptLast = pt; 
  1003.           CSize sizeHorz = m_pBar->CalcDynamicLayout(-1, LM_HORZ | LM_HORZDOCK); 
  1004.           CSize sizeVert = m_pBar->CalcDynamicLayout(-1, LM_VERTDOCK); 
  1005.           // calculate frame dragging rectangle 
  1006.           m_rectFrameDragHorz = m_rectDragHorz = CRect(rect.TopLeft(), sizeHorz); 
  1007.           m_rectFrameDragVert = m_rectDragVert = CRect(rect.TopLeft(), sizeVert); 
  1008.           CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz); 
  1009.           CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert); 
  1010.           m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
  1011.           m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
  1012.      } 
  1013.      else 
  1014.      { 
  1015.           // get true bar size (including borders) 
  1016.           CRect rect; 
  1017.           m_pBar->GetWindowRect(rect); 
  1018.           // This is our added funtionality 
  1019.           // This overridable allows you 
  1020.           // to adjust the window rect so that 
  1021.           // you can hide controls like a caption 
  1022.           // bar from view 
  1023.           AdjustWindowForFloat(rect); 
  1024.           m_ptLast = pt; 
  1025.           BOOL bHorz = HORZF(m_dwStyle); 
  1026.           DWORD dwMode = !bHorz ? (LM_HORZ | LM_HORZDOCK) : LM_VERTDOCK; 
  1027.           CSize size = m_pBar->CalcDynamicLayout(-1, dwMode); 
  1028.           // calculate inverted dragging rect 
  1029.           if (bHorz) 
  1030.           { 
  1031.                m_rectDragHorz = rect; 
  1032.                m_rectDragVert = CRect(CPoint(pt.x - rect.Height()/2, rect.top), size); 
  1033.           } 
  1034.           else // vertical orientation 
  1035.           { 
  1036.                m_rectDragVert = rect; 
  1037.                m_rectDragHorz = CRect(CPoint(rect.left, pt.y - rect.Width()/2), size); 
  1038.           } 
  1039.           // calculate frame dragging rectangle 
  1040.           m_rectFrameDragHorz = m_rectDragHorz; 
  1041.           m_rectFrameDragVert = m_rectDragVert; 
  1042.           CMiniFrameWnd::CalcBorders(&m_rectFrameDragHorz); 
  1043.           CMiniFrameWnd::CalcBorders(&m_rectFrameDragVert); 
  1044.           m_rectFrameDragHorz.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
  1045.           m_rectFrameDragVert.InflateRect(-afxData.cxBorder2, -afxData.cyBorder2); 
  1046.      } 
  1047.      // adjust rectangles so that point is inside 
  1048.      AdjustRectangle(m_rectDragHorz, pt); 
  1049.      AdjustRectangle(m_rectDragVert, pt); 
  1050.      AdjustRectangle(m_rectFrameDragHorz, pt); 
  1051.      AdjustRectangle(m_rectFrameDragVert, pt); 
  1052.      // initialize tracking state and enter tracking loop 
  1053.      m_dwOverDockStyle = CanDock(); 
  1054.      Move(pt);   // call it here to handle special keys 
  1055.  // Here we call our new function Tracking
  1056.      Tracking(); 
  1057.   
  1058. void CExDockContext::AdjustWindowForFloat(CRect& rect) 
  1059.      // Overridable to adjust floating frame 
  1060.      // size for added controls you do not 
  1061.      // want to see in the floating state 
  1062.      // Default behavior is to move window 
  1063.      // up enough to hide the caption bar 
  1064.      if(m_pBar->IsFloating()) 
  1065.            rect.top += (GetSystemMetrics(SM_CYCAPTION) 
  1066.                + GetSystemMetrics(SM_CYFRAME)); 
  1067. BOOL CExDockContext::Tracking()
  1068. {
  1069. // don't handle if capture already set
  1070. if (::GetCapture() != NULL)
  1071. return FALSE;
  1072. // set capture to the window which received this message
  1073. m_pBar->SetCapture();
  1074. ASSERT(m_pBar == CWnd::GetCapture());
  1075. #ifndef _MAC
  1076. // get messages until capture lost or cancelled/accepted
  1077. while (CWnd::GetCapture() == m_pBar)
  1078. {
  1079. MSG msg;
  1080. if (!::GetMessage(&msg, NULL, 0, 0))
  1081. {
  1082. AfxPostQuitMessage(msg.wParam);
  1083. break;
  1084. }
  1085. switch (msg.message)
  1086. {
  1087. case WM_NCLBUTTONUP:
  1088. m_pBar->SendMessage(WM_NCLBUTTONUP,
  1089. msg.wParam,
  1090. msg.lParam);
  1091. return TRUE;
  1092. case WM_LBUTTONUP:
  1093. if (m_bDragging)
  1094. EndDrag();
  1095. else
  1096. EndResize();
  1097. return TRUE;
  1098. case WM_MOUSEMOVE:
  1099. if (m_bDragging)
  1100. Move(msg.pt);
  1101. else
  1102. Stretch(msg.pt);
  1103. break;
  1104. case WM_KEYUP:
  1105. if (m_bDragging)
  1106. OnKey((int)msg.wParam, FALSE);
  1107. break;
  1108. case WM_KEYDOWN:
  1109. if (m_bDragging)
  1110. OnKey((int)msg.wParam, TRUE);
  1111. if (msg.wParam == VK_ESCAPE)
  1112. {
  1113. CancelLoop();
  1114. return FALSE;
  1115. }
  1116. break;
  1117. case WM_RBUTTONDOWN:
  1118. CancelLoop();
  1119. return FALSE;
  1120. // just dispatch rest of the messages
  1121. default:
  1122. DispatchMessage(&msg);
  1123. break;
  1124. }
  1125. }
  1126. #else
  1127. Point   ptCur = {0};
  1128. // get messages until capture lost or cancelled/accepted
  1129. while (CWnd::GetCapture() == m_pBar)
  1130. {
  1131. EventRecord     er;
  1132. if (OSEventAvail(everyEvent, &er))
  1133. {
  1134. GetNextEvent(everyEvent, &er);
  1135. switch (er.what)
  1136. {
  1137. case mouseUp:
  1138. if (m_bDragging)
  1139. EndDrag();
  1140. else
  1141. EndResize();
  1142. return TRUE;
  1143. case keyDown:
  1144. case keyUp:
  1145. case autoKey:
  1146. case app2Evt:
  1147. {
  1148. MSG     msg;
  1149. if (WrapEvent(&er, &msg, PM_REMOVE))
  1150. {
  1151. if (m_bDragging)
  1152. OnKey((int)msg.wParam, msg.message == WM_KEYDOWN);
  1153. if (msg.message == WM_KEYUP && msg.wParam == VK_ESCAPE)
  1154. {
  1155. CancelLoop();
  1156. return FALSE;
  1157. }
  1158. }
  1159. break;
  1160. }
  1161. default:
  1162. break;
  1163. }
  1164. }
  1165. else
  1166. {
  1167. if (!EqualPt(er.where, ptCur))
  1168. {
  1169. POINT pt = {er.where.h, er.where.v};
  1170. if (m_bDragging)
  1171. Move(pt);
  1172. else
  1173. Stretch(pt);
  1174. }
  1175. }
  1176. }
  1177. #endif
  1178. CancelLoop();
  1179. return FALSE;
  1180. }