EGDockingPane.cpp
Upload User: kairuinn
Upload Date: 2009-02-07
Package Size: 2922k
Code Size: 65k
Category:

Graph program

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #include "EGDocking.h"
  3. #include "NewTheme.h"
  4. #include "EGMenu.h"
  5. #include <algorithm>
  6. #include <functional>
  7. #define SPLITTER_SIZE 4
  8. #define TABS_BKGND RGB(247,243,233)
  9. #define DM_PANESTATE_CHANGED WM_USER + 1
  10. #define _AfxGetDlgCtrlID(hWnd)          ((UINT)(WORD)::GetDlgCtrlID(hWnd))
  11. /////////////////////////////////////////////////////////////////////////
  12. // functors
  13. class HotPaneButton {
  14. int m_nX;
  15. public:
  16. HotPaneButton( int x ) {
  17. m_nX = x;
  18. }
  19. bool operator() ( CEGDockingTabBtn btn ) { 
  20. return ( btn.m_nLeft <= m_nX && m_nX <= btn.m_nLeft + btn.m_nWidth );
  21. }
  22. };
  23. class MatchPaneButton {
  24. CEGDockingPane * m_pPane;
  25. public:
  26. MatchPaneButton( CEGDockingPane * pPane ) {
  27. m_pPane = pPane;
  28. }
  29. bool operator() ( CEGDockingTabBtn btn ) { 
  30. return btn.m_pPane == m_pPane; 
  31. }
  32. };
  33. // stub
  34. int CALLBACK EnumFontFamProc(ENUMLOGFONT FAR *lpelf,
  35.  NEWTEXTMETRIC FAR *lpntm,
  36.  int FontType,
  37.  LPARAM lParam)
  38. {
  39. UNUSED_ALWAYS(lpelf);
  40. UNUSED_ALWAYS(lpntm);
  41. UNUSED_ALWAYS(FontType);
  42. UNUSED_ALWAYS(lParam);
  43. return 0;
  44. }
  45. /////////////////////////////////////////////////////////////////////////
  46. // CEGDockingPane
  47. CEGDockingPane::CEGDockingPane() {
  48. m_pDockingBar = NULL;
  49. m_pszTitle = NULL;
  50. m_bHidden = FALSE;
  51. m_clrColor = themeData.GetNewColor();
  52. // Caption height
  53. m_cyCaption = ::GetSystemMetrics(SM_CYSMCAPTION);
  54. m_pRemovedFromBar = NULL;
  55. }
  56. CEGDockingPane::~CEGDockingPane() {
  57. if ( m_pDockingBar != NULL ) {
  58. m_pDockingBar->RemovePane( this );
  59. if ( m_pDockingBar->IsEmpty() ) 
  60. delete m_pDockingBar;
  61. m_pDockingBar = NULL;
  62. }
  63. if( m_pszTitle != NULL )
  64. free( m_pszTitle );
  65. }
  66. BEGIN_MESSAGE_MAP(CEGDockingPane, CStatic)
  67. ON_NOTIFY( NM_KILLFOCUS, 0, OnKillFocus )
  68. ON_NOTIFY( NM_SETFOCUS, 0, OnSetFocus )
  69. END_MESSAGE_MAP()
  70. BOOL CEGDockingPane::baseCreate( TCHAR* lpszTitle, CSize size, CFrameWnd* pFrame ) {
  71. m_pszTitle = _tcsdup( lpszTitle );
  72. if( !Create( NULL, WS_CHILD /*| WS_BORDER */| WS_CLIPCHILDREN | WS_CLIPSIBLINGS , CRect( CPoint(0,0), size ), pFrame, 0 /* nID */ ) )
  73. return FALSE;
  74. return TRUE;
  75. }
  76. void CEGDockingPane::CreateBar( TCHAR* lpszTitle, CSize size, CFrameWnd* pFrame ) {
  77. m_pDockingBar = new CEGDockingBar( size );
  78. ::SendMessage( pFrame->m_hWnd, DM_DOCKING_BAR, (WPARAM) m_pDockingBar, 0 );
  79. m_pDockingBar->Create( lpszTitle, 0, pFrame, 0 /*nID*/);
  80. m_pDockingBar->AddPane( this );
  81. }
  82. BOOL CEGDockingPane::CreatePane( TCHAR* lpszTitle, CSize size, CFrameWnd* pFrame, CEGDockingPane *pPane, DockType nDockType, CPoint ptFloat ) {
  83. // Create pane
  84. if( !baseCreate( lpszTitle, size, pFrame ) ) {
  85. TRACE1("FAILED to CEGDockingPane::baseCreate("%s",...)", lpszTitle );
  86. return FALSE;
  87. }
  88. if ( !pPane ) {
  89. // dock to client area side
  90. CreateBar( lpszTitle, size, pFrame );
  91. int nSide = 0; 
  92. switch( nDockType ) {
  93. case dctBottom:
  94. nSide = AFX_IDW_DOCKBAR_BOTTOM;
  95. break;
  96. case dctLeft:
  97. nSide = AFX_IDW_DOCKBAR_LEFT;
  98. break;
  99. case dctRight:
  100. nSide = AFX_IDW_DOCKBAR_RIGHT;
  101. break;
  102. case dctTop:
  103. nSide = AFX_IDW_DOCKBAR_TOP;
  104. break;
  105. };
  106. if ( 0 == nSide  ) {
  107. pFrame->FloatControlBar( (CControlBar*)m_pDockingBar, ptFloat );
  108. } else {
  109. pFrame->DockControlBar( (CControlBar*)m_pDockingBar, nSide );
  110. m_pDockingBar->m_pDockContext->m_uMRUDockID = nSide;
  111. }
  112. pFrame->RecalcLayout();
  113. } else if ( pPane && dctTab == nDockType ) {
  114. // append tab to another pane
  115. pPane->AppendTab( this );
  116. m_pDockingBar = pPane->m_pDockingBar;
  117. } else {
  118. // dock to border of another pane
  119. CreateBar( lpszTitle, size, pFrame );
  120. CRect rc;
  121. pPane->m_pDockingBar->GetWindowRect( &rc );
  122. switch( nDockType ) {
  123. case dctBottom:
  124. rc.OffsetRect( 0, 20 );
  125. break;
  126. case dctLeft:
  127. rc.OffsetRect( -20, 0 );
  128. break;
  129. case dctRight:
  130. rc.OffsetRect( 20, 0 );
  131. break;
  132. case dctTop:
  133. rc.OffsetRect( 0, -20 );
  134. break;
  135. };
  136. CDockBar * pDockBar = (CDockBar*)pFrame->GetControlBar(pPane->m_pDockingBar->GetDockBarID());
  137. pDockBar->DockControlBar( m_pDockingBar, &rc);
  138. pFrame->RecalcLayout();
  139. m_pDockingBar->m_pDockContext->m_uMRUDockID = _AfxGetDlgCtrlID(pDockBar->m_hWnd);
  140. }
  141. return TRUE;
  142. }
  143. DockType GetDropTarget( CPoint pt, CRect rcClient ) {
  144. CRect rcArea;
  145. // trying dock on top
  146. rcArea = rcClient;
  147. rcArea.bottom = rcArea.top + min( rcClient.Height(), DROP_AREA_SIZE );
  148. if ( rcArea.PtInRect( pt ) )
  149. return dctTop; // can dock on top
  150. // trying dock on bottom
  151. rcArea = rcClient;
  152. rcArea.top = rcArea.bottom - min( rcClient.Height(), DROP_AREA_SIZE );
  153. if ( rcArea.PtInRect( pt ) )
  154. return dctBottom; // can dock on bottom
  155. // trying dock on left
  156. rcArea = rcClient;
  157. rcArea.right = rcArea.left + min( rcClient.Width(), DROP_AREA_SIZE );
  158. if ( rcArea.PtInRect( pt ) )
  159. return dctLeft; // can dock on bottom
  160. // trying dock on right
  161. rcArea = rcClient;
  162. rcArea.left = rcArea.right - min( rcClient.Width(), DROP_AREA_SIZE );
  163. if ( rcArea.PtInRect( pt ) )
  164. return dctRight; // can dock on bottom
  165. return dctFloat;
  166. }
  167. CRect GetDropRect( DockType dt, CRect rcWindow, int nSize ) {
  168. CRect rcResult = rcWindow; // default for dctTab;
  169. switch( dt ) {
  170. case dctBottom:
  171. rcResult.top = rcResult.bottom - min( rcWindow.Height(), nSize );
  172. break;
  173. case dctLeft:
  174. rcResult.right = rcResult.left + min( rcWindow.Width(), nSize );
  175. break;
  176. case dctRight:
  177. rcResult.left = rcResult.right - min( rcWindow.Width(), nSize );
  178. break;
  179. case dctTop:
  180. rcResult.bottom = rcResult.top + min( rcWindow.Height(), nSize );
  181. break;
  182. };
  183. return rcResult;
  184. }
  185. DockType CEGDockingPane::GetDropTarget( CPoint pt /* client coordinates */ ) {
  186. CRect rcClient;
  187. GetWindowRect( &rcClient );
  188. rcClient.OffsetRect( -rcClient.TopLeft() );
  189. return ::GetDropTarget( pt, rcClient );
  190. }
  191. CRect CEGDockingPane::GetDropRect( DockType dt ) {
  192. CRect rcWindow;
  193. GetParent()->GetWindowRect( &rcWindow );
  194. return ::GetDropRect( dt, rcWindow, DOCK_AREA_SIZE );
  195. }
  196. void CEGDockingPane::CreateDragBar( CPoint pt, CSize size, double xScale ) {
  197. CFrameWnd * pFrame = GetTopLevelFrame();
  198. CreateBar( GetTitle(), size, pFrame );
  199. pFrame->FloatControlBar( m_pDockingBar, pt );
  200. m_pDockingBar->ShowBar( FALSE );
  201. reinterpret_cast<CEGDockingContext*>( m_pDockingBar->m_pDockContext )->StartDrag( pt, xScale, 0 );
  202. }
  203. void CEGDockingPane::AppendTab( CEGDockingPane* pPane ) {
  204. ASSERT( m_pDockingBar != NULL );
  205. m_pDockingBar->AddPane( pPane );
  206. }
  207. int CEGDockingPane::Width() {
  208. return m_pDockingBar->Width();
  209. }
  210. int CEGDockingPane::Height() { 
  211. return m_pDockingBar->Height();
  212. }
  213. void CEGDockingPane::RestoreParent() {
  214. SetParent( m_pDockingBar );
  215. }
  216. void CEGDockingPane::RemoveFromBorder( CEGDockBorder * pBorder, BOOL bShow ) {
  217. ASSERT( pBorder != NULL );
  218. SetParent( m_pDockingBar );
  219. m_pDockingBar->ActivatePane( this );
  220. m_pDockingBar->RemoveFromBorder( pBorder, bShow );
  221. }
  222. void CEGDockingPane::OnKillFocus( NMHDR* pNMHDR, LRESULT* pResult ) {
  223. HWND hFocus = ::GetFocus();
  224. if ( hFocus && !::IsChild( hFocus, GetSafeHwnd() ) )
  225. GetParent()->PostMessage( WM_KILLFOCUS, (WPARAM)hFocus, 0 );
  226. }
  227. void CEGDockingPane::OnSetFocus( NMHDR* pNMHDR, LRESULT* pResult ) {
  228. GetParent()->PostMessage( WM_FOCUS_CHANGED, 0, 0 );
  229. }
  230. void CEGDockingPane::Show() {
  231. if ( m_pDockingBar->IsFlyOutMode() && m_bHidden ) {
  232. m_pDockingBar->m_pBorder->AddButton( DRAWBTNSTYLE_GROUP, this );
  233. m_bHidden = FALSE;
  234. //m_pDockingBar->m_pBorder->FlyOutPane( this );
  235. m_pDockingBar->GetTopLevelFrame()->RecalcLayout();
  236. } else if ( m_bHidden ) {
  237. m_bHidden = FALSE;
  238. m_pDockingBar->PostMessage( DM_PANESTATE_CHANGED, (WPARAM)this, 1 );
  239. }
  240. }
  241. void CEGDockingPane::Hide( BOOL bNotifyContainer ) {
  242. if ( m_pDockingBar->IsFlyOutMode() && !m_bHidden ) {
  243. m_pDockingBar->m_pBorder->FlyDownPane( this );
  244. m_pDockingBar->m_pBorder->RemoveButton( this );
  245. m_bHidden = TRUE;
  246. m_pDockingBar->GetTopLevelFrame()->DelayRecalcLayout();
  247. } else if ( !m_bHidden ) {
  248. m_bHidden = TRUE;
  249. if ( bNotifyContainer )
  250. m_pDockingBar->PostMessage( DM_PANESTATE_CHANGED, (WPARAM)this, 0 );
  251. }
  252. }
  253. void CEGDockingPane::ToggleVisible() {
  254. if ( !m_bHidden ) {
  255. Hide();
  256. } else {
  257. Show();
  258. }
  259. }
  260. BOOL CEGDockingPane::SetIcon( UINT nIDResource, HINSTANCE hInst ) {
  261. return m_bmpIcon.LoadBitmap( nIDResource, hInst );
  262. }
  263. BOOL CEGDockingPane::SetIcon( LPCTSTR lpszResourceName, HINSTANCE hInst ) {
  264. return m_bmpIcon.LoadBitmap( lpszResourceName, hInst );
  265. }
  266. /////////////////////////////////////////////////////////////////////////
  267. // CEGDockingControlPane
  268. CEGDockingControlPane::CEGDockingControlPane(void)
  269. {
  270. m_hWndControl = NULL;
  271. m_nID = 0;
  272. }
  273. CEGDockingControlPane::~CEGDockingControlPane(void)
  274. {
  275. }
  276. HWND CEGDockingControlPane::CreateControl() {
  277. return NULL;
  278. }
  279. BOOL CEGDockingControlPane::InitControl() {
  280. return TRUE;
  281. }
  282. BEGIN_MESSAGE_MAP(CEGDockingControlPane, CEGDockingPane)
  283. ON_WM_CREATE()
  284. ON_WM_SIZE()
  285. // ON_MESSAGE(WM_USER,OnKickIdle)
  286. END_MESSAGE_MAP()
  287. int CEGDockingControlPane::OnCreate( LPCREATESTRUCT lpCreateStruct ) {
  288. if( CEGDockingPane::OnCreate( lpCreateStruct) ) {
  289. TRACE0("Cannot create docking pane");
  290. return -1;
  291. }
  292. m_hWndControl = CreateControl();
  293. if ( !m_hWndControl ) {
  294. TRACE0("Cannot create docking control");
  295. return -1;
  296. }
  297. if ( !InitControl() ) {
  298. TRACE0("Cannot initialize docking control");
  299. return -1;
  300. }
  301. if ( 0 == m_nID ) 
  302. return 0;
  303.   if (!m_wndToolBar.CreateEx(this, TBSTYLE_AUTOSIZE|TBSTYLE_FLAT|TBSTYLE_LIST, WS_CHILD | WS_VISIBLE | CBRS_TOP
  304.     |CBRS_TOOLTIPS | CBRS_SIZE_DYNAMIC,CRect(1,1,1,1),AFX_IDW_TOOLBAR) ||
  305.     !m_wndToolBar.LoadToolBar(m_nID))
  306.   {
  307.     TRACE0("Failed to create toolbarn");
  308.     return -1;      // fail to create
  309.   }
  310.   // Prevent the toolbarbutton to be too big after resizing TaskBar!
  311.   for (int n=0;n<m_wndToolBar.GetCount();n++)
  312.   {
  313.     DWORD dwStyle = m_wndToolBar.GetButtonStyle(n);
  314.     if( !(dwStyle&TBBS_SEPARATOR) )
  315.     {
  316.        m_wndToolBar.SetButtonStyle(n,dwStyle|TBBS_AUTOSIZE);
  317.     }
  318.   }
  319.   // adjust border
  320.   switch (CEGMenu::GetMenuDrawMode())
  321.   {
  322.   case CEGMenu::STYLE_COLORFUL_NOBORDER:
  323.   case CEGMenu::STYLE_COLORFUL:
  324.   case CEGMenu::STYLE_XP_2003_NOBORDER:
  325.   case CEGMenu::STYLE_XP_2003:
  326.   case CEGMenu::STYLE_ICY:
  327.   case CEGMenu::STYLE_ICY_NOBORDER:
  328.     m_wndToolBar.SetBorders(0,0,0,4);
  329.     break;
  330.   default:
  331.     m_wndToolBar.SetBorders(0,0,0,0);
  332.     break;
  333.   }
  334.   CRect rcClientStart;
  335. CRect rcClientNow;
  336. GetClientRect(rcClientStart);
  337. RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0,reposQuery,rcClientNow);
  338. // Set the icon for this dialog.  The framework does this automatically
  339. CPoint ptoffset(rcClientNow.left - rcClientStart.left, rcClientNow.top - rcClientStart.top); 
  340. CRect  rcchild;
  341. CWnd* pwndchild = GetWindow(GW_CHILD);
  342. while (pwndchild)
  343. {      
  344. pwndchild->GetWindowRect(rcchild);
  345. ScreenToClient(rcchild);
  346. rcchild.OffsetRect(ptoffset);
  347. pwndchild->MoveWindow(rcchild, FALSE);
  348. pwndchild = pwndchild->GetNextWindow();
  349. }
  350. // adjust the dialog window dimensions
  351. CRect rcwindow;
  352. GetWindowRect(rcwindow);
  353. rcwindow.right += rcClientStart.Width() - rcClientNow.Width();
  354. rcwindow.bottom += rcClientStart.Height() - rcClientNow.Height();
  355. MoveWindow(rcwindow, FALSE); // and position the control bars
  356. RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
  357. return 0;
  358. }
  359. void CEGDockingControlPane::OnSize( UINT nType, int cx, int cy ) {
  360. CEGDockingPane::OnSize( nType, cx, cy );
  361. if ( 0 != m_nID ) 
  362. RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
  363. if ( m_hWndControl ) {
  364. int nDelta = 0;
  365. if ( 0 != m_nID ) {
  366. CRect rc;
  367. m_wndToolBar.GetWindowRect( &rc );
  368. nDelta = rc.Height();
  369. }
  370. ::MoveWindow( m_hWndControl, 0, 0 + nDelta  , cx, cy - nDelta, TRUE );
  371. }
  372. }
  373. void CEGDockingControlPane::SetResourceID( int nID ) {
  374. m_nID = nID;
  375. }
  376. class CToolCmdUI : public CCmdUI 
  377. {    
  378.   virtual void Enable(BOOL bEnable) 
  379.   {
  380.     ::SendMessage(m_pOther->GetSafeHwnd(), TB_ENABLEBUTTON, m_nID , MAKELPARAM(bEnable, 0));
  381.   }
  382.   virtual void SetCheck(int nCheck = 1)
  383.   { 
  384.     ::SendMessage(m_pOther->GetSafeHwnd(), TB_CHECKBUTTON, m_nID, MAKELPARAM(nCheck, 0)); 
  385.   }
  386. };
  387. /*LRESULT CEGDockingControlPane::OnKickIdle(WPARAM wp, LPARAM lp)
  388. {
  389.   UNREFERENCED_PARAMETER(wp);
  390.   UNREFERENCED_PARAMETER(lp);
  391. if ( 0 == m_nID ) return false;
  392.   CToolCmdUI cmdUI;
  393.   cmdUI.m_pOther = &m_wndToolBar;
  394.   UINT indexMax = m_wndToolBar.GetToolBarCtrl().GetButtonCount();
  395.   cmdUI.m_nIndexMax = indexMax;
  396.   for (UINT i = 0; i < indexMax; i++) 
  397.   {
  398.     if (m_wndToolBar.GetButtonStyle(i) & TBSTYLE_SEP)
  399.       continue;
  400.     cmdUI.m_nIndex = i;
  401.     cmdUI.m_nID = m_wndToolBar.GetItemID(i);
  402.     cmdUI.m_pMenu = NULL;
  403.     cmdUI.DoUpdate(this,FALSE);
  404.   }
  405. return false;
  406.   //UpdateDialogControls(this,FALSE);
  407.   //AfxCallWndProc(this, m_hWnd,WM_IDLEUPDATECMDUI, (WPARAM)TRUE, 0);
  408.   //SendMessageToDescendants(WM_IDLEUPDATECMDUI,(WPARAM)TRUE, 0, TRUE, TRUE);
  409.   //return 0;
  410. */
  411. /////////////////////////////////////////////////////////////////////////
  412. // CEGToolBaredPane
  413. /*
  414. BEGIN_MESSAGE_MAP(CEGToolBaredPane, CEGDockingPane)
  415. ON_WM_CREATE()
  416. ON_WM_SIZE()
  417. ON_MESSAGE(WM_USER,OnKickIdle)
  418. END_MESSAGE_MAP()
  419. int CEGToolBaredPane::OnCreate( LPCREATESTRUCT lpCreateStruct ) {
  420. if( CEGDockingPane::OnCreate( lpCreateStruct) ) {
  421. TRACE0("Cannot create docking pane");
  422. return -1;
  423. }
  424. if ( 0 == m_nID ) 
  425. return 0;
  426.   if (!m_wndToolBar.CreateEx(this, TBSTYLE_AUTOSIZE|TBSTYLE_FLAT|TBSTYLE_LIST, WS_CHILD | WS_VISIBLE | CBRS_TOP
  427.     |CBRS_TOOLTIPS | CBRS_SIZE_DYNAMIC,CRect(1,1,1,1),AFX_IDW_TOOLBAR) ||
  428.     !m_wndToolBar.LoadToolBar(m_nID))
  429.   {
  430.     TRACE0("Failed to create toolbarn");
  431.     return -1;      // fail to create
  432.   }
  433.   // Prevent the toolbarbutton to be too big after resizing TaskBar!
  434.   for (int n=0;n<m_wndToolBar.GetCount();n++)
  435.   {
  436.     DWORD dwStyle = m_wndToolBar.GetButtonStyle(n);
  437.     if( !(dwStyle&TBBS_SEPARATOR) )
  438.     {
  439.        m_wndToolBar.SetButtonStyle(n,dwStyle|TBBS_AUTOSIZE);
  440.     }
  441.   }
  442.   // adjust border
  443.   switch (CEGMenu::GetMenuDrawMode())
  444.   {
  445.   case CEGMenu::STYLE_COLORFUL_NOBORDER:
  446.   case CEGMenu::STYLE_COLORFUL:
  447.   case CEGMenu::STYLE_XP_2003_NOBORDER:
  448.   case CEGMenu::STYLE_XP_2003:
  449.   case CEGMenu::STYLE_ICY:
  450.   case CEGMenu::STYLE_ICY_NOBORDER:
  451.     m_wndToolBar.SetBorders(0,0,0,4);
  452.     break;
  453.   default:
  454.     m_wndToolBar.SetBorders(0,0,0,0);
  455.     break;
  456.   }
  457.   CRect rcClientStart;
  458. CRect rcClientNow;
  459. GetClientRect(rcClientStart);
  460. RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0,reposQuery,rcClientNow);
  461. // Set the icon for this dialog.  The framework does this automatically
  462. CPoint ptoffset(rcClientNow.left - rcClientStart.left, rcClientNow.top - rcClientStart.top); 
  463. CRect  rcchild;
  464. CWnd* pwndchild = GetWindow(GW_CHILD);
  465. while (pwndchild)
  466. {      
  467. pwndchild->GetWindowRect(rcchild);
  468. ScreenToClient(rcchild);
  469. rcchild.OffsetRect(ptoffset);
  470. pwndchild->MoveWindow(rcchild, FALSE);
  471. pwndchild = pwndchild->GetNextWindow();
  472. }
  473. // adjust the dialog window dimensions
  474. CRect rcwindow;
  475. GetWindowRect(rcwindow);
  476. rcwindow.right += rcClientStart.Width() - rcClientNow.Width();
  477. rcwindow.bottom += rcClientStart.Height() - rcClientNow.Height();
  478. MoveWindow(rcwindow, FALSE); // and position the control bars
  479. RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
  480. return 0;
  481. }
  482. void CEGToolBaredPane::OnSize( UINT nType, int cx, int cy ) {
  483. CEGDockingPane::OnSize( nType, cx, cy );
  484. if ( 0 != m_nID ) 
  485. RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);
  486. }
  487. void CEGToolBaredPane::SetResourceID( int nID ) {
  488. m_nID = nID;
  489. }
  490. LRESULT CEGToolBaredPane::OnKickIdle(WPARAM wp, LPARAM lp)
  491. {
  492.   UNREFERENCED_PARAMETER(wp);
  493.   UNREFERENCED_PARAMETER(lp);
  494. if ( 0 == m_nID ) return false;
  495.   CToolCmdUI cmdUI;
  496.   cmdUI.m_pOther = &m_wndToolBar;
  497.   UINT indexMax = m_wndToolBar.GetToolBarCtrl().GetButtonCount();
  498.   cmdUI.m_nIndexMax = indexMax;
  499.   for (UINT i = 0; i < indexMax; i++) 
  500.   {
  501.     if (m_wndToolBar.GetButtonStyle(i) & TBSTYLE_SEP)
  502.       continue;
  503.     cmdUI.m_nIndex = i;
  504.     cmdUI.m_nID = m_wndToolBar.GetItemID(i);
  505.     cmdUI.m_pMenu = NULL;
  506.     cmdUI.DoUpdate(this,FALSE);
  507.   }
  508. return false;
  509.   //UpdateDialogControls(this,FALSE);
  510.   //AfxCallWndProc(this, m_hWnd,WM_IDLEUPDATECMDUI, (WPARAM)TRUE, 0);
  511.   //SendMessageToDescendants(WM_IDLEUPDATECMDUI,(WPARAM)TRUE, 0, TRUE, TRUE);
  512.   //return 0;
  513. */
  514. /////////////////////////////////////////////////////////////////////////
  515. // CEGDockingBar
  516. IMPLEMENT_DYNAMIC(CEGDockingBar, CControlBar);
  517. CEGDockingBar::CEGDockingBar( CSize size )
  518. {
  519. m_szMinHorz = CSize(33, 32);
  520. m_szMinVert = CSize(33, 32);
  521. m_szMinFloat = CSize(37, 32);
  522. m_szHorz = size;
  523. m_szVert = size;
  524. m_szFloat = CSize( size.cx, size.cx );
  525. m_bTracking = FALSE;
  526. m_bKeepSize = FALSE;
  527. m_bParentSizing = FALSE;
  528. m_cxEdge = 4;
  529. m_bDragShowContent = FALSE;
  530. m_nDockBarID = 0;
  531. m_dwPaneStyle = 0;
  532. m_cyCaption = 16;
  533. m_cyTabs = 25;
  534. m_bActive = FALSE;
  535. m_bAutoHidePinned = FALSE;
  536. m_bClosePressed = FALSE;
  537. m_bCloseHover = FALSE;
  538. m_bPinPressed = FALSE;
  539. m_bPinHover = FALSE;
  540. m_pActivePane = NULL;
  541. m_bFlyOutMode = FALSE;
  542. m_pFrameWnd = NULL;
  543. m_bTabDrag = FALSE;
  544. m_pBorder = NULL;
  545. }
  546. CEGDockingBar::~CEGDockingBar()
  547. {
  548. }
  549. BEGIN_MESSAGE_MAP(CEGDockingBar, CControlBar)
  550. ON_WM_CREATE()
  551. ON_WM_DESTROY()
  552. ON_WM_TIMER()
  553. //ON_WM_PAINT()
  554. ON_WM_NCPAINT()
  555. ON_WM_NCCALCSIZE()
  556. ON_WM_WINDOWPOSCHANGING()
  557. ON_WM_CAPTURECHANGED()
  558. ON_WM_CANCELMODE()
  559. ON_WM_SETTINGCHANGE()
  560. ON_WM_LBUTTONUP()
  561. ON_WM_MOUSEMOVE()
  562. ON_WM_NCLBUTTONDOWN()
  563. ON_WM_NCLBUTTONUP()
  564. ON_WM_NCMOUSEMOVE()
  565. ON_WM_LBUTTONDOWN()
  566. ON_WM_LBUTTONDBLCLK()
  567. ON_WM_RBUTTONDOWN()
  568. ON_WM_NCHITTEST()
  569. ON_WM_CLOSE()
  570. ON_WM_SIZE()
  571. ON_MESSAGE( WM_SETTEXT, OnSetText )
  572. ON_MESSAGE( WM_NCMOUSELEAVE, OnNcMouseLeave )
  573. ON_MESSAGE( DM_PANESTATE_CHANGED, OnPaneStateChanged )
  574. END_MESSAGE_MAP()
  575. BOOL CEGDockingBar::Create(LPCTSTR lpszWindowName, UINT nIconID,
  576.  CWnd* pParentWnd, UINT nID,
  577.  DWORD dwStyle)
  578. {
  579. m_nIconID = nIconID;
  580. // must have a parent
  581. ASSERT_VALID(pParentWnd);
  582. // cannot be both fixed and dynamic
  583. // (CBRS_SIZE_DYNAMIC is used for resizng when floating)
  584. ASSERT (!((dwStyle & CBRS_SIZE_FIXED) &&
  585. (dwStyle & CBRS_SIZE_DYNAMIC)));
  586. m_dwStyle = dwStyle & CBRS_ALL; // save the control bar styles
  587. // register and create the window - skip CControlBar::Create()
  588. CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS,
  589. ::LoadCursor(NULL, IDC_ARROW),
  590. ::GetSysColorBrush(COLOR_BTNFACE), 0);
  591. dwStyle &= ~CBRS_ALL; // keep only the generic window styles
  592. dwStyle |= WS_CLIPCHILDREN; // prevents flashing
  593. if (!CWnd::Create(wndclass, lpszWindowName, dwStyle,
  594. CRect(0, 0, 0, 0), pParentWnd, nID))
  595. return FALSE;
  596. EnableDocking(CBRS_ALIGN_ANY);
  597. return TRUE;
  598. }
  599. /////////////////////////////////////////////////////////////////////////
  600. // CEGDockingBar attributes
  601. DockType CEGDockingBar::GetDropTarget( CPoint ptScreen, CEGDockingPane ** ppPane ) {
  602. *ppPane = NULL;
  603. CRect rcWindow;
  604. GetWindowRect( &rcWindow );
  605. if ( !rcWindow.PtInRect( ptScreen ) )
  606. return dctOutOfBorders;
  607. if ( IsFloating() ) {
  608. *ppPane = m_pActivePane;
  609. return dctTab;
  610. }
  611. CPoint pt = ptScreen;
  612. ScreenToClient( &pt );
  613. CRect rcActivePane;
  614. m_pActivePane->GetWindowRect( &rcActivePane );
  615. ScreenToClient( rcActivePane );
  616. *ppPane = m_pActivePane;
  617. if ( !rcActivePane.PtInRect( pt ) )
  618. return dctTab;
  619. return (*ppPane)->GetDropTarget( pt );
  620. }
  621. CRect CEGDockingBar::GetDropRect( DockType nDockType ) {
  622. CRect rc;
  623. GetWindowRect( &rc ); // default for dctTab
  624. switch ( nDockType ) {
  625. case dctTop:
  626. rc.bottom = rc.top + min( rc.Height(), m_cyCaption * 2 );
  627. break;
  628. case dctBottom:
  629. rc.top = rc.bottom - min( rc.Height(), m_cyCaption * 2 );
  630. break;
  631. case dctLeft:
  632. rc.right = rc.left + min( rc.Width(), m_cyCaption * 2 );
  633. break;
  634. case dctRight:
  635. rc.left = rc.right - min( rc.Width(), m_cyCaption * 2 );
  636. break;
  637. }
  638. return rc;
  639. }
  640. /////////////////////////////////////////////////////////////////////////
  641. // CEGDockingBar operations
  642. void CEGDockingBar::EnableDocking(DWORD dwDockStyle)
  643. {
  644. // must be CBRS_ALIGN_XXX or CBRS_FLOAT_MULTI only
  645. ASSERT((dwDockStyle & ~(CBRS_ALIGN_ANY|CBRS_FLOAT_MULTI)) == 0);
  646. // cannot have the CBRS_FLOAT_MULTI style
  647. ASSERT((dwDockStyle & CBRS_FLOAT_MULTI) == 0);
  648. // the bar must have CBRS_SIZE_DYNAMIC style
  649. ASSERT((m_dwStyle & CBRS_SIZE_DYNAMIC) != 0);
  650. m_dwDockStyle = dwDockStyle;
  651. if (m_pDockContext == NULL)
  652. m_pDockContext = new CEGDockingContext(this);
  653. // permanently wire the bar's owner to its current parent
  654. if (m_hWndOwner == NULL)
  655. m_hWndOwner = ::GetParent(m_hWnd);
  656. }
  657. /////////////////////////////////////////////////////////////////////////
  658. // CEGDockingBar message handlers
  659. int CEGDockingBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  660. {
  661. if (CControlBar::OnCreate(lpCreateStruct) == -1)
  662. return -1;
  663. // query SPI_GETDRAGFULLWINDOWS system parameter
  664. // OnSettingChange() will update m_bDragShowContent
  665. m_bDragShowContent = FALSE;
  666. ::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0,
  667. &m_bDragShowContent, 0);
  668. // Caption height
  669. m_cyCaption = ::GetSystemMetrics(SM_CYSMCAPTION);
  670. // uncomment this line if you want raised borders
  671. //m_dwPaneStyle |= DPS_SHOWEDGES;
  672. SetPaneStyle(m_dwPaneStyle|DPS_SIZECHILD);
  673. // m_tabs.Create( NULL, NULL, WS_CHILD | FTS_ALIGN_BOTTOM, CRect(0,0,0,0), this, 0, NULL ); 
  674. m_nTimer = (UINT)SetTimer( 1, 250, NULL );
  675. return 0;
  676. }
  677. void CEGDockingBar::OnDestroy() {
  678. KillTimer( m_nTimer );
  679. }
  680. LRESULT CEGDockingBar::OnSetText(WPARAM wParam, LPARAM lParam)
  681. {
  682. UNUSED_ALWAYS(wParam);
  683. LRESULT lResult = CWnd::Default();
  684. CFrameWnd * pFrame = GetParentFrame();
  685. if (IsFloating() && pFrame && pFrame->IsKindOf(RUNTIME_CLASS(CMiniDockFrameWnd)))
  686. {
  687. pFrame->SetWindowText( (LPCTSTR) lParam); // update dockbar
  688. pFrame->DelayRecalcLayout(); // refresh miniframe
  689. }
  690. return lResult;
  691. }
  692. const BOOL CEGDockingBar::IsFloating() const
  693. {
  694. return !IsHorzDocked() && !IsVertDocked();
  695. }
  696. const BOOL CEGDockingBar::IsHorzDocked() const
  697. {
  698. return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
  699. m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
  700. }
  701. const BOOL CEGDockingBar::IsVertDocked() const
  702. {
  703. return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
  704. m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
  705. }
  706. const BOOL CEGDockingBar::IsSideTracking() const
  707. {
  708. // don't call this when not tracking
  709. ASSERT(m_bTracking && !IsFloating());
  710. return (m_htEdge == HTLEFT || m_htEdge == HTRIGHT) ?
  711. IsHorzDocked() : IsVertDocked();
  712. }
  713. CSize CEGDockingBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
  714. {
  715. if (bStretch) // the bar is stretched (is not the child of a dockbar)
  716. if (bHorz)
  717. return CSize(32767, m_szHorz.cy);
  718. else
  719. return CSize(m_szVert.cx, 32767);
  720. // dirty cast - we need access to protected CDockBar members
  721. CEGDockSite* pDockBar = reinterpret_cast<CEGDockSite*>( m_pDockBar );
  722. // force imediate RecalcDelayShow() for all sizing bars on the row
  723. // with delayShow/delayHide flags set to avoid IsVisible() problems
  724. CDPArray arrSCBars;
  725. GetRowSizingBars(arrSCBars);
  726. AFX_SIZEPARENTPARAMS layout;
  727. layout.hDWP = pDockBar->m_bLayoutQuery ?
  728. NULL : ::BeginDeferWindowPos(int(arrSCBars.GetSize()));
  729. for (INT_PTR i = 0; i < arrSCBars.GetSize(); i++)
  730. if (arrSCBars[i]->m_nStateFlags & (delayHide|delayShow))
  731. arrSCBars[i]->RecalcDelayShow(&layout);
  732. if (layout.hDWP != NULL)
  733. ::EndDeferWindowPos(layout.hDWP);
  734. // get available length
  735. CRect rc = pDockBar->m_rectLayout;
  736. if (rc.IsRectEmpty())
  737. m_pDockSite->GetClientRect(&rc);
  738. int nLengthTotal = bHorz ? rc.Width() + 2 : rc.Height() - 2;
  739. if (IsVisible() && !IsFloating() &&
  740. m_bParentSizing && arrSCBars[0] == this)
  741. if (NegotiateSpace(nLengthTotal, (bHorz != FALSE)))
  742. AlignControlBars();
  743. m_bParentSizing = FALSE;
  744. if (bHorz)
  745. return CSize(max(m_szMinHorz.cx, m_szHorz.cx),
  746. max(m_szMinHorz.cy, m_szHorz.cy));
  747. return CSize(max(m_szMinVert.cx, m_szVert.cx),
  748. max(m_szMinVert.cy, m_szVert.cy));
  749. }
  750. CSize CEGDockingBar::CalcDynamicLayout(int nLength, DWORD dwMode)
  751. {
  752. if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ?
  753. {
  754. if (nLength == -1)
  755. m_bParentSizing = TRUE;
  756. return CControlBar::CalcDynamicLayout(nLength, dwMode);
  757. }
  758. if (dwMode & LM_MRUWIDTH) return m_szFloat;
  759. if (dwMode & LM_COMMIT) return m_szFloat; // already committed
  760. // check for dialgonal resizing hit test
  761. int nHitTest = m_pDockContext->m_nHitTest;
  762. if (IsFloating() &&
  763. (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT ||
  764. nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT))
  765. {
  766. CPoint ptCursor;
  767. ::GetCursorPos(&ptCursor);
  768. CRect rFrame, rBar;
  769. GetParentFrame()->GetWindowRect(&rFrame);
  770. GetWindowRect(&rBar);
  771. if (nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT)
  772. {
  773. m_szFloat.cx = rFrame.left + rBar.Width() - ptCursor.x;
  774. m_pDockContext->m_rectFrameDragHorz.left = 
  775. min(ptCursor.x, rFrame.left + rBar.Width() - m_szMinFloat.cx);
  776. }
  777. if (nHitTest == HTTOPLEFT || nHitTest == HTTOPRIGHT)
  778. {
  779. m_szFloat.cy = rFrame.top + rBar.Height() - ptCursor.y;
  780. m_pDockContext->m_rectFrameDragHorz.top =
  781. min(ptCursor.y, rFrame.top + rBar.Height() - m_szMinFloat.cy);
  782. }
  783. if (nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT)
  784. m_szFloat.cx = rBar.Width() + ptCursor.x - rFrame.right;
  785. if (nHitTest == HTBOTTOMLEFT || nHitTest == HTBOTTOMRIGHT)
  786. m_szFloat.cy = rBar.Height() + ptCursor.y - rFrame.bottom;
  787. }
  788. else
  789. ((dwMode & LM_LENGTHY) ? m_szFloat.cy : m_szFloat.cx) = nLength;
  790. m_szFloat.cx = max(m_szFloat.cx, m_szMinFloat.cx);
  791. m_szFloat.cy = max(m_szFloat.cy, m_szMinFloat.cy);
  792. return m_szFloat;
  793. }
  794. void CEGDockingBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
  795. {
  796. // force non-client recalc if moved or resized
  797. lpwndpos->flags |= SWP_FRAMECHANGED;
  798. CControlBar::OnWindowPosChanging(lpwndpos);
  799. // find on which side are we docked
  800. m_nDockBarID = GetParent()->GetDlgCtrlID();
  801. if (!IsFloating())
  802. if (lpwndpos->flags & SWP_SHOWWINDOW)
  803. m_bKeepSize = TRUE;
  804. }
  805. /////////////////////////////////////////////////////////////////////////
  806. // Mouse Handling
  807. //
  808. void CEGDockingBar::OnLButtonDown(UINT nFlags, CPoint point)
  809. {
  810. HWND hActiveWnd = ::GetFocus();
  811. if ( hActiveWnd && hActiveWnd !=  m_hWnd && !::IsChild( m_hWnd, hActiveWnd ) ) {
  812. if ( !m_pActivePane ) {
  813. ::SetFocus( m_hWnd );
  814. } else {
  815. HWND hChild = ::GetWindow( m_pActivePane->GetSafeHwnd(), GW_CHILD );
  816. ::SetFocus( hChild != NULL ? hChild : m_hWnd );
  817. }
  818. }
  819. if ( point.y < 0 && -point.y < m_cyCaption ) {
  820. if ( m_rcClose.PtInRect( point ) ) {
  821. SetCapture();
  822. m_bClosePressed = TRUE;
  823. RePaint();
  824. } else if ( m_rcPin.PtInRect( point ) ) {
  825. SetCapture();
  826. m_bPinPressed = TRUE;
  827. RePaint();
  828. }
  829. }
  830. CWnd::OnLButtonDown(nFlags, point);
  831. }
  832. void CEGDockingBar::OnLButtonDblClk(UINT nFlags, CPoint point)
  833. {
  834. if (m_pDockBar != NULL)
  835. {
  836. // not a buttons?
  837. if ( !m_rcClose.PtInRect( point ) && !m_rcPin.PtInRect( point ) ) {
  838. // toggle docking
  839. ASSERT(m_pDockContext != NULL);
  840. m_pDockContext->ToggleDocking();
  841. TRACE0("CEGDockingBar::OnLButtonDblClkrn");
  842. }
  843. }
  844. else {
  845. TRACE0("CEGDockingBar::OnLButtonDblClk - CWnd::OnLButtonDblClkrn");
  846. CWnd::OnLButtonDblClk(nFlags, point);
  847. }
  848. }
  849. void CEGDockingBar::OnNcLButtonDown(UINT nHitTest, CPoint point) 
  850. {
  851. UNUSED_ALWAYS(point);
  852. if (m_bTracking /* || IsFloating() */ )
  853. return;
  854. CPoint ptScreen( point );
  855. ScreenToClient( &point );
  856. point.y -= m_cxEdge;
  857. if ((nHitTest >= HTSIZEFIRST) && (nHitTest <= HTSIZELAST)) {
  858. StartTracking(nHitTest, ptScreen); // sizing edge hit
  859. } else if ( point.y >= m_rcClient.Height() && point.y <= m_rcClient.Height() + m_cyTabs ) {
  860. CEGDockingTabBtnsIt it = find_if( m_lstTabButtons.begin(), m_lstTabButtons.end(), HotPaneButton( point.x ) );
  861. if ( it != m_lstTabButtons.end() && !it->m_pPane->IsHidden() ) {
  862. ActivatePane( it->m_pPane );
  863. m_bTabDrag = TRUE;
  864. m_nTabDragStart = point.x;
  865. // 狸蜩忤痼屐 蝠