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

Graph program

Development Platform:

Visual C++

  1. // BirchCtrl.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "BirchCtrl.h"
  5. #include ".birchctrl.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. CBirch::CBirch()
  12. {
  13. m_pTopNode = new CTreeNode(); // The tree top
  14. m_pSelected = NULL;
  15. m_wnd   =  NULL;
  16. }
  17. CBirch::~CBirch()
  18. {
  19. DeleteNode( m_pTopNode ); // Delete all childs if there are any
  20. delete m_pTopNode; // Delete top node
  21. m_pTopNode = NULL;
  22. }
  23. HTREENODE CBirch::InsertSibling( HTREENODE pInsertAfter, const CString& csLabel,
  24. COLORREF crText /* = 0 */, BOOL bUseDefaultTextColor /* = TRUE */)
  25. {
  26. ASSERT( pInsertAfter != NULL ); // Make sure the node exists
  27. HTREENODE pNewNode = new CTreeNode();
  28. pNewNode->csLabel = csLabel; // New node's label
  29. if( bUseDefaultTextColor )
  30. pNewNode->bUseDefaultTextColor = TRUE; // Use the default text color
  31. else
  32. pNewNode->crText = crText; // New node's text color
  33. pNewNode->pParent = pInsertAfter->pParent; // Nas the same parent
  34. pNewNode->iNodeLevel = pInsertAfter->pParent->iNodeLevel+1;
  35. ASSERT(pNewNode->iNodeLevel==pInsertAfter->iNodeLevel);
  36. // Insert the new node between pInsertAfter and its next sibling
  37. pNewNode->pNextSibling = pInsertAfter->pNextSibling;
  38. if (pNewNode->pNextSibling==NULL)
  39. pNewNode->pParent->pLastChild = pNewNode;
  40. else
  41. pNewNode->pNextSibling->pPrevSibling = pNewNode;
  42. pInsertAfter->pNextSibling = pNewNode;
  43. pNewNode->pPrevSibling = pInsertAfter;
  44. return pNewNode;
  45. }
  46. HTREENODE CBirch::InsertChild( HTREENODE pParent, const CString& csLabel,
  47.   COLORREF crText /* = 0 */, BOOL bUseDefaultTextColor /* = TRUE */)
  48. {
  49. ASSERT( pParent != NULL ); // Make sure the node exists
  50. if( pParent == HTOPNODE ) // Check for top node
  51. pParent = m_pTopNode;
  52. HTREENODE pNewNode = new CTreeNode();
  53. // Basic node information
  54. pNewNode->csLabel = csLabel; // New node's label
  55. if( bUseDefaultTextColor )
  56. pNewNode->bUseDefaultTextColor = TRUE; // Use the default text color
  57. else
  58. pNewNode->crText = crText; // New node's text color
  59. pNewNode->pParent = pParent; // New node's parent
  60. pNewNode->iNodeLevel = pParent->iNodeLevel+1;
  61. if (pParent->pFirstChild==NULL)
  62. {
  63. ASSERT(pParent->pLastChild==NULL);
  64. pParent->pFirstChild=pParent->pLastChild=pNewNode;
  65. pNewNode->pPrevSibling = pNewNode->pNextSibling = NULL;
  66. }
  67. else
  68. {
  69. pNewNode->pNextSibling = NULL;
  70. pNewNode->pPrevSibling = pNewNode->pParent->pLastChild;
  71. pNewNode->pParent->pLastChild->pNextSibling = pNewNode;
  72. pNewNode->pParent->pLastChild = pNewNode;
  73. }
  74. return pNewNode;
  75. }
  76. void CBirch::DeleteNode( HTREENODE pNode)
  77. {
  78. ASSERT( pNode != NULL ); // Make sure the node exists
  79. // Don't delete the top node
  80. if( pNode == HTOPNODE )
  81. DeleteNode( m_pTopNode);
  82. // Delete childs
  83. if( pNode->pFirstChild != NULL )
  84. DeleteSubTree( pNode );
  85. // If this node is not the top node, fix pointers in sibling list
  86. if( pNode != m_pTopNode )
  87. {
  88. HTREENODE pNodePar = pNode->pParent;
  89. // If first child, set the parent pointer to the next sibling
  90. // Otherwise, find sibling before and set its sibling pointer to the node's sibling
  91. if( pNodePar->pFirstChild == pNode )
  92. pNodePar->pFirstChild = pNode->pNextSibling;
  93. if( pNodePar->pLastChild == pNode )
  94. pNodePar->pLastChild = pNode->pPrevSibling;
  95. {
  96. HTREENODE  prevNd = pNode->pPrevSibling;
  97. HTREENODE  nextNd = pNode->pNextSibling;
  98. if (prevNd)
  99. prevNd->pNextSibling = nextNd;
  100. if (nextNd)
  101. nextNd->pPrevSibling = prevNd;
  102. }
  103. delete pNode;
  104. pNode = NULL;
  105. }
  106. }
  107. void CBirch::ToggleNode( HTREENODE pNode)
  108. {
  109. ASSERT( pNode != NULL );
  110. pNode->bOpen = !( pNode->bOpen );
  111. if (m_wnd && m_wnd->IsWindowVisible())
  112. m_wnd->Invalidate();
  113. }
  114. void CBirch::SetNodeColor( HTREENODE pNode, COLORREF crText)
  115. {
  116. ASSERT( pNode != NULL );
  117. pNode->bUseDefaultTextColor = FALSE;
  118. pNode->crText = crText;
  119. }
  120. void CBirch::DeleteSubTree( HTREENODE pNode )
  121. {
  122. if( pNode->pFirstChild == NULL )
  123. return;
  124. HTREENODE curNd = pNode->pFirstChild;
  125. while(curNd)
  126. {
  127. DeleteSubTree(curNd);
  128. HTREENODE tmpNd = curNd->pNextSibling;
  129. DeleteNode(curNd);
  130. curNd = tmpNd;
  131. }
  132. }
  133. /////////////////////////////////////////////////////////////////////////////
  134. // CBirchCtrl
  135. CBirchCtrl::CBirchCtrl()
  136. {
  137. m_bShowLines = TRUE; // Show lines by default
  138. m_bScrollBarMessage = FALSE; // Only relevant when calculating the scrollbar
  139. m_iIndent = 16; // Indentation for tree branches
  140. m_iPadding = 4; // Padding between tree and the control border
  141. m_iLineHeight = 0;
  142. m_iLineHeightByFont = 0;
  143. m_iDocHeight = 0; // A polite yet meaningless default
  144. m_crDefaultTextColor = RGB(58,58,58); // Some default
  145. m_crConnectingLines = RGB(128,128,128); // Some default
  146. // Safeguards
  147. m_birch                 = NULL;
  148. m_edit                  = NULL;
  149. m_editable_item         = NULL;
  150. }
  151. CBirchCtrl::~CBirchCtrl()
  152. {
  153. m_Font.DeleteObject();
  154. if (m_edit)
  155. {
  156. m_edit->DestroyWindow();
  157. delete m_edit;
  158. m_edit = NULL;
  159. }
  160. }
  161. BEGIN_MESSAGE_MAP(CBirchCtrl, CWnd)
  162. //{{AFX_MSG_MAP(CBirchCtrl)
  163. ON_WM_PAINT()
  164. ON_WM_SIZE()
  165. ON_WM_VSCROLL()
  166. ON_WM_LBUTTONDOWN()
  167. ON_WM_MOUSEWHEEL()
  168. //}}AFX_MSG_MAP
  169. END_MESSAGE_MAP()
  170. /////////////////////////////////////////////////////////////////////////////
  171. // PUBLIC METHODS
  172. /////////////////////////////////////////////////////////////////////////////
  173. CBirchCtrl& CBirchCtrl::SetTextFont( LONG nHeight, BOOL bBold, BOOL bItalic, const CString& csFaceName )
  174. {
  175. m_lgFont.lfHeight = -MulDiv( nHeight, GetDeviceCaps( GetDC()->m_hDC, LOGPIXELSY ), 72 );
  176. m_lgFont.lfWidth = 0;
  177. m_lgFont.lfEscapement = 0;
  178. m_lgFont.lfOrientation = 0;
  179. m_lgFont.lfWeight = ( bBold )? FW_BOLD:FW_DONTCARE;
  180. m_lgFont.lfItalic = (BYTE)( ( bItalic )? TRUE:FALSE );
  181. m_lgFont.lfUnderline = FALSE;
  182. m_lgFont.lfStrikeOut = FALSE;
  183. m_lgFont.lfCharSet = DEFAULT_CHARSET;
  184. m_lgFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
  185. m_lgFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  186. m_lgFont.lfQuality = DEFAULT_QUALITY;
  187. m_lgFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  188. STRCPY( m_lgFont.lfFaceName, csFaceName );
  189. if( m_Font.GetSafeHandle() != NULL )
  190. m_Font.DeleteObject();
  191. m_Font.CreateFontIndirect( &m_lgFont );
  192. // Calculate node height for this font
  193. CDC *pDC = GetDC();
  194. int iSaved = pDC->SaveDC();
  195. CFont* pOldFont = pDC->SelectObject( &m_Font );
  196. // Calculate the height of this font with a character likely to be 'big'
  197. // and don't forget to add a little padding
  198. m_iLineHeightByFont = m_iLineHeight = pDC->GetTextExtent( "X" ).cy + 4;
  199. pDC->SelectObject( pOldFont );
  200. pDC->RestoreDC( iSaved );
  201. ReleaseDC( pDC );
  202. return *this;
  203. }
  204. CBirchCtrl& CBirchCtrl::SetDefaultTextColor( COLORREF crText )
  205. {
  206. m_crDefaultTextColor = crText;
  207. return *this;
  208. }
  209. int CBirchCtrl::DrawNodesRecursive( CDC* pDC, HTREENODE pNode, int y, 
  210. CPen* linesPen, CPen* marksPen, CRect rFrame )
  211. {
  212. if (!m_birch)
  213. return 0;
  214. if (!pNode->bVisible)
  215. return (y-1);
  216. CRect rNode;
  217. // The node's location and dimensions on screen
  218. rNode.left = m_iIndent*pNode->iNodeLevel+3;
  219. rNode.top = y;
  220. rNode.right = rFrame.right - m_iPadding;
  221. rNode.bottom = y + m_iLineHeight;
  222. pNode->rNode.CopyRect( rNode ); // Record the rectangle
  223. if (pNode->pParent==m_birch->GetTopNode())
  224. {
  225. CRect rct(0,rNode.top+1,rFrame.right,rNode.bottom-1);
  226. themeData.DrawThemedRect(pDC,&rct,TRUE);
  227. pDC->FillSolidRect(rct.left,rct.top-1,rct.Width(),1,GetSysColor(COLOR_3DFACE));
  228. pDC->FillSolidRect(rct.left,rct.bottom,rct.Width(),1,GetSysColor(COLOR_3DSHADOW));
  229. }
  230. int iJointX = pNode->rNode.left - m_iIndent - 6;
  231. int iJointY = pNode->rNode.top + ( m_iLineHeight / 2 );
  232. int iDispY = iJointY - pNode->pParent->rNode.top - ( m_iLineHeight / 2 );
  233. if( rNode.bottom > 0 && rNode.top < rFrame.bottom )
  234. {
  235. COLORREF cr = ( pNode->bUseDefaultTextColor )? m_crDefaultTextColor:pNode->crText;
  236. COLORREF crOldText = pDC->SetTextColor( cr );
  237. size_t bmps_cnt = pNode->item_bitmaps.size();
  238. int  buf_len = 1;
  239. if (bmps_cnt>0)
  240. {
  241. for (size_t jj=0;jj<bmps_cnt;jj++)
  242. {
  243. int bw = pNode->item_bitmaps[jj]->GetWidth();
  244. int bh = pNode->item_bitmaps[jj]->GetHeight();
  245. CRect destR(pNode->rNode.left+buf_len,
  246. pNode->rNode.top+m_iLineHeight/2-bh/2,
  247. pNode->rNode.left+buf_len+bw,
  248. pNode->rNode.top+m_iLineHeight/2+bh/2);
  249. CRect srcR(0, 0, bw,bh);
  250. //pDC->Rectangle(destR);
  251. pNode->item_bitmaps[jj]->Draw(pDC,&destR,&srcR);
  252. buf_len += bw+1;
  253. //CTreeCtrl::CreateDragImage()
  254. }
  255. }
  256. pDC->DrawText( pNode->csLabel, CRect(rNode.left+buf_len+2,rNode.top,
  257. rNode.right,rNode.bottom), DT_LEFT | DT_SINGLELINE | DT_VCENTER );
  258. pDC->SetTextColor( crOldText );
  259. // draw lines START
  260. // If the parent is not the top node, throw a connecting line to it
  261. if( pNode->pParent != m_birch->GetTopNode() )
  262. {
  263. // How far up from the joint is the parent?
  264. // Use 1 pixel wide rectangles to draw lines
  265. pDC->SelectObject(linesPen);
  266. pDC->MoveTo(iJointX, iJointY);
  267. pDC->LineTo(iJointX+m_iIndent, iJointY);
  268. //if (pNode==pNode->pParent->pLastChild)
  269. {
  270. pDC->MoveTo(iJointX, iJointY);
  271. pDC->LineTo(iJointX, iJointY-iDispY+5);
  272. }
  273. }
  274. pDC->SelectObject(marksPen);
  275. // Put a solid dot to mark a node
  276. if (pNode->pFirstChild != NULL)
  277. {
  278. pDC->Rectangle(iJointX + m_iIndent - 4, iJointY - 4, iJointX + m_iIndent +5, iJointY +5);
  279. pDC->MoveTo(iJointX + m_iIndent - 2, iJointY);
  280. pDC->LineTo(iJointX + m_iIndent + 3, iJointY);
  281. if (!pNode->bOpen)
  282. {
  283. pDC->MoveTo(iJointX + m_iIndent, iJointY - 2);
  284. pDC->LineTo(iJointX + m_iIndent, iJointY + 3);
  285. }
  286. }
  287. // Hollow out the dot if the node has no childs
  288. else
  289. {
  290. pDC->Ellipse(iJointX + m_iIndent - 1, iJointY - 1, iJointX + m_iIndent +2, iJointY +2);
  291. }
  292. // draw lines END
  293. }
  294. else
  295. {
  296. pDC->SelectObject(linesPen);
  297. if( pNode->pParent != m_birch->GetTopNode()/* && pNode==pNode->pParent->pLastChild*/)
  298. {
  299. pDC->MoveTo(iJointX, iJointY);
  300. pDC->LineTo(iJointX, iJointY-iDispY+5);
  301. }
  302. }
  303. // If there are no child or siblings, then this branch is done
  304. if( pNode->pFirstChild == NULL)
  305. return pNode->rNode.bottom;//pNode->rNode.Height();
  306. // If the node is open AND it has childs, then draw those
  307. int iLastNodePos=pNode->rNode.bottom;
  308. if( pNode->bOpen)
  309. {
  310. HTREENODE curTreeNode = pNode->pFirstChild ;
  311. while (curTreeNode)
  312. {
  313. iLastNodePos = DrawNodesRecursive( pDC, curTreeNode,
  314. iLastNodePos+1,
  315. linesPen, marksPen,
  316. rFrame );
  317. curTreeNode = curTreeNode->pNextSibling;
  318. }
  319. }
  320. return iLastNodePos;
  321. }
  322. void CBirchCtrl::ResetScrollBar()
  323. {
  324. // Flag to avoid a call from OnSize while resetting the scrollbar
  325. m_bScrollBarMessage = TRUE;
  326. CRect rFrame;
  327. GetClientRect( rFrame );
  328. // Need for scrollbars?
  329. if( rFrame.Height() > m_iDocHeight + 8 )
  330. {
  331. ShowScrollBar( SB_VERT, FALSE ); // Hide it
  332. SetScrollPos( SB_VERT, 0 );
  333. }
  334. else
  335. {
  336. SCROLLINFO si;
  337. si.cbSize = sizeof(SCROLLINFO);
  338. si.fMask = SIF_PAGE | SIF_RANGE;
  339. si.nPage = rFrame.Height()/*/m_iLineHeight*/;
  340. si.nMax = (m_iDocHeight + 8)/*/m_iLineHeight*/;
  341. si.nMin = 0 ;
  342. SetScrollInfo( SB_VERT, &si );
  343. EnableScrollBarCtrl( SB_VERT, TRUE );
  344. }
  345. m_bScrollBarMessage = FALSE;
  346. }
  347. HTREENODE CBirchCtrl::FindNodeByPoint( const CPoint& point, HTREENODE pNode )
  348. {
  349. HTREENODE curTreeNode = pNode->pFirstChild ;
  350. HTREENODE tmpNd = NULL;
  351. while (curTreeNode)
  352. {
  353. if (curTreeNode->bVisible)
  354. {
  355. // Found it?
  356. if( (point.y>curTreeNode->rNode.top)&&
  357. (point.y<curTreeNode->rNode.bottom))
  358. return curTreeNode;
  359. if( curTreeNode->bOpen && curTreeNode->pFirstChild != NULL )
  360. if ((tmpNd=FindNodeByPoint( point, curTreeNode ))!=NULL)
  361. return tmpNd;
  362. }
  363. curTreeNode = curTreeNode->pNextSibling;
  364. }
  365. return NULL;
  366. }
  367. /////////////////////////////////////////////////////////////////////////////
  368. // CBirchCtrl message handlers
  369. void CBirchCtrl::OnPaint() 
  370. {
  371. CPaintDC dc(this); // Device context for painting
  372. if (!m_birch)
  373. return;
  374. // Double-buffering
  375. CDC* pDCMem = new CDC;
  376. CBitmap* pOldBitmap = NULL;
  377. CBitmap bmpCanvas;
  378. CRect rFrame;
  379. GetClientRect( rFrame );
  380. pDCMem->CreateCompatibleDC( &dc );
  381. bmpCanvas.CreateCompatibleBitmap( &dc, rFrame.Width(), rFrame.Height() );
  382. pOldBitmap = pDCMem->SelectObject( &bmpCanvas );
  383. // START DRAW -------------------------------------------------
  384. // If there is a bitmap loaded, use it
  385. // Otherwise, paint the background white
  386.     pDCMem->FillSolidRect( rFrame, GetSysColor(COLOR_WINDOW) );
  387. UINT nMode = pDCMem->SetBkMode( TRANSPARENT );
  388. CFont* pOldFont = pDCMem->SelectObject( &m_Font );
  389. CPen *pOldPen = pDCMem->GetCurrentPen();
  390. CPen linesPen(PS_SOLID, 1,  m_crConnectingLines),
  391. marksPen(PS_SOLID,  1, m_crConnectingLines);
  392. int iLastNodePos = m_iPadding - GetScrollPos( SB_VERT );
  393. HTREENODE curTreeNode = m_birch->GetTopNode()->pFirstChild ;
  394. while (curTreeNode)
  395. {
  396. iLastNodePos = DrawNodesRecursive( pDCMem, curTreeNode,
  397. iLastNodePos+1,
  398. &linesPen,
  399. &marksPen,
  400. rFrame );
  401. curTreeNode = curTreeNode->pNextSibling;
  402. }
  403. pDCMem->SelectObject(pOldPen);
  404. pDCMem->SelectObject( pOldFont );
  405. pDCMem->SetBkMode( nMode );
  406. // END DRAW   -------------------------------------------------
  407. dc.BitBlt( 0, 0, rFrame.Width(), rFrame.Height(), pDCMem, 0, 0, SRCCOPY );
  408. pDCMem->SelectObject( pOldBitmap );
  409. delete pDCMem;
  410. iLastNodePos+=GetScrollPos( SB_VERT );
  411. // Has the total document height changed?
  412. if( iLastNodePos != m_iDocHeight )
  413. {
  414. BOOL bInvalidate = ( ( m_iDocHeight < rFrame.Height() ) != ( iLastNodePos < rFrame.Height() ) );
  415. m_iDocHeight = iLastNodePos;
  416. ResetScrollBar();
  417. // If the scrollbar has just been hidden/shown, repaint
  418. if( bInvalidate )
  419. Invalidate();
  420. }
  421. }
  422. void CBirchCtrl::OnSize(UINT nType, int cx, int cy) 
  423. {
  424. // Setting the scroll sends its own size message. Prevent it thus avoiding an ugly loop.
  425. // Other than that, resizing the control means that the tree height may change (word-wrap).
  426. if( !m_bScrollBarMessage )
  427. ResetScrollBar();
  428. if (m_edit)
  429. {
  430. CRect rrr;
  431. m_edit->GetWindowRect(rrr);
  432. ScreenToClient(rrr);
  433. rrr.right = cx;
  434. m_edit->MoveWindow(rrr);
  435. }
  436. CWnd::OnSize(nType, cx, cy);
  437. }
  438. void CBirchCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  439. {
  440. int iScrollBarPos = GetScrollPos( SB_VERT );
  441. CRect rFrame;
  442. GetClientRect( rFrame );
  443. switch( nSBCode )
  444. {
  445. case SB_LINEUP:
  446. iScrollBarPos = max( iScrollBarPos - m_iLineHeight, 0 );
  447. break;
  448. case SB_LINEDOWN:
  449. iScrollBarPos = min( iScrollBarPos + m_iLineHeight, GetScrollLimit( SB_VERT ) );
  450. break;
  451. case SB_PAGEUP:
  452. iScrollBarPos = max( iScrollBarPos - rFrame.Height(), 0 );
  453. break;
  454. case SB_PAGEDOWN:
  455. iScrollBarPos = min( iScrollBarPos + rFrame.Height(), GetScrollLimit( SB_VERT ) );
  456. break;
  457. case SB_THUMBTRACK:
  458. case SB_THUMBPOSITION:
  459. iScrollBarPos = nPos;
  460. break;
  461. }
  462. SetScrollPos( SB_VERT, iScrollBarPos );
  463. if (m_edit)
  464. {
  465. m_edit->DestroyWindow();
  466. delete m_edit;
  467. m_edit = NULL;
  468. }
  469. Invalidate();
  470. CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
  471. }
  472. void CBirchCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
  473. {
  474. if (!m_birch)
  475. return;
  476. HTREENODE pClickedOn = NULL; // Assume no node was clicked on
  477. if( m_birch->GetTopNode()->pFirstChild != NULL) // If the tree is populated, search it
  478. pClickedOn = FindNodeByPoint( point, m_birch->GetTopNode() );
  479. if (m_edit)
  480. {
  481. m_edit->DestroyWindow();
  482. delete m_edit;
  483. m_edit = NULL;
  484. }
  485. if( pClickedOn != NULL ) // If a node was clicked on
  486. {
  487. if (point.x<pClickedOn->rNode.left)
  488. m_birch->ToggleNode( pClickedOn);
  489. else
  490. {
  491. size_t sss = pClickedOn->item_bitmaps.size();
  492. int buf_l = 1;
  493. for (size_t i=0;i<sss;i++)
  494. {
  495. if ((point.x>(pClickedOn->rNode.left+buf_l))&&
  496. (point.x<(pClickedOn->rNode.left+buf_l+pClickedOn->item_bitmaps[i]->GetWidth())))
  497. {
  498. ClickOnIcon(pClickedOn,i);
  499. return;
  500. }
  501. buf_l+=pClickedOn->item_bitmaps[i]->GetWidth()+1;
  502. }
  503. if (point.x>(pClickedOn->rNode.left+buf_l) && pClickedOn->bEditable)
  504. {
  505. m_edit=new CTreeItemEdit;
  506. CRect rrr(pClickedOn->rNode.left+buf_l+2,pClickedOn->rNode.top-2,
  507. pClickedOn->rNode.right,pClickedOn->rNode.bottom+2);
  508. m_edit->Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | 
  509. WS_BORDER| ES_AUTOHSCROLL | ES_WANTRETURN,
  510. rrr, this, 1);
  511. m_edit->CreateFont(15,"MS Shell Dlg");
  512. m_edit->SetBirch(this);
  513. m_edit->SetWindowPos(&wndTop,rrr.left,rrr.top,rrr.Width(),rrr.Height(),SWP_SHOWWINDOW);
  514. m_edit->SetFocus();
  515. CString labb = pClickedOn->csLabel;
  516. StartEditLabel(pClickedOn,labb);
  517. m_edit->SetWindowText(labb);
  518. m_edit->SetSel(0,-1);
  519. m_editable_item = pClickedOn;
  520. }
  521. }
  522. }
  523. else
  524. CWnd::OnLButtonDown(nFlags, point);
  525. }
  526. BOOL CBirchCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
  527. {
  528. // zDelta greater than 0, means rotating away from the user, that is, scrolling up
  529. OnVScroll( ( zDelta > 0 )? SB_LINEUP:SB_LINEDOWN, 0, NULL );
  530. return CWnd::OnMouseWheel(nFlags, zDelta, pt);
  531. }
  532. void CBirchCtrl::FireMessageFromEdit()
  533. {
  534. if (m_editable_item)
  535. {
  536. ASSERT(m_edit);
  537. CString newLabel;
  538. m_edit->GetWindowText(newLabel);
  539. FinishEditLabel(m_editable_item, newLabel);
  540. }
  541. if (m_edit)
  542. {
  543. m_edit->DestroyWindow();
  544. delete m_edit;
  545. m_edit = NULL;
  546. }
  547. m_editable_item = NULL;
  548. }
  549. // CTreeItemEdit
  550. IMPLEMENT_DYNAMIC(CTreeItemEdit, CEdit)
  551. CTreeItemEdit::CTreeItemEdit()
  552. {
  553. m_birch_ctrl = NULL;
  554. }
  555. CTreeItemEdit::~CTreeItemEdit()
  556. {
  557. }
  558. BEGIN_MESSAGE_MAP(CTreeItemEdit, CEdit)
  559. ON_WM_KEYUP()
  560. ON_WM_KILLFOCUS()
  561. END_MESSAGE_MAP()
  562. BOOL CTreeItemEdit::CreateFont(LONG lfHeight, LPCTSTR lpszFaceName)
  563. {
  564. //  Create a font for the combobox
  565. LOGFONT logFont;
  566. memset(&logFont, 0, sizeof(logFont));
  567. if (!::GetSystemMetrics(SM_DBCSENABLED))
  568. {
  569. // Since design guide says toolbars are fixed height so is the font.
  570. logFont.lfHeight = lfHeight;
  571. //logFont.lfWeight = 0;
  572. CString strDefaultFont = lpszFaceName;
  573. lstrcpy(logFont.lfFaceName, strDefaultFont);
  574. if (!m_font.CreateFontIndirect(&logFont))
  575. {
  576. TRACE("Could Not create font for combon");
  577. return FALSE;
  578. }
  579. }
  580. else
  581. {
  582. m_font.Attach(::GetStockObject(SYSTEM_FONT));
  583. }
  584. SetFont(&m_font);
  585. ModifyStyleEx(0, WS_EX_CLIENTEDGE|WS_EX_STATICEDGE, SWP_FRAMECHANGED);
  586. return TRUE;
  587. }
  588. // CTreeItemEdit message handlers
  589. void CTreeItemEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  590. {
  591. if (nChar==13)
  592. {
  593. if (m_birch_ctrl)
  594. m_birch_ctrl->FireMessageFromEdit();
  595. }
  596. else
  597. CEdit::OnKeyUp(nChar, nRepCnt, nFlags);
  598. }
  599. void CTreeItemEdit::OnKillFocus(CWnd* pNewWnd)
  600. {
  601. CEdit::OnKillFocus(pNewWnd);
  602. if (m_birch_ctrl)
  603. m_birch_ctrl->FireMessageFromEdit();
  604. }