StaticTreeCtrl.cpp
上传用户:dengkfang
上传日期:2008-12-30
资源大小:5233k
文件大小:24k
源码类别:

CA认证

开发平台:

Visual C++

  1. // StaticTreeCtrl.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "....minica.h"
  5. #include "StaticTreeCtrl.h"
  6. //#include "ContextMenu.h"
  7. //#include "DLG_TreeNodeText.h"
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13. /////////////////////////////////////////////////////////////////////////////
  14. // CStaticTreeCtrl
  15. CStaticTreeCtrl::CStaticTreeCtrl()
  16. {
  17. m_pTopNode = new CTreeNode(); // The tree top
  18. m_iIndent = 16; // Indentation for tree branches
  19. m_iPadding = 4; // Padding between tree and the control border
  20. m_bShowLines = TRUE; // Show lines by default
  21. m_bScrollBarMessage = FALSE; // Only relevant when calculating the scrollbar
  22. m_iDocHeight = 0; // A polite yet meaningless default
  23. m_crDefaultTextColor = RGB(58,58,58); // Some default
  24. m_crConnectingLines = RGB(128,128,128); // Some default
  25. m_bAudioOn = TRUE; // The context menu audio
  26. // Safeguards
  27. m_pSelected = NULL;
  28. }
  29. CStaticTreeCtrl::~CStaticTreeCtrl()
  30. {
  31. DeleteNode( m_pTopNode ); // Delete all childs if there are any
  32. delete m_pTopNode; // Delete top node
  33. m_pTopNode = NULL;
  34. m_Font.DeleteObject();
  35. if( m_bmpBackground.GetSafeHandle() != NULL )
  36. m_bmpBackground.DeleteObject();
  37. }
  38. BEGIN_MESSAGE_MAP(CStaticTreeCtrl, CStatic)
  39. //{{AFX_MSG_MAP(CStaticTreeCtrl)
  40. ON_WM_PAINT()
  41. ON_WM_SIZE()
  42. ON_WM_VSCROLL()
  43. ON_WM_LBUTTONUP()
  44. ON_WM_MOUSEWHEEL()
  45. /* ON_WM_CONTEXTMENU()
  46. ON_COMMAND(CM_INSERTCHILD, OnCM_InsertChild)
  47. ON_COMMAND(CM_INSERTSIBLING, OnCM_InsertSibling)
  48. ON_COMMAND(CM_DELETENODE, OnCM_DeleteNode)
  49. ON_COMMAND(CM_MODIFYNODETEXT, OnCM_ModifyNodeText)
  50. ON_COMMAND(CM_CHANGENODECOLOR, OnCM_ChangeNodeColor)
  51. ON_COMMAND(CM_TOGGLECONNECTINGLINES, OnCM_ToggleConnectingLines)
  52. ON_COMMAND(CM_SETCONNECTINGLINESCOLOR, OnCM_SetConnectingLinesColor)
  53. ON_COMMAND(CM_SETFONT, OnCM_SetFont)
  54. ON_COMMAND(CM_SETDEFAULTCOLOR, OnCM_SetDefaultColor)
  55. ON_COMMAND(CM_SETBACKGROUNDBITMAP, OnCM_SetBackgroundBitmap)
  56. ON_COMMAND(CM_TOGGLEMENUSOUND, OnCM_ToggleMenuSound)*/
  57. //}}AFX_MSG_MAP
  58. END_MESSAGE_MAP()
  59. /////////////////////////////////////////////////////////////////////////////
  60. // PUBLIC METHODS
  61. /////////////////////////////////////////////////////////////////////////////
  62. CStaticTreeCtrl& CStaticTreeCtrl::SetTextFont( LONG nHeight, BOOL bBold, BOOL bItalic, const CString& csFaceName )
  63. {
  64. CDC * pDC = GetDC();
  65. m_lgFont.lfHeight = -MulDiv( nHeight, GetDeviceCaps( pDC->m_hDC, LOGPIXELSY ), 72 );
  66. m_lgFont.lfWidth = 0;
  67. m_lgFont.lfEscapement = 0;
  68. m_lgFont.lfOrientation = 0;
  69. m_lgFont.lfWeight = ( bBold )? FW_BOLD:FW_DONTCARE;
  70. m_lgFont.lfItalic = (BYTE)( ( bItalic )? TRUE:FALSE );
  71. m_lgFont.lfUnderline = FALSE;
  72. m_lgFont.lfStrikeOut = FALSE;
  73. m_lgFont.lfCharSet = DEFAULT_CHARSET;
  74. m_lgFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  75. m_lgFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  76. m_lgFont.lfQuality = DEFAULT_QUALITY;
  77. m_lgFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  78. STRCPY( m_lgFont.lfFaceName, csFaceName );
  79. if( m_Font.GetSafeHandle() != NULL )
  80. m_Font.DeleteObject();
  81. m_Font.CreateFontIndirect( &m_lgFont );
  82. // Calculate node height for this font
  83. // CDC *pDC = GetDC();
  84. int iSaved = pDC->SaveDC();
  85. CFont* pOldFont = pDC->SelectObject( &m_Font );
  86. // Calculate the height of this font with a character likely to be 'big'
  87. // and don't forget to add a little padding
  88. m_iLineHeight = pDC->GetTextExtent( "X" ).cy + 4;
  89. pDC->SelectObject( pOldFont );
  90. pDC->RestoreDC( iSaved );
  91. ReleaseDC( pDC );
  92. return *this;
  93. }
  94. CStaticTreeCtrl& CStaticTreeCtrl::SetDefaultTextColor( COLORREF crText )
  95. {
  96. m_crDefaultTextColor = crText;
  97. return *this;
  98. }
  99. HTREENODE CStaticTreeCtrl::InsertSibling( HTREENODE pInsertAfter, const CString& csLabel,
  100. COLORREF crText /* = 0 */, BOOL bUseDefaultTextColor /* = TRUE */,
  101. BOOL bInvalidate /* = FALSE  */)
  102. {
  103. ASSERT( pInsertAfter != NULL ); // Make sure the node exists
  104. HTREENODE pNewNode = new CTreeNode();
  105. pNewNode->csLabel = csLabel; // New node's label
  106. if( bUseDefaultTextColor )
  107. pNewNode->bUseDefaultTextColor = TRUE; // Use the default text color
  108. else
  109. pNewNode->crText = crText; // New node's text color
  110. pNewNode->pParent = pInsertAfter->pParent; // Nas the same parent
  111. // Insert the new node between pInsertAfter and its next sibling
  112. pNewNode->pSibling = pInsertAfter->pSibling;
  113. pInsertAfter->pSibling = pNewNode;
  114. // Repaint the control if so desired
  115. if( bInvalidate )
  116. Invalidate();
  117. return pNewNode;
  118. }
  119. HTREENODE CStaticTreeCtrl::InsertChild( HTREENODE pParent, const CString& csLabel,
  120. COLORREF crText /* = 0 */, BOOL bUseDefaultTextColor /* = TRUE */,
  121. BOOL bInvalidate /* = FALSE  */)
  122. {
  123. ASSERT( pParent != NULL ); // Make sure the node exists
  124. if( pParent == HTOPNODE ) // Check for top node
  125. pParent = m_pTopNode;
  126. HTREENODE pNewNode = new CTreeNode();
  127. // Basic node information
  128. pNewNode->csLabel = csLabel; // New node's label
  129. if( bUseDefaultTextColor )
  130. pNewNode->bUseDefaultTextColor = TRUE; // Use the default text color
  131. else
  132. pNewNode->crText = crText; // New node's text color
  133. pNewNode->pParent = pParent; // New node's parent
  134. // Insert the new node as pParent's first child
  135. pNewNode->pSibling = pParent->pChild;
  136. pParent->pChild = pNewNode;
  137. // Repaint the control if so desired
  138. if( bInvalidate )
  139. Invalidate();
  140. return pNewNode;
  141. }
  142. void CStaticTreeCtrl::DeleteNode( HTREENODE pNode, BOOL bInvalidate /* = FALSE  */)
  143. {
  144. ASSERT( pNode != NULL ); // Make sure the node exists
  145. // Don't delete the top node
  146. if( pNode == HTOPNODE )
  147. DeleteNode( m_pTopNode, bInvalidate );
  148. // Delete childs
  149. if( pNode->pChild != NULL )
  150. DeleteNodeRecursive( pNode->pChild );
  151. // If this node is not the top node, fix pointers in sibling list
  152. if( pNode != m_pTopNode )
  153. {
  154. HTREENODE pRunner = pNode->pParent;
  155. // If first child, set the parent pointer to the next sibling
  156. // Otherwise, find sibling before and set its sibling pointer to the node's sibling
  157. if( pRunner->pChild == pNode )
  158. pRunner->pChild = pNode->pSibling;
  159. else
  160. {
  161. pRunner = pRunner->pChild;
  162. // Loop until the next node is the one being deleted
  163. while( pRunner->pSibling != pNode )
  164. pRunner = pRunner->pSibling;
  165. pRunner->pSibling = pNode->pSibling;
  166. }
  167. delete pNode;
  168. pNode = NULL;
  169. }
  170. // Repaint the control if so desired
  171. if( bInvalidate )
  172. Invalidate();
  173. }
  174. void CStaticTreeCtrl::ToggleNode( HTREENODE pNode, BOOL bInvalidate /* = FALSE  */)
  175. {
  176. ASSERT( pNode != NULL );
  177. pNode->bOpen = !( pNode->bOpen );
  178. if( bInvalidate )
  179. Invalidate();
  180. }
  181. void CStaticTreeCtrl::SetNodeColor( HTREENODE pNode, COLORREF crText, BOOL bInvalidate /* = FALSE  */)
  182. {
  183. ASSERT( pNode != NULL );
  184. pNode->bUseDefaultTextColor = FALSE;
  185. pNode->crText = crText;
  186. if( bInvalidate )
  187. Invalidate();
  188. }
  189. void CStaticTreeCtrl::SetBackgroundBitmap( BOOL bInvalidate /* = FALSE  */)
  190. {
  191. CFileDialog fd( TRUE, NULL, NULL, OFN_EXPLORER | OFN_FILEMUSTEXIST, _T("Bitmap Files (*.bmp)|*.bmp||"), this );
  192. // If the user clicked 'ok'
  193. if( fd.DoModal() == IDOK )
  194. {
  195. // If there is a bitmap already loaded, delete it
  196.     if( m_bmpBackground.GetSafeHandle() != NULL )
  197. m_bmpBackground.DeleteObject();
  198. // Load the bitmap from the file selected
  199. HBITMAP hBitmap = (HBITMAP)LoadImage( NULL, fd.GetPathName(), IMAGE_BITMAP, 
  200. 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION | LR_DEFAULTSIZE );
  201. // Attach it to the CBitmap object
  202. m_bmpBackground.Attach( hBitmap );
  203. // Repaint if so desired
  204. if( bInvalidate )
  205. Invalidate();
  206. }
  207. }
  208. /////////////////////////////////////////////////////////////////////////////
  209. // PROTECTED METHODS
  210. /////////////////////////////////////////////////////////////////////////////
  211. void CStaticTreeCtrl::DeleteNodeRecursive( HTREENODE pNode )
  212. {
  213. if( pNode->pSibling != NULL )
  214. DeleteNodeRecursive( pNode->pSibling );
  215. if( pNode->pChild != NULL )
  216. DeleteNodeRecursive( pNode->pChild );
  217. delete pNode;
  218. pNode = NULL;
  219. }
  220. int CStaticTreeCtrl::DrawNodesRecursive( CDC* pDC, HTREENODE pNode, int x, int y, CRect rFrame )
  221. {
  222. int iDocHeight = 0; // Total document height
  223. CRect rNode;
  224. // The node's location and dimensions on screen
  225. rNode.left = x;
  226. rNode.top = y;
  227. rNode.right = rFrame.right - m_iPadding;
  228. rNode.bottom = y + m_iLineHeight;
  229. pNode->rNode.CopyRect( rNode ); // Record the rectangle
  230. COLORREF cr = ( pNode->bUseDefaultTextColor )? m_crDefaultTextColor:pNode->crText;
  231. COLORREF crOldText = pDC->SetTextColor( cr );
  232. // MULTILINE TEXT - begins
  233. CString cs = pNode->csLabel;
  234. int iPos = 0;
  235. // Draw text until there is nothing left to draw
  236. while( cs.GetLength() > 0 )
  237. {
  238. // Height of a line of text
  239. rNode.bottom = rNode.top + m_iLineHeight;
  240. // Find out how much text fits in one line
  241. iPos = HowMuchTextFits( pDC, rFrame.right - m_iPadding - rNode.left, cs );
  242. // Draw only if the node is visible
  243. if( rNode.bottom > 0 && rNode.top < rFrame.bottom )
  244. pDC->DrawText( cs.Left( iPos + 1 ), rNode, DT_LEFT | DT_SINGLELINE | DT_VCENTER );
  245. // Eliminate the text that has been already drawn
  246. cs = cs.Mid( iPos + 1 );
  247. // The node grows everytime another line of text is drawn
  248. pNode->rNode.UnionRect( pNode->rNode, rNode );
  249. // Move down the drawing rectangle for the next line of text
  250. rNode.top = rNode.bottom;
  251. }
  252. // MULTILINE TEXT - ends
  253. pDC->SetTextColor( crOldText );
  254. // If there are no child or siblings, then this branch is done
  255. if( pNode->pChild == NULL &&  pNode->pSibling == NULL )
  256. return pNode->rNode.Height();
  257. // If the node is open AND it has childs, then draw those
  258. if( pNode->bOpen && pNode->pChild != NULL )
  259. iDocHeight = DrawNodesRecursive( pDC, pNode->pChild, x + m_iIndent, y + pNode->rNode.Height(), rFrame );
  260. // If the node has siblings, then draw those
  261. if( pNode->pSibling != NULL )
  262. iDocHeight += DrawNodesRecursive( pDC, pNode->pSibling, x, y + pNode->rNode.Height() + iDocHeight, rFrame );
  263. return iDocHeight + pNode->rNode.Height();
  264. }
  265. int CStaticTreeCtrl::HowMuchTextFits( CDC* pDC, int iAvailableWidth, CString csText )
  266. {
  267. int iValidSoFar = csText.GetLength() - 1; // Assume the entire text fits
  268. // If the text's pixel width is larger than what's available
  269. if( pDC->GetTextExtent( csText ).cx > iAvailableWidth )
  270. {
  271. int iNextBlank = 0; // Position of the next blank in text
  272. int iPixelWidth = 0; // Text's pixel width
  273. // Loop until we can fit no more of the text
  274. while( iPixelWidth < iAvailableWidth )
  275. {
  276. iValidSoFar = iNextBlank; // Record the char pos so far
  277. iNextBlank = csText.Find( ' ', iNextBlank + 1 ); // Advance one word at a time
  278. // Have reached the end of the string?
  279. if( iNextBlank == -1 )
  280. iNextBlank = csText.GetLength();
  281. // Calculate the new width
  282. iPixelWidth = pDC->GetTextExtent( csText.Left( iNextBlank ) ).cx;
  283. }
  284. }
  285. return iValidSoFar;
  286. }
  287. void CStaticTreeCtrl::DrawLinesRecursive( CDC* pDC, HTREENODE pNode )
  288. {
  289. // Draw lines from childs if the node is open before drawing lines from this node
  290. if( pNode->bOpen && pNode->pChild != NULL )
  291. DrawLinesRecursive( pDC, pNode->pChild );
  292. // Where is the elbow joint of this connecting line?
  293. int iJointX = pNode->rNode.left - m_iIndent - 6;
  294. int iJointY = pNode->rNode.top + ( m_iLineHeight / 2 );
  295. // If the parent is not the top node, throw a connecting line to it
  296. if( pNode->pParent != m_pTopNode )
  297. {
  298. // How far up from the joint is the parent?
  299. int iDispY = iJointY - pNode->pParent->rNode.top - ( m_iLineHeight / 2 );
  300. // Use 1 pixel wide rectangles to draw lines
  301. pDC->FillSolidRect( iJointX, iJointY, m_iIndent, 1, m_crConnectingLines ); // Horizontal line
  302. pDC->FillSolidRect( iJointX, iJointY, 1, -iDispY, m_crConnectingLines ); // Vertical line
  303. }
  304. // Put a solid dot to mark a node
  305. pDC->FillSolidRect( iJointX + m_iIndent - 2, iJointY - 2, 5, 5, m_crConnectingLines );
  306. // Hollow out the dot if the node has no childs
  307. if( pNode->pChild == NULL )
  308. pDC->FillSolidRect( iJointX + m_iIndent - 1, iJointY - 1, 3, 3, RGB(255,255,255) );
  309. // Draw the next sibling if there are any
  310. if( pNode->pSibling != NULL )
  311. DrawLinesRecursive( pDC, pNode->pSibling );
  312. }
  313. void CStaticTreeCtrl::ResetScrollBar()
  314. {
  315. // Flag to avoid a call from OnSize while resetting the scrollbar
  316. m_bScrollBarMessage = TRUE;
  317. CRect rFrame;
  318. GetClientRect( rFrame );
  319. // Need for scrollbars?
  320. if( rFrame.Height() > m_iDocHeight + 8 )
  321. {
  322. ShowScrollBar( SB_VERT, FALSE ); // Hide it
  323. SetScrollPos( SB_VERT, 0 );
  324. }
  325. else
  326. {
  327. SCROLLINFO si;
  328. si.cbSize = sizeof(SCROLLINFO);
  329. si.fMask = SIF_PAGE | SIF_RANGE;
  330. si.nPage = rFrame.Height();
  331. si.nMax = m_iDocHeight + 8;
  332. si.nMin = 0 ;
  333. SetScrollInfo( SB_VERT, &si );
  334. EnableScrollBarCtrl( SB_VERT, TRUE );
  335. }
  336. m_bScrollBarMessage = FALSE;
  337. }
  338. HTREENODE CStaticTreeCtrl::FindNodeByPoint( const CPoint& point, HTREENODE pNode )
  339. {
  340. HTREENODE pFound = NULL;
  341. // Found it?
  342. if( pNode->rNode.PtInRect( point ) )
  343. pFound = pNode;
  344. // If this node isn't it then check the node's childs if it is open and there are any
  345. if( pFound == NULL && pNode->bOpen && pNode->pChild != NULL )
  346. pFound = FindNodeByPoint( point, pNode->pChild );
  347. // If didn't find it among the node's childs, then check the next sibling 
  348. if( pFound == NULL && pNode->pSibling != NULL )
  349. pFound = FindNodeByPoint( point, pNode->pSibling );
  350. return pFound;
  351. }
  352. /*BOOL CStaticTreeCtrl::NodeTextDlg( CString& csText )
  353. {
  354. BOOL bRet = FALSE;
  355. CDLG_TreeNodeText tntDlg;
  356. tntDlg.m_csItemText = csText;
  357. if( tntDlg.DoModal() == IDOK )
  358. {
  359. csText = tntDlg.m_csItemText;
  360. bRet = TRUE;
  361. }
  362. return bRet;
  363. }*/
  364. /////////////////////////////////////////////////////////////////////////////
  365. // CStaticTreeCtrl message handlers
  366. void CStaticTreeCtrl::OnPaint() 
  367. {
  368. CPaintDC dc(this); // Device context for painting
  369. // Double-buffering
  370. CDC* pDCMem = new CDC;
  371. CBitmap* pOldBitmapHpxs = NULL;
  372. CBitmap bmpCanvas;
  373. CRect rFrame;
  374. GetClientRect( rFrame );
  375. pDCMem->CreateCompatibleDC( &dc );
  376. bmpCanvas.CreateCompatibleBitmap( &dc, rFrame.Width(), rFrame.Height() );
  377. pOldBitmapHpxs = pDCMem->SelectObject( &bmpCanvas );
  378. // START DRAW -------------------------------------------------
  379. // If there is a bitmap loaded, use it
  380. // Otherwise, paint the background white
  381.     if( m_bmpBackground.GetSafeHandle() != NULL )
  382.     {
  383. CDC* pDCTemp = new CDC;;
  384. BITMAP bmp;
  385. pDCTemp->CreateCompatibleDC( &dc );
  386. m_bmpBackground.GetBitmap( &bmp );
  387. // Select the bitmap into the temp device context
  388. CBitmap* pOldBitmap = (CBitmap*) pDCTemp->SelectObject( &m_bmpBackground );
  389. // Stretch the bitmap to fill the entire control area
  390. pDCMem->StretchBlt( 0, 0, rFrame.Width(), rFrame.Height(), pDCTemp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY );
  391. pDCTemp->SelectObject( pOldBitmap ); 
  392. delete pDCTemp;
  393. }
  394. else
  395. pDCMem->FillSolidRect( rFrame, RGB(255,255,255) );
  396. UINT nMode = pDCMem->SetBkMode( TRANSPARENT );
  397. CFont* pOldFont = pDCMem->SelectObject( &m_Font );
  398. int iLastNodePos = 0;
  399. if( m_pTopNode->pChild != NULL )
  400. {
  401. iLastNodePos = DrawNodesRecursive( pDCMem, m_pTopNode->pChild,
  402. rFrame.left + m_iIndent,
  403. m_iPadding - GetScrollPos( SB_VERT ),
  404. rFrame );
  405. if( m_bShowLines )
  406. DrawLinesRecursive( pDCMem, m_pTopNode->pChild );
  407. }
  408. pDCMem->SelectObject( pOldFont );
  409. pDCMem->SetBkMode( nMode );
  410. pDCMem->Draw3dRect( rFrame, RGB(0,0,0), RGB(0,0,0) ); // Border
  411. // END DRAW   -------------------------------------------------
  412. dc.BitBlt( 0, 0, rFrame.Width(), rFrame.Height(), pDCMem, 0, 0, SRCCOPY );
  413. pDCMem->SelectObject( pOldBitmapHpxs );
  414. //hpxs添加
  415. bmpCanvas.DeleteObject();
  416. delete pDCMem;
  417. // Has the total document height changed?
  418. if( iLastNodePos != m_iDocHeight )
  419. {
  420. BOOL bInvalidate = ( ( m_iDocHeight < rFrame.Height() ) != ( iLastNodePos < rFrame.Height() ) );
  421. m_iDocHeight = iLastNodePos;
  422. ResetScrollBar();
  423. // If the scrollbar has just been hidden/shown, repaint
  424. if( bInvalidate )
  425. Invalidate();
  426. }
  427. }
  428. void CStaticTreeCtrl::OnSize(UINT nType, int cx, int cy) 
  429. {
  430. // Setting the scroll sends its own size message. Prevent it thus avoiding an ugly loop.
  431. // Other than that, resizing the control means that the tree height may change (word-wrap).
  432. if( !m_bScrollBarMessage )
  433. ResetScrollBar();
  434. CStatic::OnSize(nType, cx, cy);
  435. }
  436. void CStaticTreeCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  437. {
  438. int iScrollBarPos = GetScrollPos( SB_VERT );
  439. CRect rFrame;
  440. GetClientRect( rFrame );
  441. switch( nSBCode )
  442. {
  443. case SB_LINEUP:
  444. iScrollBarPos = max( iScrollBarPos - m_iLineHeight, 0 );
  445. break;
  446. case SB_LINEDOWN:
  447. iScrollBarPos = min( iScrollBarPos + m_iLineHeight, GetScrollLimit( SB_VERT ) );
  448. break;
  449. case SB_PAGEUP:
  450. iScrollBarPos = max( iScrollBarPos - rFrame.Height(), 0 );
  451. break;
  452. case SB_PAGEDOWN:
  453. iScrollBarPos = min( iScrollBarPos + rFrame.Height(), GetScrollLimit( SB_VERT ) );
  454. break;
  455. case SB_THUMBTRACK:
  456. case SB_THUMBPOSITION:
  457. iScrollBarPos = nPos;
  458. break;
  459. }
  460. SetScrollPos( SB_VERT, iScrollBarPos );
  461. Invalidate();
  462. CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
  463. }
  464. LRESULT CStaticTreeCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
  465. {
  466. if( message == WM_NCHITTEST || message == WM_NCLBUTTONDOWN || message == WM_NCLBUTTONDBLCLK )
  467. return ::DefWindowProc( m_hWnd, message, wParam, lParam );
  468. return CStatic::WindowProc(message, wParam, lParam);
  469. }
  470. void CStaticTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point) 
  471. {
  472. HTREENODE pClickedOn = NULL; // Assume no node was clicked on
  473. if( m_pTopNode->pChild != NULL) // If the tree is populated, search it
  474. pClickedOn = FindNodeByPoint( point, m_pTopNode->pChild );
  475. if( pClickedOn != NULL ) // If a node was clicked on
  476. ToggleNode( pClickedOn, TRUE );
  477. else
  478. CStatic::OnLButtonUp(nFlags, point);
  479. }
  480. /*BOOL CStaticTreeCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
  481. {
  482. // zDelta greater than 0, means rotating away from the user, that is, scrolling up
  483. OnVScroll( ( zDelta > 0 )? SB_LINEUP:SB_LINEDOWN, 0, NULL );
  484. return CStatic::OnMouseWheel(nFlags, zDelta, pt);
  485. }
  486. void CStaticTreeCtrl::OnContextMenu(CWnd* , CPoint point) 
  487. {
  488. CPoint cp( point );
  489. // WM_CONTEXTMENU passes absolute coordinates, we need them local
  490. ScreenToClient( &cp );
  491. // Find the node that has been clicked on
  492. if( m_pTopNode->pChild == NULL )
  493. m_pSelected = NULL; // Empty tree
  494. else
  495. m_pSelected = FindNodeByPoint( cp, m_pTopNode->pChild );
  496. CContextMenu ccmPopUp;
  497. ccmPopUp.CreatePopupMenu();
  498. // Customize the menu appearance and behavior
  499. ccmPopUp
  500. .ToggleSound ( m_bAudioOn )
  501. .SetTextFont ( &m_Font )
  502. .SetColors ( RGB(70,36,36), RGB(253,249,249), RGB(172,96,96), RGB(244,234,234), RGB(182,109,109) );
  503. // Get a device context so that it'll be possible for the context menu
  504. // to calculate the size of the menu item's text
  505. CDC *pDC = GetDC();
  506. int iSaved = pDC->SaveDC();
  507. CFont* pOldFont = pDC->SelectObject( &m_Font );
  508. // ADDING MENU ITEMS - Start
  509. // If a node has been clicked on, use the first 45 chars of its text as the
  510. // first menu item (always disabled)
  511. if( m_pSelected != NULL )
  512. {
  513. CString csDots = ( m_pSelected->csLabel.GetLength() > 45 )? _T("..."):_T("");
  514. CString cs = m_pSelected->csLabel.Left( 45 ) + csDots;
  515. ccmPopUp.AppendMenuItem( MF_DISABLED, WM_APP, cs, _T(""), pDC );
  516. ccmPopUp.AppendMenuItem( MF_SEPARATOR, 0, _T(""), _T(""), pDC );
  517. }
  518. UINT nFlag = ( m_pSelected != NULL )? MF_ENABLED:MF_GRAYED;
  519. // Node related items
  520. ccmPopUp.AppendMenuItem( MF_ENABLED, CM_INSERTCHILD, _T("Insert Child"), _T("insertChild.wav"), pDC );
  521. ccmPopUp.AppendMenuItem( nFlag, CM_INSERTSIBLING, _T("Insert Sibling"), _T("insertSibling.wav"), pDC );
  522. ccmPopUp.AppendMenuItem( nFlag, CM_DELETENODE, _T("Delete Node"), _T("deleteNode.wav"), pDC );
  523. ccmPopUp.AppendMenuItem( nFlag, CM_MODIFYNODETEXT, _T("Modify Node Text"), _T("modifyNodeText.wav"), pDC );
  524. ccmPopUp.AppendMenuItem( nFlag, CM_CHANGENODECOLOR, _T("Change Node Color"), _T("changeNodeColor.wav"), pDC );
  525. ccmPopUp.AppendMenuItem( MF_SEPARATOR, 0, _T(""), _T(""), pDC );
  526. // Connecting lines related items
  527. ccmPopUp.AppendMenuItem( MF_ENABLED, CM_TOGGLECONNECTINGLINES, _T("Toggle Connecting Lines"), _T("toggleConnectingLines.wav"), pDC );
  528. ccmPopUp.AppendMenuItem( MF_ENABLED, CM_SETCONNECTINGLINESCOLOR, _T("Set Connecting Lines Color"),  _T("setConnectingLinesColor.wav"), pDC );
  529. ccmPopUp.AppendMenuItem( MF_SEPARATOR, 0, _T(""), _T(""), pDC );
  530. // Tree appearance items
  531. ccmPopUp.AppendMenuItem( MF_ENABLED, CM_SETFONT, _T("Set Font"), _T("setFont.wav"), pDC );
  532. ccmPopUp.AppendMenuItem( MF_ENABLED, CM_SETDEFAULTCOLOR, _T("Set Default Text Color"), _T("setDefaultColor.wav"), pDC );
  533. ccmPopUp.AppendMenuItem( MF_ENABLED, CM_SETBACKGROUNDBITMAP, _T("Set Background Bitmap"), _T("setBackgroundBitmap.wav"), pDC );
  534. ccmPopUp.AppendMenuItem( MF_SEPARATOR, 0, _T(""), _T(""), pDC );
  535. // Context menu sound toggle item
  536. ccmPopUp.AppendMenuItem( MF_ENABLED, CM_TOGGLEMENUSOUND, _T("Toggle Menu Sound"), _T("toggleMenuSound.wav"), pDC );
  537. // ADDING MENU ITEMS - End
  538. // Display the context menu
  539. ccmPopUp.TrackPopupMenu( TPM_LEFTALIGN, point.x, point.y, this );
  540. // Clean up
  541. pDC->SelectObject( pOldFont );
  542. pDC->RestoreDC( iSaved );
  543. ReleaseDC( pDC );
  544. }
  545. */
  546. /*void CStaticTreeCtrl::OnCM_InsertChild()
  547. {
  548. CString csText("");
  549. if( NodeTextDlg( csText ) == TRUE )
  550. {
  551. if( m_pSelected == NULL )
  552. InsertChild( m_pTopNode, csText );
  553. else
  554. {
  555. InsertChild( m_pSelected, csText );
  556. m_pSelected = NULL;
  557. }
  558. Invalidate();
  559. }
  560. }*/
  561. /*void CStaticTreeCtrl::OnCM_InsertSibling()
  562. {
  563. CString csText("");
  564. if( NodeTextDlg( csText ) == TRUE )
  565. {
  566. InsertSibling( m_pSelected, csText );
  567. m_pSelected = NULL;
  568. Invalidate();
  569. }
  570. }
  571. void CStaticTreeCtrl::OnCM_DeleteNode()
  572. {
  573. DeleteNode( m_pSelected, TRUE );
  574. m_pSelected = NULL;
  575. }
  576. void CStaticTreeCtrl::OnCM_ModifyNodeText()
  577. {
  578. if( NodeTextDlg( m_pSelected->csLabel ) == TRUE )
  579. {
  580. m_pSelected = NULL;
  581. Invalidate();
  582. }
  583. }
  584. void CStaticTreeCtrl::OnCM_ChangeNodeColor()
  585. {
  586. COLORREF cr = ( m_pSelected->bUseDefaultTextColor )? m_crDefaultTextColor:m_pSelected->crText;
  587. CColorDialog ccd( cr, CC_FULLOPEN | CC_ANYCOLOR );
  588. if ( ccd.DoModal() == IDOK )
  589. SetNodeColor( m_pSelected, ccd.GetColor(), TRUE );
  590. m_pSelected = NULL;
  591. }
  592. void CStaticTreeCtrl::OnCM_ToggleConnectingLines()
  593. {
  594. m_bShowLines = !m_bShowLines;
  595. Invalidate();
  596. }
  597. void CStaticTreeCtrl::OnCM_SetConnectingLinesColor()
  598. {
  599. CColorDialog ccd( m_crConnectingLines, CC_FULLOPEN | CC_ANYCOLOR );
  600. if ( ccd.DoModal() == IDOK )
  601. {
  602. m_crConnectingLines =  ccd.GetColor();
  603. Invalidate();
  604. }
  605. }
  606. void CStaticTreeCtrl::OnCM_SetFont()
  607. {
  608. CFontDialog cfd( &m_lgFont , CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT );
  609. if(  cfd.DoModal() == IDOK )
  610. {
  611. SetTextFont( cfd.GetSize() / 10, cfd.IsBold(), cfd.IsItalic(), cfd.GetFaceName() );
  612. Invalidate();
  613. }
  614. }
  615. void CStaticTreeCtrl::OnCM_SetDefaultColor()
  616. {
  617. CColorDialog ccd( m_crDefaultTextColor, CC_FULLOPEN | CC_ANYCOLOR );
  618. if ( ccd.DoModal() == IDOK )
  619. {
  620. m_crDefaultTextColor = ccd.GetColor();
  621. Invalidate();
  622. }
  623. }
  624. void CStaticTreeCtrl::OnCM_SetBackgroundBitmap()
  625. {
  626. SetBackgroundBitmap( TRUE );
  627. }
  628. void CStaticTreeCtrl::OnCM_ToggleMenuSound()
  629. {
  630. m_bAudioOn = !m_bAudioOn;
  631. }
  632. */
  633. void CStaticTreeCtrl::SetNodeText(HTREENODE pNode, CString strText)
  634. {
  635. pNode->csLabel = strText;
  636. Invalidate();
  637. }