CoolTabCtrl.cpp
上传用户:asikq0571
上传日期:2014-07-12
资源大小:528k
文件大小:14k
源码类别:

Internet/IE编程

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////
  2. // CoolTabCtrl.cpp : implementation file                      //
  3. //   //
  4. // Copyright 2001 WangJun   //
  5. // All Rights Reserved.   //
  6. //   //
  7. // Email: wangjun98@sohu.com   //
  8. // URL:   www.vckbase.com   //
  9. //   //
  10. // 1.0     2001/9/30   First release version.   //
  11. //   //
  12. // 2004/2/8 添加对WM_NOTIFY消息的处理   //
  13. // 2005/2/2 修正内存泄漏   //
  14. //                                                            //
  15. ////////////////////////////////////////////////////////////////
  16. #include "stdafx.h"
  17. #include "CoolTabCtrl.h"
  18. #ifdef _DEBUG
  19. #define new DEBUG_NEW
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CCoolTabCtrl
  25. IMPLEMENT_DYNCREATE(CCoolTabCtrl, CWnd)
  26. #define ITEMBUTTON_HEIGHT 23
  27. static CPen _penW(PS_SOLID,1 ,RGB(255,255,255));
  28. static CPen _penB(PS_SOLID,1 ,RGB(0,0,0));
  29. static CPen _pen3DFace(PS_SOLID,1,GetSysColor(COLOR_3DFACE));
  30. static CPen _pen3DLight(PS_SOLID,1,GetSysColor(COLOR_3DLIGHT));
  31. static CPen _pen3DShadow(PS_SOLID,1,GetSysColor(COLOR_3DSHADOW));
  32. static CPen _pen3DDKShadow(PS_SOLID,1,GetSysColor(COLOR_3DDKSHADOW));
  33. CCoolTabCtrl::CCoolTabCtrl()
  34. {
  35. m_nStyle = TCS_DOWN;
  36. m_nActivePage = -1;
  37. m_nBorder = 1;
  38. m_bEraseBkgnd = TRUE;
  39. }
  40. CCoolTabCtrl::~CCoolTabCtrl()
  41. {
  42. POSITION pos;
  43. CPageItem* pItem;
  44. for(pos=m_PageList.GetHeadPosition();pos!=NULL;)
  45. {
  46. pItem=(CPageItem*)m_PageList.GetNext(pos);
  47. if(pItem)
  48. {
  49. if(pItem->m_nStyle == 1 && pItem->m_pWnd) // 动态创建
  50. {
  51. pItem->m_pWnd->DestroyWindow();
  52. delete pItem->m_pWnd;
  53. }
  54. delete pItem;
  55. pItem=NULL;
  56. }
  57. }
  58. m_PageList.RemoveAll();
  59. }
  60. BEGIN_MESSAGE_MAP(CCoolTabCtrl, CWnd)
  61. //{{AFX_MSG_MAP(CCoolTabCtrl)
  62. ON_WM_PAINT()
  63. ON_WM_ERASEBKGND()
  64. ON_WM_LBUTTONDOWN()
  65. ON_WM_SIZING()
  66. ON_WM_SIZE()
  67. ON_WM_TIMER()
  68. ON_WM_CREATE()
  69. ON_WM_DESTROY()
  70. //}}AFX_MSG_MAP
  71. END_MESSAGE_MAP()
  72. /////////////////////////////////////////////////////////////////////////////
  73. // CCoolTabCtrl message handlers
  74. BOOL CCoolTabCtrl::Create(UINT wStyle, const CRect &rect, CWnd *pParentWnd, UINT nID)
  75. {
  76. m_nStyle = wStyle & TCS_MASK;
  77. if(m_nStyle == 0)
  78. m_nStyle = TCS_UP;
  79. if (CWnd::Create(AfxRegisterWndClass(CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, AfxGetApp()->LoadStandardCursor(IDC_ARROW), (HBRUSH)GetStockObject(LTGRAY_BRUSH), NULL),
  80. NULL,
  81. wStyle&~TCS_MASK | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  82. rect, 
  83. pParentWnd, 
  84. nID))
  85. {
  86. return TRUE;
  87. }
  88. return FALSE;
  89. }
  90. BOOL CCoolTabCtrl::OnEraseBkgnd(CDC* pDC) 
  91. {
  92. if(m_bEraseBkgnd)
  93. {
  94. CRect rect;
  95. GetWindowRect(&rect);
  96. ScreenToClient(&rect);
  97. CBrush brush(GetSysColor(COLOR_3DFACE));
  98. pDC->FillRect(rect,&brush);
  99. }
  100. return TRUE;
  101. }
  102. void CCoolTabCtrl::OnPaint() 
  103. {
  104. CPaintDC dc(this);
  105. CPen *pOldPen = dc.GetCurrentPen();
  106. CFont *pOldFont = dc.SelectObject(&m_font);
  107. int nOldBkMode = dc.SetBkMode(TRANSPARENT);
  108. CPageItem *pItem;
  109. POSITION pos;
  110. int nItemIndex = 0;
  111. DrawFrame(&dc);
  112. for(pos=m_PageList.GetHeadPosition();pos!=NULL;nItemIndex++)
  113. {
  114. pItem=(CPageItem*)m_PageList.GetNext(pos);
  115. if(pItem)
  116. {
  117. pItem->Draw(&dc,m_nStyle,(m_nActivePage==nItemIndex)?TRUE:FALSE);
  118. }
  119. }
  120. dc.SetBkMode(nOldBkMode);
  121. dc.SelectObject(pOldFont);
  122. dc.SelectObject(pOldPen);
  123. }
  124. CCoolTabCtrl::CPageItem* CCoolTabCtrl::AddPage(CWnd *pWnd, LPCTSTR sText, UINT IconID)
  125. {
  126. ASSERT(pWnd);
  127. ASSERT(IsWindow(pWnd->m_hWnd));
  128. CPageItem *pItem = NULL;
  129. pItem = new CPageItem();
  130. pItem->m_pWnd = pWnd;
  131. pItem->m_nStyle = 0; //Window delete
  132. pItem->m_sText = sText;
  133. if(IconID)
  134. pItem->m_hIcon = AfxGetApp()->LoadIcon(IconID);
  135. else
  136. pItem->m_hIcon = NULL;
  137. CRect rect;
  138. GetClientRect(rect);
  139. pWnd->MoveWindow(rect);
  140. m_PageList.AddTail(pItem);
  141. // 如果添加的Page index不等于m_nActivePage, 则隐藏
  142. if(m_nActivePage != m_PageList.GetCount())
  143. {
  144. pWnd->ShowWindow(SW_HIDE);
  145. }
  146. return pItem;
  147. }
  148. BOOL CCoolTabCtrl::AddPage(CRuntimeClass* pClass,UINT nIDTemplate, LPCTSTR sText, UINT IconID)
  149. {
  150. CDialog *pDlg = (CDialog*)pClass->CreateObject();
  151. if(pDlg != NULL)
  152. {
  153. if(pDlg->Create(nIDTemplate,this))
  154. {
  155. CCoolTabCtrl::CPageItem *pItem = AddPage(pDlg, sText, IconID);
  156. if(pItem)
  157. {
  158. pItem->SetPageStyle(1);
  159. return TRUE;
  160. }
  161. }
  162. }
  163. return FALSE;
  164. }
  165. void CCoolTabCtrl::GetClientRect(LPRECT lpRect)
  166. {
  167. CWnd::GetClientRect(lpRect);
  168. if(m_nStyle&TCS_DOWN)
  169. {
  170. lpRect->left += 2;
  171. lpRect->right -= 2;
  172. lpRect->top += 2;
  173. lpRect->bottom -= ITEMBUTTON_HEIGHT;
  174. }
  175. else if(m_nStyle&TCS_UP)
  176. {
  177. lpRect->left += 2;
  178. lpRect->right -= 2;
  179. lpRect->top += ITEMBUTTON_HEIGHT;
  180. lpRect->bottom -= 2;
  181. }
  182. }
  183. ///////取得需要占用的宽度/////
  184. UINT CCoolTabCtrl::CPageItem::GetAreaWidth(CDC *pDC)
  185. {
  186. UINT width = pDC->GetTextExtent(m_sText).cx;
  187. if(m_hIcon)
  188. width += 18;
  189. return width + 9;
  190. }
  191. void CCoolTabCtrl::CPageItem::Draw(CDC *pDC, UINT nStyle, BOOL bActive)
  192. {
  193. CRect rect = m_rect;
  194. if(nStyle&TCS_DOWN)
  195. {
  196. if(bActive)
  197. {
  198. rect.top -= 2;
  199. CBrush brush(GetSysColor(COLOR_3DFACE));
  200. pDC->FillRect(rect,&brush);
  201. rect.top += 1;
  202. }
  203. else
  204. rect.bottom -= 1;
  205. CBrush brush(GetSysColor(COLOR_3DFACE));
  206. pDC->FillRect(m_rect,&brush);
  207. pDC->SelectObject(&_penW);
  208. pDC->MoveTo(rect.left,rect.top);
  209. pDC->LineTo(rect.left,rect.bottom-1);
  210. pDC->SelectObject(&_pen3DShadow);
  211. pDC->MoveTo(rect.left+1,rect.bottom-2);
  212. pDC->LineTo(rect.left+1,rect.bottom-1);
  213. pDC->LineTo(rect.right-1,rect.bottom-1);
  214. pDC->MoveTo(rect.right-2,rect.bottom-2);
  215. pDC->LineTo(rect.right-1,rect.bottom-2);
  216. pDC->LineTo(rect.right-1,rect.top-1);
  217. pDC->SelectObject(&_penB);
  218. pDC->MoveTo(rect.left+2,rect.bottom);
  219. pDC->LineTo(rect.right-2,rect.bottom);
  220. pDC->LineTo(rect.right,rect.bottom-2);
  221. pDC->MoveTo(rect.right,rect.top);
  222. pDC->LineTo(rect.right,rect.bottom-1);
  223. rect.top -= 1;
  224. }//end of TCS_DOWN
  225. else if(nStyle&TCS_UP)
  226. {
  227. CBrush brush(GetSysColor(COLOR_3DFACE));
  228. if(bActive)
  229. {
  230. rect.bottom += 1;
  231. pDC->FillRect(rect,&brush);
  232. rect.bottom -= 1;
  233. }
  234. else
  235. {
  236. rect.top += 2;
  237. pDC->FillRect(rect,&brush);
  238. }
  239. pDC->SelectObject(&_penW);
  240. pDC->MoveTo(rect.left,rect.bottom);
  241. pDC->LineTo(rect.left,rect.top + 2);
  242. pDC->LineTo(rect.left + 2,rect.top);
  243. pDC->LineTo(rect.right,rect.top);
  244. pDC->SelectObject(&_pen3DShadow);
  245. pDC->MoveTo(rect.right - 1,rect.top);
  246. pDC->LineTo(rect.right - 1,rect.bottom);
  247. pDC->SelectObject(&_penB);
  248. pDC->MoveTo(rect.right,rect.top + 1);
  249. pDC->LineTo(rect.right,rect.bottom);
  250. }
  251. ///////////调整位置//////////
  252. rect.left += 5;
  253. rect.right -= 2;
  254. ///////////显示图标//////////
  255. if(rect.Width() > 16 && m_hIcon != NULL)
  256. {
  257. ::DrawIconEx(pDC->m_hDC,rect.left,rect.top + 3,m_hIcon,16,16,0,NULL,DI_NORMAL);
  258. rect.left += 18;
  259. }
  260. if (!m_sText.IsEmpty())
  261. {
  262. ///////////显示文字//////////
  263. rect.top += 5;
  264. CString sText = m_sText;
  265. int l = sText.GetLength();
  266. int i;
  267. for(i=0;i<10 && pDC->GetTextExtent(sText).cx > rect.Width();i++,l-=2)
  268. sText = sText.Left(l-2);
  269. if(i > 0)
  270. {
  271. sText = sText.Left(l-2);
  272. sText += "...";
  273. }
  274. pDC->DrawText(sText, &rect, DT_LEFT /*| DT_VCENTER */| DT_SINGLELINE);
  275. }
  276. }
  277. ////调整尺寸////
  278. void CCoolTabCtrl::AutoSize()
  279. {
  280. UINT PageCount = m_PageList.GetCount();
  281. if(PageCount < 1) return;
  282. CPageItem *pItem;
  283. POSITION pos;
  284. CRect rect,ClientRect,ItemRect;
  285. GetClientRect(ClientRect);
  286. ClientRect.DeflateRect(m_nBorder+1,m_nBorder+1);
  287. GetWindowRect(rect);
  288. ScreenToClient(rect);
  289. CDC* pDC = GetDC();
  290. CFont *pOldFont = pDC->SelectObject(&m_font);
  291. if(m_nStyle&TCS_DOWN)
  292. {
  293. rect.left += 6;
  294. rect.right -= 6;
  295. rect.bottom -= 1;
  296. rect.top = rect.bottom - ITEMBUTTON_HEIGHT + 1;
  297. }
  298. else if(m_nStyle&TCS_UP)
  299. {
  300. rect.left += 2;
  301. rect.right -= 6;
  302. rect.bottom = rect.top + ITEMBUTTON_HEIGHT;
  303. }
  304. ItemRect = rect;
  305. int AreaWidth = 0,ItemMaxWidth,ItemIndex=0;
  306. ItemMaxWidth = rect.Width()/m_PageList.GetCount();
  307. BOOL bMonoSpace = ((m_nStyle&TCS_MONOSPACE) == TCS_MONOSPACE)?1:0;
  308. ////////设置按钮初始宽度,并得到按钮所需占用的总宽度///////
  309. for(pos=m_PageList.GetHeadPosition();pos!=NULL;ItemIndex++)
  310. {
  311. pItem=(CPageItem*)m_PageList.GetNext(pos);
  312. if(pItem)
  313. {
  314. if(!bMonoSpace)
  315. ItemMaxWidth = pItem->GetAreaWidth(pDC);
  316. AreaWidth += ItemMaxWidth;
  317. ItemRect.right = ItemRect.left+ItemMaxWidth-1;
  318. pItem->m_rect = ItemRect;
  319. ItemRect.left = ItemRect.right + 1;
  320. if(pItem->m_pWnd)
  321. pItem->m_pWnd->MoveWindow(ClientRect);
  322. }
  323. }
  324. ////////当需要的空间大于实际空间时进行调整////
  325. if(AreaWidth > rect.Width() && !bMonoSpace)
  326. {
  327. ItemRect = rect;
  328. int AreaWidth,MaxWidth = rect.Width()/PageCount;
  329. for(pos=m_PageList.GetHeadPosition();pos!=NULL;)
  330. {
  331. pItem=(CPageItem*)m_PageList.GetNext(pos);
  332. if(pItem)
  333. {
  334. AreaWidth = pItem->GetAreaWidth(pDC);
  335. ItemMaxWidth = (ItemMaxWidth < AreaWidth)?MaxWidth:AreaWidth;
  336. ItemRect.right = ItemRect.left+ItemMaxWidth;
  337. pItem->m_rect = ItemRect;
  338. ItemRect.left = ItemRect.right + 1;
  339. }
  340. }
  341. }
  342. pDC->SelectObject(pOldFont);
  343. ReleaseDC(pDC);
  344. }
  345. void CCoolTabCtrl::SetActivePage(int nIndex)
  346. {
  347. if(nIndex == m_nActivePage)
  348. return;
  349. CPageItem *pOldItem,*pItem;
  350. if(m_nActivePage >= 0)
  351. {
  352. pOldItem = (CPageItem*)GetPageItem(m_nActivePage);
  353. if(pOldItem)
  354. {
  355. pOldItem->m_pWnd->ShowWindow(SW_HIDE);
  356. }
  357. }
  358. pItem = (CPageItem*)GetPageItem(nIndex);
  359. if(!pItem) return;
  360. m_nActivePage = nIndex;
  361. if(m_nStyle&TCS_ANIMATE)
  362. SetTimer(100,15,NULL);///为了在95或NT4下也有动画效果,没有使用AnimateWindow函数
  363. else
  364. pItem->m_pWnd->ShowWindow(SW_SHOW);
  365. }
  366. void* CCoolTabCtrl::GetPageItem(UINT nIndex)
  367. {
  368. CPageItem *pItem = NULL;
  369. POSITION pos = m_PageList.FindIndex(nIndex);
  370. if(pos)
  371. pItem = (CPageItem*)m_PageList.GetAt(pos);
  372. return pItem;
  373. }
  374. void CCoolTabCtrl::UpdateWindow()
  375. {
  376.   AutoSize();
  377.   if(m_nActivePage < 0)
  378.   SetActivePage(0);
  379.   else
  380.   SetActivePage(m_nActivePage);
  381.   Invalidate();
  382. }
  383. void CCoolTabCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
  384. {
  385. UINT nItemIndex=0;
  386. POSITION pos;
  387. CPageItem *pItem;
  388. for(pos=m_PageList.GetHeadPosition();pos!=NULL;nItemIndex++)
  389. {
  390. pItem=(CPageItem*)m_PageList.GetNext(pos);
  391. if(pItem)
  392. {
  393. if(pItem->m_rect.PtInRect(point))
  394. {
  395. SetActivePage(nItemIndex);
  396. Invalidate();
  397. break;
  398. }
  399. }
  400. }
  401. CWnd::OnLButtonDown(nFlags, point);
  402. }
  403. void CCoolTabCtrl::OnSizing(UINT fwSide, LPRECT pRect) 
  404. {
  405. CWnd::OnSizing(fwSide, pRect);
  406. m_bEraseBkgnd = FALSE;
  407. AutoSize();
  408. }
  409. void CCoolTabCtrl::OnSize(UINT nType, int cx, int cy) 
  410. {
  411. CWnd::OnSize(nType, cx, cy);
  412. m_bEraseBkgnd = TRUE;
  413. AutoSize();
  414. Invalidate();
  415. }
  416. void CCoolTabCtrl::DrawFrame(CDC *pDC)
  417. {
  418. CRect rect;
  419. GetClientRect(&rect);
  420. switch(m_nBorder)
  421. {
  422. case 1:
  423. pDC->Draw3dRect(rect,RGB(0xff,0xff,0xff),RGB(0,0,0));
  424. break;
  425. case 2:
  426. pDC->Draw3dRect(rect,RGB(0xff,0xff,0xff),RGB(0,0,0));
  427. rect.DeflateRect(1, 1);
  428. pDC->Draw3dRect(rect, GetSysColor(COLOR_3DFACE), GetSysColor(COLOR_3DSHADOW));
  429. break;
  430. default:break;
  431. }
  432. }
  433. void CCoolTabCtrl::SetStyle(UINT style)
  434. {
  435. m_nStyle = style;
  436. }
  437. UINT CCoolTabCtrl::GetStyle()
  438. {
  439. return m_nStyle;
  440. }
  441. void CCoolTabCtrl::OnTimer(UINT nIDEvent) 
  442. {
  443. static step,times = 10;
  444. UINT width;
  445. CRect rect;
  446. GetClientRect(&rect);
  447. rect.DeflateRect(m_nBorder+1,m_nBorder+1);
  448. POSITION pos = m_PageList.FindIndex(m_nActivePage);
  449. if(pos)
  450. {
  451. CPageItem *pItem = (CPageItem*)m_PageList.GetAt(pos);
  452. if(pItem)
  453. {
  454. width = rect.Width();
  455. if(times == 10)
  456. {
  457. rect.right = 10;
  458. rect.left = rect.right - width + 1;
  459. step = width/times;
  460. times--;
  461. m_bEraseBkgnd = FALSE;
  462. pItem->m_pWnd->ShowWindow(SW_SHOW);
  463. }
  464. else
  465. {
  466. if(times <= 0)
  467. {
  468. times = 10;
  469. KillTimer(nIDEvent);
  470. m_bEraseBkgnd = TRUE;
  471. }
  472. else
  473. {
  474. rect.right = width - times*step;
  475. rect.left = rect.right - width + 1;
  476. times--;
  477. }
  478. }
  479. pItem->m_pWnd->MoveWindow(rect);
  480. }
  481. }
  482. }
  483. void CCoolTabCtrl::SetStyleAnimate(BOOL bEnable)
  484. {
  485. UINT style = GetStyle();
  486. if(bEnable)
  487. style |= TCS_ANIMATE;
  488. else
  489. style &= ~TCS_ANIMATE;
  490. SetStyle(style);
  491. }
  492. void CCoolTabCtrl::SetStyleDirection(int Direction)
  493. {
  494. UINT style = GetStyle();
  495. switch(Direction)
  496. {
  497. case TCS_DOWN:
  498. style &= ~TCS_UP;
  499. style |= TCS_DOWN;
  500. break;
  501. case TCS_UP:
  502. default:
  503. style &= ~TCS_DOWN;
  504. style |= TCS_UP;
  505. break;
  506. }
  507. SetStyle(style);
  508. UpdateWindow();
  509. }
  510. void CCoolTabCtrl::SetStyleMonoSpace(BOOL bEnable)
  511. {
  512. UINT style = GetStyle();
  513. if(bEnable)
  514. style |= TCS_MONOSPACE;
  515. else
  516. style &= ~TCS_MONOSPACE;
  517. SetStyle(style);
  518. UpdateWindow();
  519. }
  520. BOOL CCoolTabCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  521. {
  522. // 将WM_NOTIFY消息转交给父窗口处理
  523. GetParent()->SendMessage(WM_NOTIFY, wParam, lParam);
  524. *pResult = 0;
  525. return TRUE;
  526. }
  527. int CCoolTabCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
  528. {
  529. if(CWnd::OnCreate(lpCreateStruct) == -1)
  530. return -1;
  531. LOGFONT logFont;
  532. ZeroMemory((void*)&logFont,sizeof(logFont));
  533. strcpy(logFont.lfFaceName,"宋体");
  534. logFont.lfHeight = -12;
  535. logFont.lfWeight = 400;
  536. logFont.lfCharSet = GB2312_CHARSET;
  537. logFont.lfOutPrecision = 3;
  538. logFont.lfClipPrecision = 2; 
  539. logFont.lfQuality = 1;
  540. logFont.lfPitchAndFamily = 2;
  541. m_font.CreateFontIndirect(&logFont);
  542. SetFont(&m_font);
  543. return 0;
  544. }
  545. void CCoolTabCtrl::OnDestroy()
  546. {
  547. CWnd::OnDestroy();
  548. }
  549. //扩充的函数:获取指定页的窗口指针
  550. CWnd* CCoolTabCtrl::GetPagePoint(UINT nIndex)
  551. {
  552.     CPageItem *pItem = NULL;
  553. CWnd* pWnd =NULL;
  554. POSITION pos = m_PageList.FindIndex(nIndex);
  555. if(pos)
  556. pItem = (CPageItem*)m_PageList.GetAt(pos);
  557. pWnd = pItem->m_pWnd;
  558. return pWnd;
  559. }