CustomTabCtrl.cpp
上传用户:tang1250
上传日期:2020-10-23
资源大小:86k
文件大小:57k
源码类别:

PropertySheet

开发平台:

Visual C++

  1. /**********************************************************************
  2. **
  3. ** CustomTabCtrl.cpp : implementation file of CCustomTabCtrl class
  4. **
  5. ** by Andrzej Markowski June 2004
  6. **
  7. **********************************************************************/
  8. #include "stdafx.h"
  9. #include <AFXPRIV.H>
  10. #include "CustomTabCtrl.h"
  11. // CCustomTabCtrlItem
  12. CCustomTabCtrlItem::CCustomTabCtrlItem(CString sText,LPARAM lParam) : 
  13. m_sText(sText), 
  14. m_lParam(lParam),
  15. m_bShape(TAB_SHAPE1),
  16. m_fSelected(FALSE),
  17. m_fHighlighted(FALSE),
  18. m_fHighlightChanged(FALSE)
  19. {
  20. }
  21. void CCustomTabCtrlItem::operator=(const CCustomTabCtrlItem &other)
  22. {
  23. m_sText = other.m_sText;
  24. m_lParam = other.m_lParam;
  25. }
  26. void CCustomTabCtrlItem::ComputeRgn(BOOL fOnTop)
  27. {
  28. m_rgn.DeleteObject();
  29. CPoint pts[6];
  30. GetRegionPoints(m_rect,pts, fOnTop);
  31. m_rgn.CreatePolygonRgn(pts, 6, WINDING);
  32. }
  33. void CCustomTabCtrlItem::GetRegionPoints(const CRect& rc, CPoint* pts, BOOL fOnTop) const
  34. {
  35. switch(m_bShape)
  36. {
  37. case TAB_SHAPE2:
  38. {
  39. if(fOnTop)
  40. {
  41. pts[0] = CPoint(rc.left, rc.bottom+1);
  42. pts[1] = CPoint(rc.left, rc.top);
  43. pts[2] = CPoint(rc.left + rc.Height()/2, rc.bottom+1);
  44. pts[3] = CPoint(rc.left + rc.Height()/2, rc.bottom+1);
  45. pts[4] = CPoint(rc.left + rc.Height()/2, rc.bottom+1);
  46. pts[5] = CPoint(rc.left + rc.Height()/2, rc.bottom+1);
  47. }
  48. else
  49. {
  50. pts[0] = rc.TopLeft();
  51. pts[1] = CPoint(rc.left, rc.bottom);
  52. pts[2] = CPoint(rc.left + rc.Height()/2, rc.top);
  53. pts[3] = CPoint(rc.left + rc.Height()/2, rc.top);
  54. pts[4] = CPoint(rc.left + rc.Height()/2, rc.top);
  55. pts[5] = CPoint(rc.left + rc.Height()/2, rc.top);
  56. }
  57. }
  58. break;
  59. case TAB_SHAPE3:
  60. {
  61. if(fOnTop)
  62. {
  63. pts[0] = CPoint(rc.left, rc.bottom+1);
  64. pts[1] = CPoint(rc.left + rc.Height()/4, rc.Height()/2);
  65. pts[2] = CPoint(rc.left, rc.top);
  66. pts[3] = CPoint(rc.left, rc.top);
  67. pts[4] = CPoint(rc.left, rc.top);
  68. pts[5] = CPoint(rc.left, rc.top);
  69. }
  70. else
  71. {
  72. pts[0] = rc.TopLeft();
  73. pts[1] = CPoint(rc.left + rc.Height()/4, rc.Height()/2);
  74. pts[2] = CPoint(rc.left, rc.bottom);
  75. pts[3] = CPoint(rc.left, rc.bottom);
  76. pts[4] = CPoint(rc.left, rc.bottom);
  77. pts[5] = CPoint(rc.left, rc.bottom);
  78. }
  79. }
  80. break;
  81. case TAB_SHAPE4:
  82. {
  83. if(fOnTop)
  84. {
  85. pts[0] = CPoint(rc.left, rc.bottom+1);
  86. pts[1] = CPoint(rc.left + rc.Height()/4, rc.Height()/2);
  87. pts[2] = CPoint(rc.left + rc.Height()/2, rc.top);
  88. pts[3] = CPoint(rc.right - rc.Height()/2, rc.top);
  89. pts[4] = CPoint(rc.right - rc.Height()/4, rc.Height()/2);
  90. pts[5] = CPoint(rc.right, rc.bottom+1);
  91. }
  92. else
  93. {
  94. pts[0] = rc.TopLeft();
  95. pts[1] = CPoint(rc.left + rc.Height()/4, rc.Height()/2);
  96. pts[2] = CPoint(rc.left + rc.Height()/2, rc.bottom);
  97. pts[3] = CPoint(rc.right - rc.Height()/2, rc.bottom);
  98. pts[4] = CPoint(rc.right - rc.Height()/4, rc.Height()/2);
  99. pts[5] = CPoint(rc.right, rc.top);
  100. }
  101. }
  102. break;
  103. case TAB_SHAPE5:
  104. {
  105. if(fOnTop)
  106. {
  107. pts[0] = CPoint(rc.left, rc.bottom+1);
  108. pts[1] = CPoint(rc.left + rc.Height()/4, rc.Height()/2);
  109. pts[2] = CPoint(rc.left + rc.Height()/2 , rc.top);
  110. pts[3] = CPoint(rc.right - rc.Height()/2, rc.top);
  111. pts[4] = CPoint(rc.right - rc.Height()/4, rc.Height()/2);
  112. pts[5] = CPoint(rc.right - rc.Height()/2, rc.bottom+1);
  113. }
  114. else
  115. {
  116. pts[0] = rc.TopLeft();
  117. pts[1] = CPoint(rc.left + rc.Height()/4, rc.Height()/2);
  118. pts[2] = CPoint(rc.left + rc.Height()/2 , rc.bottom);
  119. pts[3] = CPoint(rc.right - rc.Height()/2, rc.bottom);
  120. pts[4] = CPoint(rc.right - rc.Height()/4, rc.Height()/2);
  121. pts[5] = CPoint(rc.right - rc.Height()/2, rc.top);
  122. }
  123. }
  124. break;
  125. default:
  126. {
  127. pts[0] = CPoint(0,0);
  128. pts[1] = CPoint(0,0);
  129. pts[2] = CPoint(0,0);
  130. pts[3] = CPoint(0,0);
  131. pts[4] = CPoint(0,0);
  132. pts[5] = CPoint(0,0);
  133. }
  134. break;
  135. }
  136. }
  137. void CCustomTabCtrlItem::GetDrawPoints(const CRect& rc, CPoint* pts, BOOL fOnTop) const
  138. {
  139. switch(m_bShape)
  140. {
  141. case TAB_SHAPE2:
  142. case TAB_SHAPE3:
  143. {
  144. if(fOnTop)
  145. {
  146. pts[0] = CPoint(rc.left, rc.top);
  147. pts[1] = CPoint(rc.left + rc.Height()/2, rc.bottom);
  148. }
  149. else
  150. {
  151. pts[0] = CPoint(rc.left, rc.bottom);
  152. pts[1] = CPoint(rc.left + rc.Height()/2, rc.top);
  153. }
  154. }
  155. break;
  156. case TAB_SHAPE4:
  157. case TAB_SHAPE5:
  158. {
  159. if(fOnTop)
  160. {
  161. pts[0] = CPoint(rc.left,rc.bottom);
  162. pts[1] = CPoint(rc.left + rc.Height()/2, rc.top);
  163. pts[2] = CPoint(rc.right - rc.Height()/2, rc.top);
  164. pts[3] = CPoint(rc.right, rc.bottom);
  165. }
  166. else
  167. {
  168. pts[0] = rc.TopLeft();
  169. pts[1] = CPoint(rc.left + rc.Height()/2, rc.bottom);
  170. pts[2] = CPoint(rc.right - rc.Height()/2, rc.bottom);
  171. pts[3] = CPoint(rc.right, rc.top);
  172. }
  173. }
  174. break;
  175. }
  176. }
  177. void CCustomTabCtrlItem::Draw(CDC& dc, CFont& font, BOOL fOnTop)
  178. {
  179. COLORREF bgColor = GetSysColor((m_fSelected||m_fHighlighted) ? COLOR_WINDOW     : COLOR_3DFACE);
  180. COLORREF fgColor = GetSysColor((m_fSelected ||m_fHighlighted) ? COLOR_WINDOWTEXT : COLOR_BTNTEXT);
  181. CBrush brush(bgColor);
  182. CPen blackPen(PS_SOLID, 1, GetSysColor(COLOR_BTNTEXT));
  183. CPen shadowPen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
  184. CPoint pts[4];
  185. CRect rc = m_rect;
  186. GetDrawPoints(rc, pts, fOnTop);
  187. // Paint item background
  188. dc.FillRgn(&m_rgn, &brush);
  189. CPen* pOldPen = dc.SelectObject(&blackPen);
  190. // draw item
  191. switch(m_bShape)
  192. {
  193. case TAB_SHAPE2:
  194. case TAB_SHAPE3:
  195. {
  196. dc.MoveTo(pts[0]);
  197. dc.LineTo(pts[1]);
  198. if(!m_fSelected)
  199. {
  200. dc.SelectObject(&shadowPen);
  201. dc.MoveTo(pts[0].x-1,pts[0].y);
  202. dc.LineTo(pts[1].x-1,pts[1].y);
  203. }
  204. }
  205. break;
  206. case TAB_SHAPE4:
  207. case TAB_SHAPE5:
  208. {
  209. if(bBorderLine)
  210. {
  211. dc.MoveTo(pts[0]);
  212. dc.LineTo(pts[1]);
  213. dc.SelectObject(&shadowPen);
  214. dc.LineTo(pts[2]);
  215. if(!m_fSelected)
  216. {
  217. dc.MoveTo(pts[2].x-1,pts[2].y);
  218. dc.LineTo(pts[3].x-1,pts[3].y);
  219. }
  220. dc.SelectObject(&blackPen);
  221. dc.MoveTo(pts[2]);
  222. dc.LineTo(pts[3]);
  223. }
  224. // draw item text
  225. COLORREF bgOldColor = dc.SetBkColor(bgColor);
  226. COLORREF fgOldColor = dc.SetTextColor(fgColor);
  227. rc.DeflateRect(rc.Height()/2, 2,rc.Height()/2,2);
  228. CFont* pOldFont = dc.SelectObject(&font);
  229. dc.DrawText(m_sText, &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
  230. dc.SelectObject(pOldFont);
  231. dc.SetTextColor(fgOldColor);
  232. dc.SetBkColor(bgOldColor);
  233. }
  234. break;
  235. }
  236. dc.SelectObject(pOldPen);
  237. }
  238. // CCustomTabCtrl
  239. LOGFONT CCustomTabCtrl::lf_default = {11, 0, 0, 0, FW_NORMAL, 0, 0, 0,
  240. DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
  241. DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "宋体"};
  242. BYTE CCustomTabCtrl::m_bBitsGlyphs[] = {
  243. 0xBD,0xFB,0xDF,0xBD,0x3C,0x00,
  244. 0xB9,0xF3,0xCF,0x9D,0x99,0x00,
  245. 0xB1,0xE3,0xC7,0x8D,0xC3,0x00,
  246. 0xA3,0xC7,0xE3,0xC5,0xE7,0x00,
  247. 0xB1,0xE3,0xC7,0x8D,0xC3,0x00,
  248. 0xB9,0xF3,0xCF,0x9D,0x99,0x00,
  249. 0xBD,0xFB,0xDF,0xBD,0x3C,0x00
  250. };
  251. CCustomTabCtrl::CCustomTabCtrl() :
  252. m_nButtonIDDown(CTCID_NOBUTTON), 
  253. m_nItemSelected(-1),
  254. m_nItemNdxOffset(0), 
  255. m_hBmpBkLeftSpin(NULL),
  256. m_hBmpBkRightSpin(NULL),
  257. m_hCursorMove(NULL),
  258. m_hCursorCopy(NULL),
  259. m_nItemDragDest(0),
  260. m_BorderLine(TRUE)
  261. {
  262. RegisterWindowClass();
  263. LOGFONT logFont;
  264. ZeroMemory((void*)&logFont,sizeof(logFont));
  265. strcpy(logFont.lfFaceName,"宋体");
  266. logFont.lfHeight = -12;
  267. logFont.lfWeight = 400;
  268. logFont.lfCharSet = GB2312_CHARSET;
  269. logFont.lfOutPrecision = 3;
  270. logFont.lfClipPrecision = 2; 
  271. logFont.lfQuality = 1;
  272. logFont.lfPitchAndFamily = 2;
  273.  
  274. SetControlFont(logFont);
  275. //SetControlFont(GetDefaultFont());
  276. m_bmpGlyphsMono.CreateBitmap(48,7,1,1,m_bBitsGlyphs);
  277. }
  278. // Register the window class if it has not already been registered.
  279. BOOL CCustomTabCtrl::RegisterWindowClass()
  280. {
  281.     WNDCLASS wndcls;
  282.     HINSTANCE hInst = AfxGetInstanceHandle();
  283.     if (!(::GetClassInfo(hInst, CustomTabCtrl_CLASSNAME, &wndcls)))
  284.     {
  285.         wndcls.style            = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  286.         wndcls.lpfnWndProc      = ::DefWindowProc;
  287.         wndcls.cbClsExtra       = wndcls.cbWndExtra = 0;
  288.         wndcls.hInstance        = hInst;
  289.         wndcls.hIcon            = NULL;
  290.         wndcls.hCursor          = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
  291.         wndcls.hbrBackground    = (HBRUSH) (COLOR_3DFACE + 1);
  292.         wndcls.lpszMenuName     = NULL;
  293.         wndcls.lpszClassName    = CustomTabCtrl_CLASSNAME;
  294.         if (!AfxRegisterClass(&wndcls))
  295.         {
  296.             AfxThrowResourceException();
  297.             return FALSE;
  298.         }
  299.     }
  300.     return TRUE;
  301. }
  302. CCustomTabCtrl::~CCustomTabCtrl()
  303. {
  304. for(int i=0; i< m_aItems.GetSize(); i++)
  305. delete m_aItems[i];
  306. m_aItems.RemoveAll();
  307. ::DeleteObject(m_hBmpBkLeftSpin);
  308. m_hBmpBkLeftSpin = NULL;
  309. ::DeleteObject(m_hBmpBkRightSpin);
  310. m_hBmpBkRightSpin = NULL;
  311. ::DestroyCursor(m_hCursorMove);
  312. m_hCursorMove = NULL;
  313. ::DestroyCursor(m_hCursorCopy);
  314. m_hCursorCopy = NULL;
  315. }
  316. BEGIN_MESSAGE_MAP(CCustomTabCtrl, CWnd)
  317. //{{AFX_MSG_MAP(CCustomTabCtrl)
  318. ON_WM_ERASEBKGND()
  319. ON_WM_LBUTTONDOWN()
  320. ON_WM_RBUTTONDOWN()
  321. ON_WM_LBUTTONUP()
  322. ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)
  323. ON_MESSAGE(THM_WM_THEMECHANGED,OnThemeChanged)
  324. ON_WM_MOUSEMOVE()
  325. ON_WM_PAINT()
  326. ON_WM_SIZE()
  327. ON_WM_LBUTTONDBLCLK()
  328. ON_WM_TIMER()
  329. ON_EN_UPDATE(CTCID_EDITCTRL, OnUpdateEdit)
  330. ON_WM_RBUTTONDBLCLK()
  331. //}}AFX_MSG_MAP
  332. ON_MESSAGE(WM_SIZEPARENT, OnSizeParent)
  333. END_MESSAGE_MAP()
  334. // CCustomTabCtrl message handlers
  335. void CCustomTabCtrl::DrawBorderLines(BOOL bBorderLine)
  336. {
  337.     m_BorderLine = bBorderLine;
  338. for(int i=0; i<m_aItems.GetSize(); i++)
  339. m_aItems[i]->bBorderLine =m_BorderLine ;
  340. }
  341. Invalidate();
  342. }
  343. BOOL CCustomTabCtrl::Create(UINT dwStyle, const CRect & rect, CWnd * pParentWnd, UINT nID)
  344. return CWnd::Create(CustomTabCtrl_CLASSNAME, _T(""), dwStyle, rect, pParentWnd, nID);
  345. }
  346. BOOL CCustomTabCtrl::OnEraseBkgnd(CDC* /*pDC*/)
  347. {
  348. return TRUE;
  349. }
  350. void CCustomTabCtrl::OnPaint()
  351. {
  352. CPaintDC dc(this);
  353. if(!m_hBmpBkLeftSpin)
  354. {
  355. m_rgbGlyph[0] = GetSysColor(COLOR_BTNTEXT);
  356. m_rgbGlyph[1] = GetSysColor(COLOR_BTNTEXT);
  357. m_rgbGlyph[2] = GetSysColor(COLOR_BTNTEXT);
  358. m_rgbGlyph[3] = GetSysColor(COLOR_BTNTEXT);
  359. }
  360. CRect rCl;
  361. GetClientRect(&rCl);
  362. if(IsVertical())
  363. rCl.SetRect(0,0,rCl.Height(),rCl.Width());
  364. CPen blackPen(PS_SOLID, 1, GetSysColor(COLOR_BTNTEXT));
  365. CDC dcMem;
  366. CBitmap bmpMem;
  367. CBitmap* pOldBmp=NULL;
  368. if(dcMem.CreateCompatibleDC(&dc))
  369. {
  370. if(bmpMem.CreateCompatibleBitmap(&dc,rCl.Width(),rCl.Height()))
  371. pOldBmp = dcMem.SelectObject(&bmpMem);
  372. else
  373. return;
  374.     }
  375. else
  376. return;
  377.  
  378. // clear background
  379. dcMem.FillSolidRect(&rCl,GetSysColor(COLOR_BTNFACE));
  380.  
  381. BOOL fTop = (BOOL)GetStyle()&CTCS_TOP;
  382. CRect rAll;
  383. if(fTop)
  384. rAll.SetRect(0,0,0,rCl.Height()-1);
  385. else
  386. rAll.SetRect(0,1,0,rCl.Height());
  387. rAll.SetRectEmpty(); 
  388.  
  389. // draw tab items visible and not selected
  390. for(int i=0; i<m_aItems.GetSize(); i++)
  391. {
  392. if(m_aItems[i]->m_bShape && !m_aItems[i]->m_fSelected)
  393. {
  394. if(m_aItems[i]->m_fHighlighted)
  395. m_aItems[i]->Draw(dcMem,m_FontSelected,GetStyle()&CTCS_TOP);
  396. else
  397. m_aItems[i]->Draw(dcMem,m_Font,GetStyle()&CTCS_TOP);
  398. }
  399. }
  400. // draw selected tab item
  401. if(m_nItemSelected!=-1 && m_aItems[m_nItemSelected]->m_bShape)
  402. m_aItems[m_nItemSelected]->Draw(dcMem,m_FontSelected,GetStyle()&CTCS_TOP);
  403.  
  404.  
  405. // draw black lines
  406. int nOffsetX = rAll.Width();
  407. CPoint pts[4];
  408. if(GetStyle()&CTCS_TOP)
  409. {
  410. if(m_nItemSelected==-1)
  411. {
  412. pts[0] = CPoint(nOffsetX,rCl.bottom-2); 
  413. pts[1] = CPoint(nOffsetX,rCl.bottom-2); 
  414. pts[2] = CPoint(nOffsetX,rCl.bottom-2); 
  415. pts[3] = CPoint(rCl.right,rCl.bottom-2);
  416. }
  417. else
  418. {
  419. if(m_aItems[m_nItemSelected]->m_bShape)
  420. {
  421. pts[0] = CPoint(nOffsetX,rCl.bottom-2); 
  422. pts[1] = CPoint(m_aItems[m_nItemSelected]->m_rect.left,rCl.bottom-2); 
  423. pts[2] = CPoint(m_aItems[m_nItemSelected]->m_rect.right,rCl.bottom-2); 
  424. pts[3] = CPoint(rCl.right,rCl.bottom-2);
  425. }
  426. else
  427. {
  428. pts[0] = CPoint(nOffsetX,rCl.bottom-2); 
  429. pts[1] = CPoint(nOffsetX,rCl.bottom-2); 
  430. pts[2] = CPoint(nOffsetX,rCl.bottom-2); 
  431. pts[3] = CPoint(rCl.right,rCl.bottom-2);
  432. }
  433. }
  434. }
  435. else
  436. {
  437. if(m_nItemSelected==-1)
  438. {
  439. pts[0] = CPoint(nOffsetX,1); 
  440. pts[1] = CPoint(nOffsetX,1); 
  441. pts[2] = CPoint(nOffsetX,1); 
  442. pts[3] = CPoint(rCl.right,1);
  443. }
  444. else
  445. {
  446. if(m_aItems[m_nItemSelected]->m_bShape)
  447. {
  448. pts[0] = CPoint(nOffsetX,1); 
  449. pts[1] = CPoint(m_aItems[m_nItemSelected]->m_rect.left,1); 
  450. pts[2] = CPoint(m_aItems[m_nItemSelected]->m_rect.right,1); 
  451. pts[3] = CPoint(rCl.right,1);
  452. }
  453. else
  454. {
  455. pts[0] = CPoint(nOffsetX,1); 
  456. pts[1] = CPoint(nOffsetX,1); 
  457. pts[2] = CPoint(nOffsetX,1); 
  458. pts[3] = CPoint(rCl.right,1);
  459. }
  460. }
  461. /*
  462. CPen* pOldPen = dcMem.SelectObject(&blackPen);
  463. dcMem.MoveTo(pts[0]);
  464. dcMem.LineTo(pts[1]);
  465. dcMem.MoveTo(pts[2]);
  466. dcMem.LineTo(pts[3]);
  467. dcMem.SelectObject(pOldPen);
  468. */
  469. if(m_nButtonIDDown>=0 && (GetCursor()==m_hCursorMove || GetCursor()==m_hCursorCopy))
  470. {
  471. // Draw drag destination marker
  472. CPen* pOldPen = dcMem.SelectObject(&blackPen);
  473. int x;
  474. if(m_nItemDragDest==m_aItems.GetSize())
  475. x = m_aItems[m_nItemDragDest-1]->m_rectText.right + rCl.Height()/4-3;
  476. else
  477. x = m_aItems[m_nItemDragDest]->m_rectText.left - rCl.Height()/4-3;
  478. if(x>=rCl.right-7)
  479. x = rCl.right-7;
  480.  
  481. dcMem.MoveTo(x,1);
  482. dcMem.LineTo(x+7,1);
  483. dcMem.MoveTo(x+1,2);
  484. dcMem.LineTo(x+6,2);
  485. dcMem.MoveTo(x+2,3);
  486. dcMem.LineTo(x+5,3);
  487. dcMem.MoveTo(x+3,4);
  488. dcMem.LineTo(x+4,4);
  489. dcMem.SelectObject(pOldPen); 
  490. }
  491. if(IsVertical())
  492. {
  493. POINT pts[3];
  494. pts[0].x = 0;
  495. pts[0].y = rCl.Width();
  496. pts[1].x = 0;
  497. pts[1].y = 0;
  498. pts[2].x = rCl.Height();
  499. pts[2].y = rCl.Width();
  500. ::PlgBlt(dc.m_hDC,pts,dcMem.m_hDC,0,0,rCl.Width(),rCl.Height(),NULL,0,0); 
  501. }
  502. else
  503. dc.BitBlt(rCl.left,rCl.top,rCl.Width(),rCl.Height(),&dcMem,rCl.left,rCl.top,SRCCOPY);
  504. dcMem.SelectObject(pOldBmp);
  505. }
  506. void CCustomTabCtrl::OnSize(UINT nType, int cx, int cy) 
  507. {
  508. CWnd::OnSize(nType, cx, cy);
  509. if(cx && cy)
  510. RecalcLayout(RECALC_RESIZED, m_nItemSelected);
  511. }
  512. LRESULT CCustomTabCtrl::OnSizeParent(WPARAM, LPARAM lParam)
  513. {
  514. AFX_SIZEPARENTPARAMS* pParams = reinterpret_cast<AFX_SIZEPARENTPARAMS*>(lParam);
  515. CRect r;
  516. GetWindowRect(r);
  517. if(IsVertical())
  518. {
  519. if(GetStyle()&CTCS_TOP) // left
  520. {
  521. pParams->rect.left += r.Width();
  522. MoveWindow(pParams->rect.left-r.Width(), pParams->rect.top, r.Width(), pParams->rect.bottom-pParams->rect.top, TRUE);
  523. }
  524. else // right
  525. {
  526. pParams->rect.right -= r.Width();
  527. MoveWindow(pParams->rect.right, pParams->rect.top, r.Width(), pParams->rect.bottom-pParams->rect.top, TRUE);
  528. }
  529. }
  530. else
  531. {
  532. if(GetStyle()&CTCS_TOP)
  533. {
  534. pParams->rect.top += r.Height();
  535. MoveWindow(pParams->rect.left, pParams->rect.top-r.Height(), pParams->rect.right-pParams->rect.left, r.Height(), TRUE);
  536. }
  537. else
  538. {
  539. pParams->rect.bottom -= r.Height();
  540. MoveWindow(pParams->rect.left, pParams->rect.bottom, pParams->rect.right-pParams->rect.left, r.Height(), TRUE);
  541. }
  542. }
  543. return 0;
  544. }
  545. void CCustomTabCtrl::OnLButtonDown(UINT nFlags, CPoint point)
  546. {
  547. int nHitTest = HitTest(point);
  548. NotifyParent(CTCN_CLICK,nHitTest,point);
  549. ProcessLButtonDown(nHitTest,nFlags,point);
  550. CWnd::OnLButtonDown(nFlags,point);
  551. }
  552. void CCustomTabCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
  553. {
  554. int nHTRet = ProcessLButtonDown(HitTest(point),nFlags,point);
  555. if(nHTRet>=0)
  556. {
  557. CString str;
  558. str.Format("总共%d",nHTRet);
  559. AfxMessageBox(str);
  560. m_nButtonIDDown = CTCID_NOBUTTON;
  561. if(nHTRet==HitTest(point))
  562. EditLabel(nHTRet,TRUE);
  563. }
  564. NotifyParent(CTCN_DBLCLK,HitTest(point),point);
  565. CWnd::OnLButtonDblClk(nFlags, point);
  566. }
  567. int CCustomTabCtrl::ProcessLButtonDown(int nHitTest, UINT nFlags, CPoint point)
  568. SetCapture(); 
  569. DWORD dwStyle = GetStyle();
  570. if(((dwStyle&CTCS_DRAGMOVE) && !(nFlags&MK_CONTROL) && m_hCursorMove) || 
  571. ((dwStyle&CTCS_DRAGCOPY) && (nFlags&MK_CONTROL) && m_hCursorCopy))
  572. {
  573. m_nButtonIDDown = nHitTest;
  574. m_nItemDragDest = CTCID_NOBUTTON; 
  575. }
  576. else
  577. m_nButtonIDDown = CTCID_NOBUTTON;
  578. if((GetStyle()&CTCS_MULTIHIGHLIGHT) && (nFlags&MK_CONTROL))
  579. HighlightItem(nHitTest,TRUE,nFlags&MK_CONTROL);
  580. else
  581. {
  582. BOOL bNotify = nHitTest!=m_nItemSelected;
  583. SetCurSel(nHitTest,TRUE,nFlags&MK_CONTROL);
  584. if(bNotify)
  585. NotifyParent(CTCN_SELCHANGE,m_nItemSelected,point);
  586. }
  587. for(int i=0; i<m_aItems.GetSize();i++)
  588. {
  589. if(m_aItems[i]->m_fHighlightChanged)
  590. NotifyParent(CTCN_HIGHLIGHTCHANGE,i,point);
  591. }
  592. return nHitTest;
  593. }
  594. BOOL CCustomTabCtrl::NotifyParent(UINT code, int nItem, CPoint pt)
  595. {
  596. CTC_NMHDR nmh;
  597. memset(&nmh,0,sizeof(CTC_NMHDR));
  598. nmh.hdr.hwndFrom = GetSafeHwnd();
  599. nmh.hdr.idFrom = GetDlgCtrlID();
  600. nmh.hdr.code = code;
  601. nmh.nItem = nItem;
  602. nmh.ptHitTest = pt;
  603. if(nItem>=0 && nItem<m_aItems.GetSize())
  604. {
  605. _tcscpy(nmh.pszText,m_aItems[nItem]->m_sText);
  606. nmh.lParam       = m_aItems[nItem]->m_lParam;
  607. nmh.rItem        = m_aItems[nItem]->m_rectText;
  608. nmh.fSelected    = m_aItems[nItem]->m_fSelected;
  609. nmh.fHighlighted = m_aItems[nItem]->m_fHighlighted;
  610. }
  611. return (BOOL)GetParent()->SendMessage(WM_NOTIFY,GetDlgCtrlID(),(LPARAM)&nmh);
  612. }
  613. void CCustomTabCtrl::OnLButtonUp(UINT /*nFlags*/, CPoint /*point*/)
  614. if(m_nButtonIDDown>=0)
  615. {
  616. if((GetCursor()==m_hCursorCopy) && (GetKeyState(VK_CONTROL)&0x8000))
  617. CopyItem(m_nButtonIDDown,m_nItemDragDest, TRUE);
  618. else if((GetCursor()==m_hCursorMove) && !(GetKeyState(VK_CONTROL)&0x8000))
  619. MoveItem(m_nButtonIDDown,m_nItemDragDest, TRUE);
  620. }
  621. m_nButtonIDDown = CTCID_NOBUTTON;
  622. m_nItemDragDest = CTCID_NOBUTTON;
  623. ReleaseCapture();
  624. }
  625. void CCustomTabCtrl::OnMouseMove(UINT nFlags, CPoint point)
  626. {
  627. nFlags=nFlags;  //禁止4100未引用参数错误
  628. TRACKMOUSEEVENT trackmouseevent;
  629. trackmouseevent.cbSize = sizeof(trackmouseevent);
  630. trackmouseevent.dwFlags = TME_LEAVE;
  631. trackmouseevent.hwndTrack = GetSafeHwnd();
  632. trackmouseevent.dwHoverTime = 0;
  633. _TrackMouseEvent(&trackmouseevent);
  634.  
  635. if(m_nButtonIDDown>=0 && m_nItemDragDest>=0)
  636. {
  637. CRect rCl;
  638. GetClientRect(&rCl);
  639. int x = point.x;
  640. if(IsVertical())
  641. {
  642. x = rCl.Height()-point.y;
  643. rCl.SetRect(0,0,rCl.Height(),rCl.Width());
  644. }
  645. if(m_nItemDragDest>=m_aItems.GetSize())
  646. m_nItemDragDest = m_aItems.GetSize()-1;
  647. int x1 = m_aItems[m_nItemDragDest]->m_rectText.left - rCl.Height()/4;
  648. int x2 = m_aItems[m_nItemDragDest]->m_rectText.right + rCl.Height()/4;
  649. if(x>=rCl.right)
  650. {
  651. m_nItemDragDest++;
  652. if(m_nItemDragDest>=m_aItems.GetSize())
  653. RecalcLayout(RECALC_NEXT_PRESSED,m_aItems.GetSize()-1);
  654. else
  655. RecalcLayout(RECALC_NEXT_PRESSED,m_nItemDragDest);
  656. Invalidate(FALSE);
  657. }
  658. else if(x>=x2)
  659. {
  660. m_nItemDragDest++;
  661. if(m_nItemDragDest>=m_aItems.GetSize())
  662. RecalcLayout(RECALC_ITEM_SELECTED,m_aItems.GetSize()-1);
  663. else
  664. RecalcLayout(RECALC_ITEM_SELECTED,m_nItemDragDest);
  665. Invalidate(FALSE);
  666. }
  667. else if(x<x1)
  668. {
  669. if(m_nItemDragDest>0)
  670. m_nItemDragDest--;
  671. RecalcLayout(RECALC_ITEM_SELECTED,m_nItemDragDest);
  672. Invalidate(FALSE);
  673. }
  674. }
  675. }
  676. LONG CCustomTabCtrl::OnMouseLeave(WPARAM /*wParam*/, LPARAM /*lParam*/) 
  677. {
  678.  
  679. return 0;
  680. }
  681. void CCustomTabCtrl::OnUpdateEdit() 
  682. {
  683. if(m_ctrlEdit.m_hWnd)
  684. {
  685. m_ctrlEdit.GetWindowText(m_aItems[m_nItemSelected]->m_sText);
  686. RecalcLayout(RECALC_EDIT_RESIZED,m_nItemSelected);
  687. Invalidate(FALSE);
  688. }
  689. }
  690. LONG CCustomTabCtrl::OnThemeChanged(WPARAM /*wParam*/, LPARAM /*lParam*/) 
  691. {
  692. ::DeleteObject(m_hBmpBkLeftSpin);
  693. m_hBmpBkLeftSpin = NULL;
  694. ::DeleteObject(m_hBmpBkRightSpin);
  695. m_hBmpBkRightSpin = NULL;
  696. HBITMAP hBmpGlyph = NULL;
  697. CDC dcGlyph;
  698. dcGlyph.CreateCompatibleDC(NULL);
  699. CBitmap* pOldBmpGlyph = NULL;
  700. try
  701. {
  702. CThemeUtil tm;
  703. if(!tm.OpenThemeData(m_hWnd, L"SPIN"))
  704. AfxThrowUserException();
  705. {
  706. // left spin background
  707. int nBkType;
  708. if(!tm.GetThemeEnumValue(SPNP_DOWNHORZ,0,TMT_BGTYPE,&nBkType))
  709. AfxThrowUserException();
  710. if(nBkType!=BT_IMAGEFILE)
  711. AfxThrowUserException();
  712. int nImageCount;
  713. if(!tm.GetThemeInt(SPNP_DOWNHORZ,0,TMT_IMAGECOUNT,&nImageCount))
  714. AfxThrowUserException();
  715. if(nImageCount!=4)
  716. AfxThrowUserException();
  717. WCHAR szSpinBkLeftBitmapFilename[MAX_PATH];
  718. if(!tm.GetThemeFilename(SPNP_DOWNHORZ,0,TMT_IMAGEFILE,szSpinBkLeftBitmapFilename,MAX_PATH))
  719. AfxThrowUserException();
  720. m_hBmpBkLeftSpin = tm.LoadBitmap(szSpinBkLeftBitmapFilename);
  721. if(!m_hBmpBkLeftSpin)
  722. AfxThrowUserException();
  723. int nLeftImageLayout;
  724. if(!tm.GetThemeEnumValue(SPNP_DOWNHORZ,0,TMT_IMAGELAYOUT,&nLeftImageLayout))
  725. AfxThrowUserException();
  726. if(nLeftImageLayout==IL_VERTICAL)
  727. m_fIsLeftImageHorLayout = FALSE;
  728. else
  729. m_fIsLeftImageHorLayout = TRUE;
  730. if(!tm.GetThemeMargins(SPNP_DOWNHORZ,0,TMT_SIZINGMARGINS,&m_mrgnLeft))
  731. AfxThrowUserException();
  732. }
  733. {
  734. // right spin background
  735. int nBkType;
  736. if(!tm.GetThemeEnumValue(SPNP_UPHORZ,0,TMT_BGTYPE,&nBkType))
  737. AfxThrowUserException();
  738. if(nBkType!=BT_IMAGEFILE)
  739. AfxThrowUserException();
  740. int nImageCount;
  741. if(!tm.GetThemeInt(SPNP_UPHORZ,0,TMT_IMAGECOUNT,&nImageCount))
  742. AfxThrowUserException();
  743. if(nImageCount!=4)
  744. AfxThrowUserException();
  745. WCHAR szSpinBkRightBitmapFilename[MAX_PATH];
  746. if(!tm.GetThemeFilename(SPNP_UPHORZ,0,TMT_IMAGEFILE,szSpinBkRightBitmapFilename,MAX_PATH))
  747. AfxThrowUserException();
  748. m_hBmpBkRightSpin = tm.LoadBitmap(szSpinBkRightBitmapFilename);
  749. if(!m_hBmpBkRightSpin)
  750. AfxThrowUserException();
  751. int nRightImageLayout;
  752. if(!tm.GetThemeEnumValue(SPNP_UPHORZ,0,TMT_IMAGELAYOUT,&nRightImageLayout))
  753. AfxThrowUserException();
  754. if(nRightImageLayout==IL_VERTICAL)
  755. m_fIsRightImageHorLayout = FALSE;
  756. else
  757. m_fIsRightImageHorLayout = TRUE;
  758. if(!tm.GetThemeMargins(SPNP_UPHORZ,0,TMT_SIZINGMARGINS,&m_mrgnRight))
  759. AfxThrowUserException();
  760. }
  761. {
  762. // glyph color
  763. int nGlyphType;
  764. if(!tm.GetThemeEnumValue(SPNP_DOWNHORZ,0,TMT_GLYPHTYPE,&nGlyphType))
  765. AfxThrowUserException();
  766. if(nGlyphType==GT_IMAGEGLYPH)
  767. {
  768. COLORREF rgbTransGlyph = RGB(255,0,255);
  769. if(!tm.GetThemeColor(SPNP_DOWNHORZ,0,TMT_GLYPHTRANSPARENTCOLOR,&rgbTransGlyph))
  770. AfxThrowUserException();
  771. WCHAR szSpinGlyphIconFilename[MAX_PATH];
  772. if(!tm.GetThemeFilename(SPNP_DOWNHORZ,0,TMT_GLYPHIMAGEFILE,szSpinGlyphIconFilename,MAX_PATH))
  773. AfxThrowUserException();
  774. hBmpGlyph = tm.LoadBitmap(szSpinGlyphIconFilename);
  775. if(!hBmpGlyph)
  776. AfxThrowUserException();
  777. CBitmap* pBmp = CBitmap::FromHandle(hBmpGlyph);
  778. if(pBmp==NULL)
  779. AfxThrowUserException();
  780. pOldBmpGlyph = dcGlyph.SelectObject(pBmp);
  781. BITMAP bm;
  782. pBmp->GetBitmap(&bm);
  783. m_rgbGlyph[0] = rgbTransGlyph;
  784. m_rgbGlyph[1] = rgbTransGlyph;
  785. m_rgbGlyph[2] = rgbTransGlyph;
  786. m_rgbGlyph[3] = rgbTransGlyph;
  787. if(m_fIsLeftImageHorLayout)
  788. {
  789. for(int i=0;i<bm.bmWidth;i++)
  790. {
  791. if(i<bm.bmWidth/4 && m_rgbGlyph[0]==rgbTransGlyph)
  792. {
  793. for(int j=0;j<bm.bmHeight;j++)
  794. {
  795. if((m_rgbGlyph[0]=dcGlyph.GetPixel(i,j))!=rgbTransGlyph)
  796. break;
  797. }
  798. if(i==bm.bmWidth/4-1 && m_rgbGlyph[0]==rgbTransGlyph)
  799. AfxThrowUserException();
  800. }
  801. else if(i>=bm.bmWidth/4 && i<bm.bmWidth/2 && m_rgbGlyph[1]==rgbTransGlyph)
  802. {
  803. for(int j=0;j<bm.bmHeight;j++)
  804. {
  805. if((m_rgbGlyph[1]=dcGlyph.GetPixel(i,j))!=rgbTransGlyph)
  806. break;
  807. }
  808. if(i==bm.bmWidth/2-1 && m_rgbGlyph[1]==rgbTransGlyph)
  809. AfxThrowUserException();
  810. }
  811. else if(i>=bm.bmWidth/2 && i<3*bm.bmWidth/4 && m_rgbGlyph[2]==rgbTransGlyph)
  812. {
  813. for(int j=0;j<bm.bmHeight;j++)
  814. {
  815. if((m_rgbGlyph[2]=dcGlyph.GetPixel(i,j))!=rgbTransGlyph)
  816. break;
  817. }
  818. if(i==3*bm.bmWidth/4-1 && m_rgbGlyph[2]==rgbTransGlyph)
  819. AfxThrowUserException();
  820. }
  821. else if(i>=3*bm.bmWidth/4 && i<bm.bmWidth && m_rgbGlyph[3]==rgbTransGlyph)
  822. {
  823. for(int j=0;j<bm.bmHeight;j++)
  824. {
  825. if((m_rgbGlyph[3]=dcGlyph.GetPixel(i,j))!=rgbTransGlyph)
  826. break;
  827. }
  828. if(i==bm.bmWidth-1 && m_rgbGlyph[3]==rgbTransGlyph)
  829. AfxThrowUserException();
  830. }
  831. }
  832. }
  833. else
  834. {
  835. for(int i=0;i<bm.bmHeight;i++)
  836. {
  837. if(i<bm.bmHeight/4 && m_rgbGlyph[0]==rgbTransGlyph)
  838. {
  839. for(int j=0;j<bm.bmWidth;j++)
  840. {
  841. if((m_rgbGlyph[0] = dcGlyph.GetPixel(j,i))!=rgbTransGlyph)
  842. break;
  843. }
  844. if(i==bm.bmHeight/4-1 && m_rgbGlyph[0]==rgbTransGlyph)
  845. AfxThrowUserException();
  846. }
  847. else if(i>=bm.bmHeight/4 && i<bm.bmHeight/2 && m_rgbGlyph[1]==rgbTransGlyph)
  848. {
  849. for(int j=0;j<bm.bmWidth;j++)
  850. {
  851. if((m_rgbGlyph[1]=dcGlyph.GetPixel(j,i))!=rgbTransGlyph)
  852. break;
  853. }
  854. if(i==bm.bmHeight/2-1 && m_rgbGlyph[1]==rgbTransGlyph)
  855. AfxThrowUserException();
  856. }
  857. else if(i>=bm.bmHeight/2 && i<3*bm.bmHeight/4 && m_rgbGlyph[2]==rgbTransGlyph)
  858. {
  859. for(int j=0;j<bm.bmWidth;j++)
  860. {
  861. if((m_rgbGlyph[2] = dcGlyph.GetPixel(j,i))!=rgbTransGlyph)
  862. break;
  863. }
  864. if(i==3*bm.bmHeight/4-1 && m_rgbGlyph[2]==rgbTransGlyph)
  865. AfxThrowUserException();
  866. }
  867. else if(i>=3*bm.bmHeight/4 && i<bm.bmHeight && m_rgbGlyph[3]==rgbTransGlyph)
  868. {
  869. for(int j=0;j<bm.bmWidth;j++)
  870. {
  871. if((m_rgbGlyph[3]=dcGlyph.GetPixel(j,i))!=rgbTransGlyph)
  872. break;
  873. }
  874. if(i==bm.bmHeight-1 && m_rgbGlyph[3]==rgbTransGlyph)
  875. AfxThrowUserException();
  876. }
  877. }
  878. }
  879. dcGlyph.SelectObject(pOldBmpGlyph);
  880. pOldBmpGlyph = NULL;
  881. ::DeleteObject(hBmpGlyph);
  882. hBmpGlyph = NULL;
  883. }
  884. else if(nGlyphType==GT_FONTGLYPH)
  885. {
  886. if(!tm.GetThemeColor(SPNP_UPHORZ,UPHZS_NORMAL,TMT_GLYPHTEXTCOLOR,&m_rgbGlyph[0]))
  887. AfxThrowUserException();
  888. if(!tm.GetThemeColor(SPNP_UPHORZ,UPHZS_HOT,TMT_GLYPHTEXTCOLOR,&m_rgbGlyph[1]))
  889. AfxThrowUserException();
  890. if(!tm.GetThemeColor(SPNP_UPHORZ,UPHZS_PRESSED,TMT_GLYPHTEXTCOLOR,&m_rgbGlyph[2]))
  891. AfxThrowUserException();
  892. }
  893. else
  894. AfxThrowUserException();
  895. }
  896. tm.CloseThemeData();
  897. }
  898. catch(CUserException* e)
  899. {
  900. e->Delete();
  901. ::DeleteObject(m_hBmpBkLeftSpin);
  902. m_hBmpBkLeftSpin = NULL;
  903. ::DeleteObject(m_hBmpBkRightSpin);
  904. m_hBmpBkRightSpin = NULL;
  905. if(pOldBmpGlyph)
  906. dcGlyph.SelectObject(pOldBmpGlyph);
  907. ::DeleteObject(hBmpGlyph);
  908. hBmpGlyph = NULL;
  909. }
  910. return 0;
  911. void CCustomTabCtrl::SetControlFont(const LOGFONT& lf, BOOL fRedraw)
  912. {
  913. if(m_Font.m_hObject)
  914. {
  915. DeleteObject(m_Font);
  916. m_Font.m_hObject = NULL;
  917. }
  918. if(m_FontSelected.m_hObject)
  919. {
  920. DeleteObject(m_FontSelected);
  921. m_FontSelected.m_hObject = NULL;
  922. }
  923. if(!m_Font.CreateFontIndirect(&lf))
  924. m_Font.CreateFontIndirect(&lf_default);
  925. LOGFONT lfSel;
  926. m_Font.GetLogFont(&lfSel);
  927. lfSel.lfWeight = FW_BOLD;
  928. m_FontSelected.CreateFontIndirect(&lfSel);
  929. if(fRedraw)
  930. {
  931. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  932. Invalidate();
  933. }
  934. }
  935. int CCustomTabCtrl::InsertItem(int nItem, CString sText, LPARAM lParam)
  936. {
  937. if(nItem<0 || nItem>m_aItems.GetSize())
  938. return CTCERR_INDEXOUTOFRANGE;
  939. if(sText.GetLength()>MAX_LABEL_TEXT-1)
  940. return CTCERR_TEXTTOOLONG;
  941. CCustomTabCtrlItem* pItem = new CCustomTabCtrlItem(sText,lParam);
  942. if(pItem==NULL)
  943. return CTCERR_OUTOFMEMORY;
  944. try
  945. {
  946. m_aItems.InsertAt(nItem,pItem);
  947. }
  948. catch(CMemoryException* e)
  949. {
  950. e->Delete();
  951. delete pItem;
  952. return CTCERR_OUTOFMEMORY;
  953. }
  954. if(m_nItemSelected>=nItem)
  955. m_nItemSelected++;
  956. if(m_ctrlToolTip.m_hWnd)
  957. {
  958. for(int i=m_aItems.GetSize()-1; i>nItem; i--)
  959. {
  960. CString s;
  961. m_ctrlToolTip.GetText(s,this,i);
  962. m_ctrlToolTip.DelTool(this,i);
  963. m_ctrlToolTip.AddTool(this,s,CRect(0,0,0,0),i+1);
  964. }
  965. m_ctrlToolTip.DelTool(this,nItem+1);
  966. }
  967. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  968. Invalidate(FALSE);
  969. DrawBorderLines(this->m_BorderLine);
  970. return nItem;
  971. }
  972. int CCustomTabCtrl::MoveItem(int nItemSrc, int nItemDst)
  973. {
  974. return MoveItem(nItemSrc, nItemDst, FALSE);
  975. }
  976. int CCustomTabCtrl::MoveItem(int nItemSrc, int nItemDst, BOOL fMouseSel)
  977. {
  978. if(nItemSrc<0||nItemSrc>=m_aItems.GetSize())
  979. return CTCERR_INDEXOUTOFRANGE;
  980. if(nItemDst<0||nItemDst>m_aItems.GetSize())
  981. return CTCERR_INDEXOUTOFRANGE;
  982. if(nItemSrc==nItemDst || nItemSrc==nItemDst-1)
  983. return nItemSrc;
  984. CCustomTabCtrlItem *pItem = m_aItems[nItemSrc];
  985. // remove item from old place
  986. CString sOldTooltip;
  987. if(m_ctrlToolTip.m_hWnd)
  988. {
  989. m_ctrlToolTip.GetText(sOldTooltip,this,nItemSrc+1);
  990. for(int i=nItemSrc+1; i< m_aItems.GetSize(); i++)
  991. {
  992. CString s;
  993. m_ctrlToolTip.GetText(s,this,i+1);
  994. m_ctrlToolTip.DelTool(this,i);
  995. m_ctrlToolTip.AddTool(this,s,CRect(0,0,0,0),i);
  996. }
  997. }
  998. m_aItems.RemoveAt(nItemSrc);
  999. // insert item in new place
  1000. if(nItemDst>nItemSrc)
  1001. nItemDst--;
  1002. try
  1003. {
  1004. m_aItems.InsertAt(nItemDst,pItem);
  1005. }
  1006. catch(CMemoryException* e)
  1007. {
  1008. e->Delete();
  1009. delete pItem;
  1010. if(fMouseSel)
  1011. NotifyParent(CTCN_ITEMMOVE,nItemSrc,CPoint(0,0));
  1012. return CTCERR_OUTOFMEMORY;
  1013. }
  1014. if(m_ctrlToolTip.m_hWnd)
  1015. {
  1016. for(int i=m_aItems.GetSize()-1; i>nItemDst; i--)
  1017. {
  1018. CString s;
  1019. m_ctrlToolTip.GetText(s,this,i);
  1020. m_ctrlToolTip.DelTool(this,i+1);
  1021. m_ctrlToolTip.AddTool(this,s,CRect(0,0,0,0),i+1);
  1022. }
  1023. m_ctrlToolTip.DelTool(this,nItemDst+1);
  1024. m_ctrlToolTip.AddTool(this,sOldTooltip,CRect(0,0,0,0),nItemDst+1);
  1025. }
  1026. m_nItemSelected = nItemDst;
  1027. RecalcLayout(RECALC_ITEM_SELECTED,m_nItemSelected);
  1028. Invalidate(FALSE);
  1029. if(fMouseSel)
  1030. NotifyParent(CTCN_ITEMMOVE,m_nItemSelected,CPoint(0,0));
  1031. return nItemDst;
  1032. }
  1033. int CCustomTabCtrl::CopyItem(int nItemSrc, int nItemDst)
  1034. {
  1035. return CopyItem(nItemSrc, nItemDst, FALSE);
  1036. }
  1037. int CCustomTabCtrl::CopyItem(int nItemSrc, int nItemDst, BOOL fMouseSel)
  1038. {
  1039. if(nItemSrc<0||nItemSrc>=m_aItems.GetSize())
  1040. return CTCERR_INDEXOUTOFRANGE;
  1041. if(nItemDst<0||nItemDst>m_aItems.GetSize())
  1042. return CTCERR_INDEXOUTOFRANGE;
  1043. CString sDst;
  1044. try
  1045. {
  1046. BOOL bAppendFlag=TRUE;
  1047. int n = m_aItems[nItemSrc]->m_sText.GetLength();
  1048. if(n>=4)
  1049. {
  1050. if(m_aItems[nItemSrc]->m_sText[n-1]==_T(')') && 
  1051. m_aItems[nItemSrc]->m_sText[n-2]>_T('1') &&
  1052. m_aItems[nItemSrc]->m_sText[n-2]<=_T('9') &&
  1053. m_aItems[nItemSrc]->m_sText[n-3]==_T('('))
  1054. {
  1055. n = m_aItems[nItemSrc]->m_sText.GetLength()-3;
  1056. bAppendFlag = FALSE;
  1057. }
  1058. else if(m_aItems[nItemSrc]->m_sText[n-1]==_T(')') && 
  1059. m_aItems[nItemSrc]->m_sText[n-2]>=_T('0') &&
  1060. m_aItems[nItemSrc]->m_sText[n-2]<=_T('9') &&
  1061. m_aItems[nItemSrc]->m_sText[n-3]>=_T('1') &&
  1062. m_aItems[nItemSrc]->m_sText[n-3]<=_T('9') &&
  1063. m_aItems[nItemSrc]->m_sText[n-4]==_T('('))
  1064. {
  1065. n = m_aItems[nItemSrc]->m_sText.GetLength()-4;
  1066. bAppendFlag = FALSE;
  1067. }
  1068. }
  1069. int ndx = 1;
  1070. while(1)
  1071. {
  1072. ndx++;
  1073. if(bAppendFlag)
  1074. sDst.Format(_T("%s (%d)"),(LPCTSTR)m_aItems[nItemSrc]->m_sText,ndx);
  1075. else
  1076. sDst.Format(_T("%s(%d)"),(LPCTSTR)m_aItems[nItemSrc]->m_sText.Left(n),ndx);
  1077. for(int i=0;i<m_aItems.GetSize();i++)
  1078. {
  1079. if(m_aItems[i]->m_sText==sDst)
  1080. break;
  1081. }
  1082. if(i==m_aItems.GetSize())
  1083. break;
  1084. }
  1085. }
  1086. catch(CMemoryException* e)
  1087. {
  1088. e->Delete();
  1089. if(fMouseSel)
  1090. NotifyParent(CTCN_OUTOFMEMORY,nItemSrc,CPoint(0,0));
  1091. return CTCERR_OUTOFMEMORY;
  1092. }
  1093. int nRetItem = InsertItem(nItemDst,sDst,m_aItems[nItemSrc]->m_lParam);
  1094. if(nRetItem>=0)
  1095. {
  1096. SetCurSel(nRetItem);
  1097. if(fMouseSel)
  1098. NotifyParent(CTCN_ITEMCOPY,nRetItem,CPoint(0,0));
  1099. }
  1100. else if(fMouseSel && nRetItem==CTCERR_OUTOFMEMORY)
  1101. NotifyParent(CTCN_OUTOFMEMORY,nRetItem,CPoint(0,0));
  1102. return nRetItem;
  1103. }
  1104. int CCustomTabCtrl::DeleteItem(int nItem)
  1105. {
  1106. if(nItem<0 || nItem>=m_aItems.GetSize())
  1107. return CTCERR_INDEXOUTOFRANGE;
  1108. try
  1109. {
  1110. if(m_ctrlToolTip.m_hWnd)
  1111. {
  1112. for(int i=nItem; i<m_aItems.GetSize(); i++)
  1113. {
  1114. m_ctrlToolTip.DelTool(this,i+1);
  1115. if(i!=m_aItems.GetSize()-1)
  1116. {
  1117. CString s;
  1118. m_ctrlToolTip.GetText(s,this,i+2);
  1119. m_ctrlToolTip.AddTool(this,s,CRect(0,0,0,0),i+1);
  1120. }
  1121. }
  1122. }
  1123. }
  1124. catch(CMemoryException* e)
  1125. {
  1126. e->Delete();
  1127. return CTCERR_OUTOFMEMORY;
  1128. }
  1129. if(m_aItems.GetSize()==1)
  1130. m_nItemSelected = -1;
  1131. else if(m_nItemSelected==nItem)
  1132. {
  1133. if(m_nItemSelected==m_aItems.GetSize()-1) // last item
  1134. {
  1135. m_nItemSelected--;
  1136. m_aItems[m_nItemSelected]->m_fSelected = TRUE;
  1137. }
  1138. else
  1139. m_aItems[m_nItemSelected+1]->m_fSelected = TRUE;
  1140. }
  1141. else if(m_nItemSelected>nItem)
  1142. m_nItemSelected--;
  1143. delete m_aItems[nItem];
  1144. m_aItems.RemoveAt(nItem);
  1145. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  1146. Invalidate(FALSE);
  1147. return CTCERR_NOERROR;
  1148. }
  1149. void CCustomTabCtrl::DeleteAllItems()
  1150. {
  1151. if(m_ctrlToolTip.m_hWnd)
  1152. {
  1153. for(int i=0; i< m_aItems.GetSize(); i++)
  1154. {
  1155. delete m_aItems[i];
  1156. m_ctrlToolTip.DelTool(this,i+1);
  1157. }
  1158. }
  1159. else
  1160. {
  1161. for(int i=0; i< m_aItems.GetSize(); i++)
  1162. delete m_aItems[i];
  1163. }
  1164. m_aItems.RemoveAll();
  1165. m_nItemSelected = -1;
  1166. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  1167. Invalidate(FALSE);
  1168. }
  1169. int CCustomTabCtrl::SetCurSel(int nItem)
  1170. {
  1171. return SetCurSel(nItem,FALSE,FALSE);
  1172. }
  1173. int CCustomTabCtrl::HighlightItem(int nItem, BOOL fHighlight)
  1174. {
  1175. if(!(GetStyle()&CTCS_MULTIHIGHLIGHT))
  1176. return CTCERR_NOMULTIHIGHLIGHTSTYLE;
  1177. if(nItem<0 || nItem>=m_aItems.GetSize())
  1178. return CTCERR_INDEXOUTOFRANGE;
  1179. if(m_nItemSelected==-1 && !fHighlight)
  1180. return CTCERR_NOERROR;
  1181. if(m_nItemSelected==-1)
  1182. {
  1183. SetCurSel(nItem);
  1184. return CTCERR_NOERROR;
  1185. }
  1186. if(fHighlight==m_aItems[nItem]->m_fHighlighted || nItem==m_nItemSelected)
  1187. return CTCERR_NOERROR;
  1188. m_aItems[nItem]->m_fHighlighted = fHighlight;
  1189. return CTCERR_NOERROR;
  1190. }
  1191. int CCustomTabCtrl::GetItemText(int nItem, CString& sText)
  1192. {
  1193. if(nItem<0 || nItem>=m_aItems.GetSize())
  1194. return CTCERR_INDEXOUTOFRANGE;
  1195. sText = m_aItems[nItem]->m_sText;
  1196. return CTCERR_NOERROR;
  1197. }
  1198. int CCustomTabCtrl::SetItemText(int nItem, CString sText)
  1199. {
  1200. if(nItem<0 || nItem>=m_aItems.GetSize())
  1201. return CTCERR_INDEXOUTOFRANGE;
  1202. m_aItems[nItem]->m_sText = sText;
  1203. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  1204. Invalidate(FALSE);
  1205. return CTCERR_NOERROR;
  1206. }
  1207. int CCustomTabCtrl::SetItemTooltipText(int nItem, CString sText)
  1208. {
  1209. if(!(GetStyle()&CTCS_TOOLTIPS))
  1210. return CTCERR_NOTOOLTIPSSTYLE;
  1211. if(nItem>=CTCID_NOBUTTON && nItem<m_aItems.GetSize())
  1212. {
  1213. if(m_ctrlToolTip.m_hWnd==NULL)
  1214. {
  1215. if(!m_ctrlToolTip.Create(this))
  1216. return CTCERR_CREATETOOLTIPFAILED;
  1217. m_ctrlToolTip.Activate(TRUE);
  1218. }
  1219. if(nItem>=0)
  1220. nItem++;
  1221. m_ctrlToolTip.DelTool(this,nItem);
  1222. m_ctrlToolTip.AddTool(this,sText,CRect(0,0,0,0),nItem);
  1223. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  1224. Invalidate(FALSE);
  1225. return CTCERR_NOERROR;
  1226. }
  1227. return CTCERR_INDEXOUTOFRANGE;
  1228. }
  1229. int CCustomTabCtrl::GetItemData(int nItem, DWORD& dwData)
  1230. {
  1231. if(nItem<0 || nItem>=m_aItems.GetSize())
  1232. return CTCERR_INDEXOUTOFRANGE;
  1233. dwData = m_aItems[nItem]->m_lParam;
  1234. return CTCERR_NOERROR;
  1235. }
  1236. int CCustomTabCtrl::GetItemRect(int nItem, CRect& rect) const
  1237. {
  1238. if(nItem<0 || nItem>=m_aItems.GetSize())
  1239. return CTCERR_INDEXOUTOFRANGE;
  1240. rect = m_aItems[nItem]->m_rectText;
  1241. return CTCERR_NOERROR;
  1242. }
  1243. int CCustomTabCtrl::SetItemData(int nItem, DWORD dwData)
  1244. {
  1245. if(nItem<0 || nItem>=m_aItems.GetSize())
  1246. return CTCERR_INDEXOUTOFRANGE;
  1247. m_aItems[nItem]->m_lParam = dwData;
  1248. return CTCERR_NOERROR;
  1249. }
  1250. int CCustomTabCtrl::IsItemHighlighted(int nItem)
  1251. {
  1252. if(nItem<0 || nItem>=m_aItems.GetSize())
  1253. return CTCERR_INDEXOUTOFRANGE;
  1254. return (m_aItems[nItem]->m_fHighlighted)?1:0;
  1255. }
  1256. int CCustomTabCtrl::HitTest(CPoint pt)
  1257. {
  1258. CRect rCl;
  1259. GetClientRect(&rCl);
  1260. if(IsVertical())
  1261. {
  1262. rCl.SetRect(0,0,rCl.Height(),rCl.Width());
  1263. pt = CPoint(rCl.Width()-pt.y,pt.x);
  1264. }
  1265.  
  1266. CRect rFirst,rPrev,rNext,rLast; 
  1267.  
  1268. for(int i=0; i<m_aItems.GetSize(); i++)
  1269. {
  1270. if(m_aItems[i]->HitTest(pt))
  1271. return i;
  1272. }
  1273. int CCustomTabCtrl::HighlightItem(int nItem, BOOL fMouseSel, BOOL fCtrlPressed)
  1274. {
  1275. if(!(GetStyle()&CTCS_MULTIHIGHLIGHT))
  1276. return CTCERR_NOMULTIHIGHLIGHTSTYLE;
  1277. for(int i=0; i<m_aItems.GetSize();i++)
  1278. m_aItems[i]->m_fHighlightChanged = FALSE;
  1279. if(fCtrlPressed)
  1280. {
  1281. if(nItem!=m_nItemSelected)
  1282. {
  1283. m_aItems[nItem]->m_fHighlighted = !m_aItems[nItem]->m_fHighlighted;
  1284. if(fMouseSel)
  1285. m_aItems[nItem]->m_fHighlightChanged = TRUE;
  1286. }
  1287. }
  1288. else if(!m_aItems[nItem]->m_fHighlighted)
  1289. {
  1290. m_aItems[nItem]->m_fHighlighted = TRUE;
  1291. m_aItems[nItem]->m_fHighlightChanged = TRUE;
  1292. for(int i=0;i<m_aItems.GetSize();i++)
  1293. {
  1294. if(i!=m_nItemSelected)
  1295. {
  1296. if(m_aItems[i]->m_fHighlighted)
  1297. {
  1298. m_aItems[i]->m_fHighlighted = FALSE;
  1299. if(fMouseSel)
  1300. m_aItems[i]->m_fHighlightChanged = TRUE;
  1301. }
  1302. }
  1303. }
  1304. }
  1305. if(fMouseSel)
  1306. RecalcLayout(RECALC_ITEM_SELECTED,nItem);
  1307. Invalidate(FALSE);
  1308. return CTCERR_NOERROR;
  1309. }
  1310. int CCustomTabCtrl::SetCurSel(int nItem, BOOL fMouseSel, BOOL fCtrlPressed)
  1311. {
  1312. if(nItem<0 || nItem>=m_aItems.GetSize())
  1313. return CTCERR_INDEXOUTOFRANGE;
  1314. if(m_nItemSelected!=-1)
  1315. m_aItems[m_nItemSelected]->m_fSelected = FALSE;
  1316. m_nItemSelected = nItem;
  1317. if(m_nItemSelected!=-1)
  1318. m_aItems[m_nItemSelected]->m_fSelected = TRUE;
  1319. if(fMouseSel)
  1320. RecalcLayout(RECALC_ITEM_SELECTED,m_nItemSelected);
  1321. else
  1322. {
  1323. m_nItemNdxOffset = nItem;
  1324. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  1325. }
  1326. Invalidate(FALSE);
  1327. HighlightItem(nItem, fMouseSel, fCtrlPressed);
  1328. return CTCERR_NOERROR;
  1329. }
  1330. void CCustomTabCtrl::RecalcLayout(int nRecalcType, int nItem)
  1331. {
  1332. CRect rCl;
  1333. GetClientRect(&rCl);
  1334. if(IsVertical())
  1335. rCl.SetRect(0,0,rCl.Height(),rCl.Width());
  1336.  
  1337. int nWidth = RecalcRectangles();
  1338. if(m_aItems.GetSize()<2 || nWidth <= rCl.Width())
  1339. {
  1340.  
  1341. m_nItemNdxOffset = 0;
  1342. RecalcOffset(0);
  1343. if(nRecalcType==RECALC_EDIT_RESIZED)
  1344. RecalcEditResized(0,nItem); 
  1345. return;
  1346. }
  1347.  
  1348. if(m_aItems.GetSize()==0)
  1349. return;
  1350.  
  1351. switch(nRecalcType)
  1352. {
  1353. case RECALC_CLOSE_PRESSED:
  1354. RecalcRectangles();
  1355. RecalcOffset(0);
  1356. break;
  1357. case RECALC_FIRST_PRESSED:
  1358. {
  1359. m_nItemNdxOffset=0;
  1360. RecalcRectangles();
  1361. RecalcOffset(0);
  1362. }
  1363. break;
  1364. case RECALC_PREV_PRESSED:
  1365. {
  1366. RecalcOffset(0);
  1367. if(m_nItemNdxOffset>0)
  1368. {
  1369. m_nItemNdxOffset--;
  1370. RecalcRectangles();
  1371. RecalcOffset(0);
  1372. }
  1373. }
  1374. break;
  1375. case RECALC_NEXT_PRESSED:
  1376. {
  1377. RecalcOffset(0);
  1378. if(m_aItems[m_aItems.GetSize()-1]->m_rect.right>rCl.Width() && m_nItemNdxOffset!=m_aItems.GetSize()-1)
  1379. {
  1380. m_nItemNdxOffset++;
  1381. RecalcRectangles();
  1382. RecalcOffset(0);
  1383. }
  1384. }
  1385. break;
  1386. case RECALC_ITEM_SELECTED:
  1387. {
  1388. RecalcOffset(0);
  1389. if(m_aItems[nItem]->m_bShape==TAB_SHAPE2 || m_aItems[nItem]->m_bShape==TAB_SHAPE3)
  1390. {
  1391. m_nItemNdxOffset--;
  1392. RecalcRectangles();
  1393. RecalcOffset(0);
  1394. }
  1395. else
  1396. {
  1397. while(m_nItemNdxOffset<nItem && 
  1398. m_aItems[nItem]->m_bShape==TAB_SHAPE4 && 
  1399. m_aItems[nItem]->m_rect.right>rCl.Width() && 
  1400. m_aItems[nItem]->m_rect.left>(0))
  1401. {
  1402. m_nItemNdxOffset++;
  1403. RecalcRectangles();
  1404. RecalcOffset(0);
  1405. }
  1406. }
  1407. }
  1408. break;
  1409. case RECALC_EDIT_RESIZED:
  1410. {
  1411. RecalcOffset(0);
  1412. RecalcEditResized(0,nItem);
  1413. }
  1414. break;
  1415. case RECALC_LAST_PRESSED:
  1416. {
  1417. m_nItemNdxOffset=m_aItems.GetSize()-1;
  1418. }
  1419. default: // window resized
  1420. {
  1421. BOOL bNdxOffsetChanged = FALSE;
  1422. RecalcOffset(0);
  1423. while(m_nItemNdxOffset>=0 && m_aItems[m_aItems.GetSize()-1]->m_rect.right<rCl.Width())
  1424. {
  1425. m_nItemNdxOffset--;
  1426. if(m_nItemNdxOffset>=0)
  1427. {
  1428. RecalcRectangles();
  1429. RecalcOffset(0);
  1430. }
  1431. bNdxOffsetChanged = TRUE;
  1432. }
  1433. if(bNdxOffsetChanged)
  1434. {
  1435. m_nItemNdxOffset++;
  1436. RecalcRectangles();
  1437. RecalcOffset(0);
  1438. }
  1439. }
  1440. break;
  1441. }
  1442. }
  1443. void CCustomTabCtrl::RecalcEditResized(int nOffset, int nItem)
  1444. {
  1445. CRect rCl;
  1446. GetClientRect(rCl);
  1447.  
  1448. do
  1449. {
  1450. CRect r;
  1451. CDC* pDC = GetDC();
  1452. CFont* pOldFont = pDC->SelectObject(&m_FontSelected);
  1453. int h = pDC->DrawText(m_aItems[nItem]->m_sText+"X", r, DT_CALCRECT);
  1454. pDC->SelectObject(pOldFont);
  1455. ReleaseDC(pDC);
  1456. r = m_aItems[nItem]->m_rectText;
  1457. if(r.Height()>h)
  1458. {
  1459. r.top += (r.Height()-h)/2;
  1460. r.bottom -= (r.Height()-h)/2;
  1461. }
  1462. r.left += 2;
  1463. if(r.right>rCl.right && m_nItemSelected>m_nItemNdxOffset)
  1464. {
  1465. m_nItemNdxOffset++;
  1466. RecalcRectangles();
  1467. RecalcOffset(nOffset);
  1468. }
  1469. else
  1470. {
  1471. if(r.right>rCl.right)
  1472. r.right = rCl.right;
  1473. m_ctrlEdit.MoveWindow(r);
  1474. int n = m_aItems[nItem]->m_sText.GetLength();
  1475. int nStart, nEnd;
  1476. m_ctrlEdit.GetSel(nStart,nEnd);
  1477. if(nStart==nEnd && nStart==n)
  1478. {
  1479. m_ctrlEdit.SetSel(0,0);
  1480. m_ctrlEdit.SetSel(n,n);
  1481. }
  1482. return;
  1483. }
  1484. while(1);
  1485. }
  1486. void CCustomTabCtrl::RecalcOffset(int nOffset)
  1487. {
  1488. CRect rCl;
  1489. GetClientRect(&rCl);
  1490. if(IsVertical())
  1491. rCl.SetRect(0,0,rCl.Height(),rCl.Width());
  1492. int rightAdjusment = 0;
  1493.  
  1494. for(int i = 0; i<m_aItems.GetSize(); i++)
  1495. {
  1496. if(i<m_nItemNdxOffset-1)
  1497. {
  1498. m_aItems[i]->m_bShape = TAB_SHAPE1;
  1499. nOffset -= m_aItems[i]->m_rect.Width()-rCl.Height()/2;
  1500. m_aItems[i]->m_rectText.SetRectEmpty();
  1501. }
  1502. else if(i==m_nItemNdxOffset-1)
  1503. if(i==m_nItemSelected)
  1504. m_aItems[i]->m_bShape = TAB_SHAPE2;
  1505. else
  1506. m_aItems[i]->m_bShape = TAB_SHAPE3;
  1507. nOffset -= m_aItems[i]->m_rect.Width()-rCl.Height()/2;
  1508. m_aItems[i]->m_rect.SetRect(0,1,rCl.Height()/2,rCl.Height()-1);
  1509.  
  1510. m_aItems[i]->m_rectText.SetRectEmpty();
  1511. }
  1512. else
  1513. {
  1514. if(i==m_nItemSelected)
  1515. m_aItems[i]->m_bShape = TAB_SHAPE4;
  1516. else if(i==m_aItems.GetSize()-1) // last item
  1517. m_aItems[i]->m_bShape = TAB_SHAPE4;
  1518. else
  1519. m_aItems[i]->m_bShape = TAB_SHAPE5;
  1520. m_aItems[i]->m_rect.OffsetRect(nOffset,0);
  1521. m_aItems[i]->m_rectText.OffsetRect(nOffset,0);
  1522. }
  1523. m_aItems[i]->ComputeRgn(GetStyle()&CTCS_TOP);
  1524. if(m_ctrlToolTip.m_hWnd)
  1525. {
  1526. CRect rT = m_aItems[i]->m_rectText;
  1527. if(rT.left>=rCl.Width()-rightAdjusment)
  1528. rT.SetRect(0,0,0,0);
  1529. else if(rT.right>rCl.Width()-rightAdjusment)
  1530. rT.right = rCl.right-rightAdjusment;
  1531. if(IsVertical())
  1532. rT.SetRect(0,rCl.Width()-rT.right,rCl.Height(),rCl.Width()-rT.left);
  1533. m_ctrlToolTip.SetToolRect(this,i+1,rT);
  1534. }
  1535. }
  1536. }
  1537. int CCustomTabCtrl::RecalcRectangles()
  1538. {
  1539. CRect rCl;
  1540. GetClientRect(&rCl);
  1541. if(IsVertical())
  1542. rCl.SetRect(0,0,rCl.Height(),rCl.Width());
  1543. BOOL fTop = GetStyle()&CTCS_TOP;
  1544. int nWidth = 0; 
  1545. // calculate width
  1546. int nOffset = 0;
  1547. CRect rcText;
  1548. CDC* pDC = GetDC();
  1549. CFont* pOldFont = pDC->SelectObject(&m_FontSelected);
  1550. if(GetStyle()&CTCS_FIXEDWIDTH)
  1551. {
  1552. int nMaxWidth=0;
  1553. //先算出最大的距离
  1554. for(int i=0; i<m_aItems.GetSize(); i++)
  1555. {
  1556. int w=0;
  1557. int h = pDC->DrawText(m_aItems[i]->m_sText, rcText, DT_CALCRECT);
  1558. if(h>0)
  1559. w = rcText.Width();
  1560. if(w>nMaxWidth)
  1561. nMaxWidth = w;
  1562. }
  1563. //if(nMaxWidth * m_aItems.GetSize() > rCl.Width())
  1564. // nMaxWidth =  rCl.Width()/m_aItems.GetSize()+1;
  1565. for(i=0; i<m_aItems.GetSize(); i++)
  1566. {
  1567. if(fTop)
  1568. {
  1569. m_aItems[i]->m_rect     = CRect(0,0,nMaxWidth+rCl.Height()+4,rCl.Height()-2);
  1570. m_aItems[i]->m_rectText = CRect(rCl.Height()/2,0,nMaxWidth+rCl.Height()/2+4,rCl.Height()-2);
  1571. }
  1572. else
  1573. {
  1574. m_aItems[i]->m_rect     = CRect(0,1,nMaxWidth+rCl.Height()+4,rCl.Height()-1);
  1575. m_aItems[i]->m_rectText = CRect(rCl.Height()/2,1,nMaxWidth+rCl.Height()/2+4,rCl.Height()-1);
  1576. }
  1577. m_aItems[i]->m_rect     += CPoint(nOffset,0);
  1578. m_aItems[i]->m_rectText += CPoint(nOffset,0);
  1579. nOffset += m_aItems[i]->m_rect.Width()-rCl.Height()/2;
  1580. nWidth   = m_aItems[i]->m_rect.right;
  1581. }
  1582. }
  1583. else
  1584. {
  1585. for(int i= 0; i<m_aItems.GetSize(); i++)
  1586. {
  1587. int w=0;
  1588. int h = pDC->DrawText(m_aItems[i]->m_sText, rcText, DT_CALCRECT);
  1589. if(h>0)
  1590. w = rcText.Width();
  1591. if(fTop)
  1592. {
  1593. m_aItems[i]->m_rect = CRect(0,0,w+rCl.Height()+4,rCl.Height()-2);
  1594. m_aItems[i]->m_rectText = CRect(rCl.Height()/2,0,w+rCl.Height()/2+4,rCl.Height()-2);
  1595. }
  1596. else
  1597. {
  1598. m_aItems[i]->m_rect = CRect(0,1,w+rCl.Height()+4,rCl.Height()-1);
  1599. m_aItems[i]->m_rectText = CRect(rCl.Height()/2,1,w+rCl.Height()/2+4,rCl.Height()-1);
  1600. }
  1601. m_aItems[i]->m_rect += CPoint(nOffset,0);
  1602. m_aItems[i]->m_rectText += CPoint(nOffset,0);
  1603. nOffset += m_aItems[i]->m_rect.Width()-rCl.Height()/2;
  1604. nWidth = m_aItems[i]->m_rect.right;
  1605. }
  1606. }
  1607. pDC->SelectObject(pOldFont);
  1608. ReleaseDC(pDC); 
  1609. return nWidth;
  1610. }
  1611. BOOL CCustomTabCtrl::PreTranslateMessage(MSG* pMsg)
  1612. {
  1613. if(GetStyle()&CTCS_TOOLTIPS && m_ctrlToolTip.m_hWnd && 
  1614. (pMsg->message==WM_LBUTTONDOWN || pMsg->message==WM_LBUTTONUP || pMsg->message==WM_MOUSEMOVE))
  1615. m_ctrlToolTip.RelayEvent(pMsg);
  1616. return CWnd::PreTranslateMessage(pMsg);
  1617. }
  1618. void CCustomTabCtrl::DrawBk(CDC& dc, CRect& r, HBITMAP hBmp, BOOL fIsImageHorLayout, MY_MARGINS& mrgn, int nImageNdx)
  1619. {
  1620. CDC dcMem;
  1621. dcMem.CreateCompatibleDC(&dc);
  1622. CBitmap* pBmp = CBitmap::FromHandle(hBmp);
  1623. BITMAP bm;
  1624. pBmp->GetBitmap(&bm);
  1625. CBitmap* pOldBmp = dcMem.SelectObject(pBmp);
  1626. if(fIsImageHorLayout)
  1627. {
  1628. // left-top
  1629. dc.BitBlt(r.left,
  1630. r.top,
  1631. mrgn.cxLeftWidth,
  1632. mrgn.cyTopHeight,
  1633. &dcMem,
  1634. nImageNdx*bm.bmWidth/4,
  1635. 0,
  1636. SRCCOPY);
  1637. // right-top
  1638. dc.BitBlt(r.right-mrgn.cxRightWidth,
  1639. r.top,
  1640. mrgn.cxRightWidth,
  1641. mrgn.cyTopHeight,
  1642. &dcMem,
  1643. (nImageNdx+1)*bm.bmWidth/4-mrgn.cxRightWidth,
  1644. 0,
  1645. SRCCOPY);
  1646. // left-bottom
  1647. dc.BitBlt(r.left,
  1648. r.bottom-mrgn.cyBottomHeight,
  1649. mrgn.cxLeftWidth,
  1650. mrgn.cyBottomHeight,
  1651. &dcMem,
  1652. nImageNdx*bm.bmWidth/4,
  1653. bm.bmHeight-mrgn.cyBottomHeight,
  1654. SRCCOPY);
  1655. // right-bottom
  1656. dc.BitBlt(r.right-mrgn.cxRightWidth,
  1657. r.bottom-mrgn.cyBottomHeight,
  1658. mrgn.cxRightWidth,
  1659. mrgn.cyBottomHeight,
  1660. &dcMem,
  1661. (nImageNdx+1)*bm.bmWidth/4-mrgn.cxRightWidth,
  1662. bm.bmHeight-mrgn.cyBottomHeight,
  1663. SRCCOPY);
  1664. // middle-top
  1665. dc.StretchBlt(r.left+mrgn.cxLeftWidth,
  1666. r.top,
  1667. r.Width()-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1668. mrgn.cyTopHeight,
  1669. &dcMem,
  1670. nImageNdx*bm.bmWidth/4+mrgn.cxLeftWidth,
  1671. 0,
  1672. bm.bmWidth/4-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1673. mrgn.cyTopHeight,
  1674. SRCCOPY);
  1675. // middle-bottom
  1676. dc.StretchBlt(r.left+mrgn.cxLeftWidth,
  1677. r.bottom-mrgn.cyBottomHeight,
  1678. r.Width()-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1679. mrgn.cyBottomHeight,
  1680. &dcMem,
  1681. nImageNdx*bm.bmWidth/4+mrgn.cxLeftWidth,
  1682. bm.bmHeight-mrgn.cyBottomHeight,
  1683. bm.bmWidth/4-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1684. mrgn.cyBottomHeight,
  1685. SRCCOPY);
  1686. // middle-left
  1687. dc.StretchBlt(r.left,
  1688. r.top+mrgn.cyTopHeight,
  1689. mrgn.cxLeftWidth,
  1690. r.Height()-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1691. &dcMem,
  1692. nImageNdx*bm.bmWidth/4,
  1693. mrgn.cyTopHeight,
  1694. mrgn.cxLeftWidth,
  1695. bm.bmHeight-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1696. SRCCOPY);
  1697. // middle-right
  1698. dc.StretchBlt(r.right-mrgn.cxRightWidth,
  1699. r.top+mrgn.cyTopHeight,
  1700. mrgn.cxRightWidth,
  1701. r.Height()-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1702. &dcMem,
  1703. (nImageNdx+1)*bm.bmWidth/4-mrgn.cxRightWidth,
  1704. mrgn.cyTopHeight,
  1705. mrgn.cxRightWidth,
  1706. bm.bmHeight-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1707. SRCCOPY);
  1708. // middle
  1709. dc.StretchBlt(
  1710. r.left+mrgn.cxLeftWidth,
  1711. r.top+mrgn.cyTopHeight,
  1712. r.Width()-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1713. r.Height()-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1714. &dcMem,
  1715. nImageNdx*bm.bmWidth/4 + mrgn.cxLeftWidth,
  1716. mrgn.cyTopHeight,
  1717. bm.bmWidth/4-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1718. bm.bmHeight-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1719. SRCCOPY);
  1720. }
  1721. else
  1722. {
  1723. // left-top
  1724. dc.BitBlt(r.left,
  1725. r.top,
  1726. mrgn.cxLeftWidth,
  1727. mrgn.cyTopHeight,
  1728. &dcMem,
  1729. 0,
  1730. nImageNdx*bm.bmHeight/4,
  1731. SRCCOPY);
  1732. // right-top
  1733. dc.BitBlt(r.right-mrgn.cxRightWidth,
  1734. r.top,
  1735. mrgn.cxRightWidth,
  1736. mrgn.cyTopHeight,
  1737. &dcMem,
  1738. bm.bmWidth-mrgn.cxRightWidth,
  1739. nImageNdx*bm.bmHeight/4,
  1740. SRCCOPY);
  1741. // left-bottom
  1742. dc.BitBlt(r.left,
  1743. r.bottom-mrgn.cyBottomHeight,
  1744. mrgn.cxLeftWidth,
  1745. mrgn.cyBottomHeight,
  1746. &dcMem,
  1747. 0,
  1748. (nImageNdx+1)*bm.bmHeight/4-mrgn.cyBottomHeight,
  1749. SRCCOPY);
  1750. // right-bottom
  1751. dc.BitBlt(r.right-mrgn.cxRightWidth,
  1752. r.bottom-mrgn.cyBottomHeight,
  1753. mrgn.cxRightWidth,
  1754. mrgn.cyBottomHeight,
  1755. &dcMem,
  1756. bm.bmWidth-mrgn.cxRightWidth,
  1757. (nImageNdx+1)*bm.bmHeight/4-mrgn.cyBottomHeight,
  1758. SRCCOPY);
  1759. // middle-top
  1760. dc.StretchBlt(r.left+mrgn.cxLeftWidth,
  1761. r.top,
  1762. r.Width()-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1763. mrgn.cyTopHeight,
  1764. &dcMem,
  1765. mrgn.cxLeftWidth,
  1766. nImageNdx*bm.bmHeight/4,
  1767. bm.bmWidth-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1768. mrgn.cyTopHeight,
  1769. SRCCOPY);
  1770. // middle-bottom
  1771. dc.StretchBlt(r.left+mrgn.cxLeftWidth,
  1772. r.bottom-mrgn.cyBottomHeight,
  1773. r.Width()-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1774. mrgn.cyBottomHeight,
  1775. &dcMem,
  1776. mrgn.cxLeftWidth,
  1777. (nImageNdx+1)*bm.bmHeight/4-mrgn.cyBottomHeight,
  1778. bm.bmWidth-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1779. mrgn.cyBottomHeight,
  1780. SRCCOPY);
  1781. // middle-left
  1782. dc.StretchBlt(r.left,
  1783. r.top+mrgn.cyTopHeight,
  1784. mrgn.cxLeftWidth,
  1785. r.Height()-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1786. &dcMem,
  1787. 0,
  1788. nImageNdx*bm.bmHeight/4+mrgn.cyTopHeight,
  1789. mrgn.cxLeftWidth,
  1790. bm.bmHeight/4-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1791. SRCCOPY);
  1792. // middle-right
  1793. dc.StretchBlt(r.right-mrgn.cxRightWidth,
  1794. r.top+mrgn.cyTopHeight,
  1795. mrgn.cxRightWidth,
  1796. r.Height()-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1797. &dcMem,
  1798. bm.bmWidth-mrgn.cxRightWidth,
  1799. nImageNdx*bm.bmHeight/4+mrgn.cyTopHeight,
  1800. mrgn.cxRightWidth,
  1801. bm.bmHeight/4-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1802. SRCCOPY);
  1803. // middle
  1804. dc.StretchBlt(
  1805. r.left+mrgn.cxLeftWidth,
  1806. r.top+mrgn.cyTopHeight,
  1807. r.Width()-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1808. r.Height()-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1809. &dcMem,
  1810. mrgn.cxLeftWidth,
  1811. nImageNdx*bm.bmHeight/4+mrgn.cyTopHeight,
  1812. bm.bmWidth-mrgn.cxLeftWidth-mrgn.cxRightWidth,
  1813. bm.bmHeight/4-mrgn.cyTopHeight-mrgn.cyBottomHeight,
  1814. SRCCOPY);
  1815. }
  1816. dcMem.SelectObject(pOldBmp);
  1817. }
  1818. void CCustomTabCtrl::DrawGlyph(CDC& dc, CPoint& pt, int nImageNdx, int nColorNdx)
  1819. {
  1820. CDC dcMem, dcMemMono;
  1821. dcMem.CreateCompatibleDC(&dc);
  1822. dcMemMono.CreateCompatibleDC(&dc);
  1823. CBitmap* pOldBmpGlyphMono = dcMemMono.SelectObject(&m_bmpGlyphsMono);
  1824. CBitmap bmpGlyphColor;
  1825. bmpGlyphColor.CreateCompatibleBitmap(&dc,8,7);
  1826. CBitmap* pOldBmpGlyphColor = dcMem.SelectObject(&bmpGlyphColor);
  1827. COLORREF rgbOldTextGlyph =  dcMem.SetTextColor(m_rgbGlyph[nColorNdx]);
  1828. dcMem.BitBlt(0, 0, 8, 7, &dcMemMono, nImageNdx*8, 0, SRCCOPY);
  1829. dcMem.SetTextColor(rgbOldTextGlyph);
  1830. COLORREF rgbOldBk = dc.SetBkColor(RGB(255,255,255));
  1831. COLORREF rgbOldText = dc.SetTextColor(RGB(0,0,0));
  1832. dc.BitBlt(pt.x, pt.y, 8, 7, &dcMem, 0, 0, SRCINVERT);
  1833. dc.BitBlt(pt.x, pt.y, 8, 7, &dcMemMono, nImageNdx*8, 0, SRCAND);
  1834. dc.BitBlt(pt.x, pt.y, 8, 7, &dcMem, 0, 0, SRCINVERT);
  1835. dcMem.SelectObject(pOldBmpGlyphColor);
  1836. dcMemMono.SelectObject(pOldBmpGlyphMono);
  1837. dc.SetBkColor(rgbOldBk);
  1838. dc.SetTextColor(rgbOldText);
  1839. }
  1840. BOOL CCustomTabCtrl::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  1841. {
  1842. if(dwRemove&CTCS_TOOLTIPS)
  1843. m_ctrlToolTip.DestroyWindow();
  1844. if(dwRemove&CTCS_MULTIHIGHLIGHT)
  1845. {
  1846. for(int i=0;i<m_aItems.GetSize();i++)
  1847. m_aItems[i]->m_fHighlighted = FALSE;
  1848. }
  1849. if(dwAdd&CTCS_MULTIHIGHLIGHT)
  1850. {
  1851. for(int i=0;i<m_aItems.GetSize();i++)
  1852. {
  1853. if(i==m_nItemSelected)
  1854. m_aItems[i]->m_fHighlighted = TRUE;
  1855. }
  1856. }
  1857. CWnd::ModifyStyle(dwRemove,dwAdd,nFlags);
  1858. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  1859. Invalidate(FALSE);
  1860. return TRUE;
  1861. }
  1862. BOOL CCustomTabCtrl::ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
  1863. {
  1864. CWnd::ModifyStyleEx(dwRemove,dwAdd,nFlags);
  1865. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  1866. Invalidate(FALSE);
  1867. return TRUE;
  1868. }
  1869. void CCustomTabCtrl::PreSubclassWindow() 
  1870. {
  1871. OnThemeChanged(0,0);
  1872. CWnd::ModifyStyle(0,WS_CLIPCHILDREN);
  1873. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  1874. CWnd::PreSubclassWindow();
  1875. }
  1876. void CCustomTabCtrl::SetDragCursors(HCURSOR hCursorMove, HCURSOR hCursorCopy)
  1877. {
  1878. ::DestroyCursor(m_hCursorMove);
  1879. m_hCursorMove = NULL;
  1880. ::DestroyCursor(m_hCursorCopy);
  1881. m_hCursorCopy = NULL;
  1882. m_hCursorMove = CopyCursor(hCursorMove);
  1883. m_hCursorCopy = CopyCursor(hCursorCopy);
  1884. }
  1885. void CCustomTabCtrl::OnRButtonDown(UINT nFlags, CPoint point)
  1886. {
  1887. NotifyParent(CTCN_RCLICK,HitTest(point),point);
  1888. CWnd::OnRButtonDown(nFlags, point);
  1889. }
  1890. void CCustomTabCtrl::OnRButtonDblClk(UINT nFlags, CPoint point) 
  1891. {
  1892. NotifyParent(CTCN_RDBLCLK,HitTest(point),point);
  1893. CWnd::OnRButtonDblClk(nFlags, point);
  1894. }
  1895. int CCustomTabCtrl::EditLabel(int nItem)
  1896. {
  1897. return EditLabel(nItem, FALSE);
  1898. }
  1899. int CCustomTabCtrl::EditLabel(int nItem, BOOL fMouseSel)
  1900. {
  1901. if(nItem<0 || nItem>=m_aItems.GetSize())
  1902. return CTCERR_INDEXOUTOFRANGE;
  1903. if(!(GetStyle()&CTCS_EDITLABELS))
  1904. return CTCERR_NOEDITLABELSTYLE;
  1905. if(nItem!=m_nItemSelected)
  1906. return CTCERR_ITEMNOTSELECTED;
  1907. if(m_ctrlEdit.m_hWnd)
  1908. return CTCERR_ALREADYINEDITMODE;
  1909. if(IsVertical())
  1910. return CTCERR_EDITNOTSUPPORTED;
  1911. try
  1912. {
  1913. CRect r;
  1914. CDC* pDC = GetDC();
  1915. CFont* pOldFont = pDC->SelectObject(&m_FontSelected);
  1916. int h = pDC->DrawText(m_aItems[nItem]->m_sText, r, DT_CALCRECT);
  1917. pDC->SelectObject(pOldFont);
  1918. ReleaseDC(pDC);
  1919. r = m_aItems[nItem]->m_rectText;
  1920. if(r.Height()>h)
  1921. {
  1922. r.top += (r.Height()-h)/2;
  1923. r.bottom -= (r.Height()-h)/2;
  1924. }
  1925. r.left += 2;
  1926. if(m_ctrlEdit.Create(WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL,r,this,CTCID_EDITCTRL))
  1927. {
  1928. CString sOld = m_aItems[nItem]->m_sText;
  1929. m_ctrlEdit.SetFont(&m_FontSelected,FALSE);
  1930. m_ctrlEdit.SetLimitText(MAX_LABEL_TEXT);
  1931. m_ctrlEdit.SetWindowText(m_aItems[nItem]->m_sText);
  1932. m_ctrlEdit.SetFocus();
  1933. m_ctrlEdit.SetSel(0,-1);
  1934. if(fMouseSel)
  1935. ReleaseCapture();
  1936. for (;;) 
  1937. {
  1938. MSG msg;
  1939. ::GetMessage(&msg, NULL, 0, 0);
  1940. switch (msg.message) 
  1941. {
  1942. case WM_SYSKEYDOWN:
  1943. {
  1944. if(msg.wParam == VK_F4 && msg.lParam&29)
  1945. break;
  1946. TranslateMessage(&msg);
  1947. DispatchMessage(&msg);
  1948. }
  1949. break;
  1950. case WM_KEYDOWN:
  1951. {
  1952. if (msg.wParam == VK_ESCAPE)
  1953. {
  1954. m_aItems[nItem]->m_sText = sOld;
  1955. m_ctrlEdit.DestroyWindow();
  1956. RecalcLayout(RECALC_RESIZED,m_nItemSelected);
  1957. Invalidate(FALSE);
  1958. return CTCERR_NOERROR;
  1959. }
  1960. if(msg.wParam == VK_RETURN)
  1961. {
  1962. if(NotifyParent(CTCN_LABELUPDATE,nItem,CPoint(0,0)))
  1963. break;
  1964. m_ctrlEdit.GetWindowText(m_aItems[nItem]->m_sText);
  1965. m_ctrlEdit.DestroyWindow();
  1966. RecalcLayout(RECALC_RESIZED,nItem);
  1967. Invalidate(FALSE);
  1968. return CTCERR_NOERROR;
  1969. }
  1970. TranslateMessage(&msg);
  1971. DispatchMessage(&msg);
  1972. }
  1973. break;
  1974. case WM_LBUTTONDOWN:
  1975. {
  1976. if(msg.hwnd==m_hWnd)
  1977. {
  1978. POINTS pt = MAKEPOINTS(msg.lParam);
  1979. if(HitTest(CPoint(pt.x,pt.y))!=m_nItemSelected)
  1980. {
  1981. if(NotifyParent(CTCN_LABELUPDATE,nItem,CPoint(0,0)))
  1982. break;
  1983. m_ctrlEdit.GetWindowText(m_aItems[m_nItemSelected]->m_sText);
  1984. m_ctrlEdit.DestroyWindow();
  1985. TranslateMessage(&msg);
  1986. DispatchMessage(&msg);
  1987. return CTCERR_NOERROR;
  1988. }
  1989. }
  1990. else if(msg.hwnd==m_ctrlEdit.m_hWnd)
  1991. {
  1992. TranslateMessage(&msg);
  1993. DispatchMessage(&msg);
  1994. }
  1995. else
  1996. {
  1997. if(NotifyParent(CTCN_LABELUPDATE,nItem,CPoint(0,0)))
  1998. break;
  1999. m_ctrlEdit.GetWindowText(m_aItems[m_nItemSelected]->m_sText);
  2000. m_ctrlEdit.DestroyWindow();
  2001. return CTCERR_NOERROR;
  2002. }
  2003. }
  2004. break;
  2005. case WM_LBUTTONUP:
  2006. {
  2007. if(msg.hwnd==m_ctrlEdit.m_hWnd)
  2008. {
  2009. TranslateMessage(&msg);
  2010. DispatchMessage(&msg);
  2011. }
  2012. }
  2013. break;
  2014. case WM_NCLBUTTONDOWN:
  2015. {
  2016. if(NotifyParent(CTCN_LABELUPDATE,nItem,CPoint(0,0)))
  2017. break;
  2018. m_ctrlEdit.GetWindowText(m_aItems[m_nItemSelected]->m_sText);
  2019. m_ctrlEdit.DestroyWindow();
  2020. TranslateMessage(&msg);
  2021. DispatchMessage(&msg);
  2022. return CTCERR_NOERROR;
  2023. }
  2024. break;
  2025. case WM_LBUTTONDBLCLK:
  2026. case WM_RBUTTONDOWN:
  2027. case WM_RBUTTONUP:
  2028. break;
  2029. default:
  2030. TranslateMessage(&msg);
  2031. DispatchMessage(&msg);
  2032. break;
  2033. }
  2034. }
  2035. }
  2036. }
  2037. catch(CMemoryException* e)
  2038. {
  2039. e->Delete();
  2040. if(fMouseSel)
  2041. NotifyParent(CTCN_OUTOFMEMORY,nItem,CPoint(0,0));
  2042. return CTCERR_OUTOFMEMORY;
  2043. }
  2044. return CTCERR_NOERROR;
  2045. }