XTTabCtrlButtons.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:10k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTTabCtrlButtons.cpp : implementation of the CXTTabCtrlButtons class.
  2. //
  3. // This file is a part of the XTREME CONTROLS MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "Resource.h"
  22. #include "Common/XTPColorManager.h"
  23. #include "Common/XTPWinThemeWrapper.h"
  24. #include "Common/XTPDrawHelpers.h"
  25. #include "XTDefines.h"
  26. #include "XTGlobal.h"
  27. #include "XTVC50Helpers.h"
  28. #include "XTColorRef.h"
  29. #include "XTTabCtrlButtons.h"
  30. #include "XTTabBase.h"
  31. #ifdef _DEBUG
  32. #define new DEBUG_NEW
  33. #undef THIS_FILE
  34. static char THIS_FILE[] = __FILE__;
  35. #endif
  36. #define DB_LEFT        0x0002
  37. #define DB_RIGHT       0x0004
  38. #define DB_CROSS       0x0008
  39. #define DB_ENABLED     0x0000
  40. #define DB_DISABLED    0x0100
  41. #define DB_PRESSED     0x1000
  42. #define DB_OVER        0x4000
  43. #define DB_ISENABLED(Style) (!((Style)&DB_DISABLED))
  44. #define DB_ISPRESSED(Style) (((Style) & (DB_PRESSED)) != 0)
  45. #define DB_ISOVER(Style) (((Style)&DB_OVER) == DB_OVER)
  46. void CXTTabCtrlButton::SetEnable(BOOL bEnable)
  47. {
  48. if (!bEnable)
  49. m_wStyle |= DB_DISABLED;
  50. else
  51. m_wStyle &= ~DB_DISABLED;
  52. }
  53. void CXTTabCtrlButton::Draw (CDC* pDC, COLORREF clrButton)
  54. {
  55. m_pButtons->m_pTabCtrlBase->GetPaintManager()->DrawButton(pDC, this, clrButton);
  56. }
  57. DWORD CXTTabCtrlButton::Click (CXTTabCtrlButtons* pWnd, CPoint pt, BOOL bRepeat)
  58. {
  59. if ((::GetCapture() != NULL) || !DB_ISENABLED(m_wStyle))
  60. {
  61. return FALSE;
  62. }
  63. pWnd->SetCapture();
  64. ASSERT(pWnd == CWnd::GetCapture());
  65. BOOL  bDown = FALSE, bClick = FALSE;
  66. CRect rcBtn(m_Rect);
  67. UINT_PTR nTimer = (bRepeat == FALSE) ? 0 : SetTimer(pWnd->GetSafeHwnd(), 1, 150, NULL);
  68. for (;;)
  69. {
  70. if (bRepeat && DB_ISENABLED(m_wStyle))
  71. {
  72. ASSERT(m_pTabCtrl);
  73. if (!m_pTabCtrl)
  74. return FALSE;
  75. int nCount = m_pTabCtrl->GetItemCount();
  76. CRect rc;
  77. m_pTabCtrl->GetItemRect(-1, rc);
  78. TCHITTESTINFO hi = {{5, rc.CenterPoint().y}};
  79. int nFirst = m_pTabCtrl->HitTest(&hi);
  80. if (m_wStyle & DB_LEFT)
  81. {
  82. if (nFirst > 0)
  83. m_pTabCtrl->SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, nFirst - 1), 0);
  84. }
  85. else if (nCount > 0)
  86. {
  87. m_pTabCtrl->SendMessage(WM_HSCROLL, MAKEWPARAM(SB_THUMBPOSITION, nFirst + 1), 0);
  88. }
  89. m_pTabCtrl->Invalidate(FALSE);
  90. pWnd->Invalidate(FALSE);
  91. }
  92. BOOL bNewDown = ::PtInRect (rcBtn, pt) != 0;
  93. if (bNewDown != bDown)
  94. {
  95. bDown = bNewDown;
  96. if (bDown)
  97. m_wStyle = m_wStyle | DB_PRESSED;
  98. else
  99. m_wStyle &= ~DB_PRESSED;
  100. pWnd->InvalidateRect (m_Rect, FALSE);
  101. }
  102. MSG msg;
  103. // assess current state
  104. // pump WM_PAINT first for better feedback
  105. while (::PeekMessage(&msg, NULL, WM_PAINT, WM_PAINT, PM_NOREMOVE))
  106. {
  107. if (!GetMessage(&msg, NULL, WM_PAINT, WM_PAINT))
  108. break;
  109. DispatchMessage(&msg);
  110. }
  111. VERIFY(::GetMessage(&msg, NULL, 0, 0));
  112. if (CWnd::GetCapture() != pWnd)
  113. {
  114. DispatchMessage (&msg);
  115. goto ExitLoop;
  116. }
  117. switch (msg.message)
  118. {
  119. case WM_MOUSEMOVE:
  120. pt = CPoint((short signed)LOWORD(msg.lParam), (short signed)HIWORD(msg.lParam));
  121. break;
  122. case WM_LBUTTONUP:
  123. bClick = bDown;
  124. goto ExitLoop;
  125. case WM_KEYDOWN:
  126. if (msg.wParam != VK_ESCAPE)
  127. break;
  128. case WM_CANCELMODE:
  129. case WM_RBUTTONDOWN:
  130. goto ExitLoop;
  131. default:
  132. DispatchMessage (&msg);
  133. break;
  134. }
  135. }
  136. ExitLoop:
  137. ReleaseCapture();
  138. if (nTimer) KillTimer(*pWnd, nTimer);
  139. m_wStyle &= ~DB_PRESSED;
  140. CheckForMouseOver (pWnd, pt);
  141. pWnd->InvalidateRect (m_Rect, FALSE);
  142. return bClick;
  143. }
  144. void CXTTabCtrlButton::CheckForMouseOver (CWnd* pWnd, CPoint pt)
  145. {
  146. if (!PtInRect (pt) && DB_ISOVER(m_wStyle))
  147. {
  148. m_wStyle &= ~DB_OVER;
  149. pWnd->InvalidateRect (m_Rect, FALSE);
  150. }
  151. if (!DB_ISOVER(m_wStyle) && PtInRect (pt) && DB_ISENABLED(m_wStyle))
  152. {
  153. TRACKMOUSEEVENT tme =
  154. {
  155. sizeof(TRACKMOUSEEVENT), TME_LEAVE, *pWnd, 0
  156. };
  157. _TrackMouseEvent(&tme);
  158. m_wStyle |= DB_OVER;
  159. pWnd->InvalidateRect (m_Rect, FALSE);
  160. }
  161. }
  162. /////////////////////////////////////////////////////////////////////////////
  163. // CXTTabCtrlButtons
  164. CXTTabCtrlButtons::CXTTabCtrlButtons()
  165. : m_btnClose(DB_CROSS), m_btnLeft(DB_LEFT), m_btnRight(DB_RIGHT)
  166. {
  167. m_dwFlags = xtNavBtnArrows;
  168. m_bShow = FALSE;
  169. m_hwndSubclassed = 0;
  170. m_hwndPrimary = 0;
  171. m_pTabCtrlBase = 0;
  172. m_pTabCtrl = 0;
  173. m_btnRight.m_pButtons = m_btnClose.m_pButtons = m_btnLeft.m_pButtons = this;
  174. }
  175. CXTTabCtrlButtons::~CXTTabCtrlButtons()
  176. {
  177. }
  178. BEGIN_MESSAGE_MAP(CXTTabCtrlButtons, CWnd)
  179. ON_WM_PAINT()
  180. ON_WM_ERASEBKGND()
  181. ON_WM_WINDOWPOSCHANGED()
  182. ON_WM_MOUSEMOVE()
  183. ON_WM_LBUTTONDOWN()
  184. ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave)
  185. END_MESSAGE_MAP()
  186. void CXTTabCtrlButtons::OnPaint()
  187. {
  188. CPaintDC dcPaint(this);
  189. CXTPClientRect rc(m_pTabCtrl);
  190. CXTPClientRect rcClient(this);
  191. CXTPBufferDC dc(dcPaint, rc);
  192. int nCount = m_pTabCtrl->GetItemCount();
  193. if (!m_bShow || nCount == 0)
  194. {
  195. CWnd::DefWindowProc(WM_PAINT, (WPARAM)dc.m_hDC, 0);
  196. return;
  197. }
  198. COLORREF clrText =m_pTabCtrlBase->GetPaintManager()->FillButtons(&dc, this);
  199. CRect rcItem;
  200. m_pTabCtrl->GetItemRect(-1, &rcItem);
  201. int nTop = (rcItem.Height() - 13) / 2;
  202. int nRight = rcClient.right - 5;
  203. if (m_dwFlags & xtNavBtnClose)
  204. {
  205. m_btnClose.SetRect(CRect(nRight - 14, nTop, nRight, nTop + 15));
  206. m_btnClose.Draw(&dc, clrText);
  207. nRight -= 14;
  208. }
  209. else
  210. m_btnClose.SetRect(CXTPEmptyRect());
  211. if (m_dwFlags & xtNavBtnArrows)
  212. {
  213. ASSERT(m_pTabCtrl);
  214. if (!m_pTabCtrl)
  215. return;
  216. BOOL bEnableRight = FALSE, bEnableLeft = FALSE;
  217. if (nCount > 0)
  218. {
  219. CRect rcLastItem;
  220. m_pTabCtrl->GetItemRect(nCount - 1, &rcLastItem);
  221. bEnableRight = rcLastItem.right > rc.Width() - GetWidth();
  222. m_pTabCtrl->GetItemRect(0, &rcLastItem);
  223. bEnableLeft = rcLastItem.left < 0;
  224. }
  225. m_btnRight.SetRect(CRect(nRight - 14, nTop, nRight, nTop + 15));
  226. m_btnRight.SetEnable(bEnableRight);
  227. m_btnRight.Draw(&dc, clrText);
  228. m_btnLeft.SetRect(CRect(nRight - 28, nTop, nRight -14, nTop + 15));
  229. m_btnLeft.SetEnable(bEnableLeft);
  230. m_btnLeft.Draw(&dc, clrText);
  231. }
  232. else
  233. {
  234. m_btnRight.SetRect(CXTPEmptyRect());
  235. m_btnLeft.SetRect(CXTPEmptyRect());
  236. }
  237. }
  238. BOOL CXTTabCtrlButtons::OnEraseBkgnd(CDC*)
  239. {
  240. return TRUE;
  241. }
  242. int CXTTabCtrlButtons::GetWidth()
  243. {
  244. return 10 + (m_dwFlags & xtNavBtnClose ? 14: 0) + (m_dwFlags & xtNavBtnArrows ? 28 : 0);
  245. }
  246. BOOL CXTTabCtrlButtons::Create(CXTTabBase* pCtrlBase)
  247. {
  248. m_pTabCtrlBase = pCtrlBase;
  249. m_pTabCtrl = m_btnRight.m_pTabCtrl = m_btnClose.m_pTabCtrl = m_btnLeft.m_pTabCtrl = pCtrlBase->GetTabCtrlImpl();
  250. return TRUE;
  251. }
  252. CRect CXTTabCtrlButtons::AdjustRect()
  253. {
  254. CRect rcItem;
  255. m_pTabCtrl->GetItemRect(-1, &rcItem);
  256. CXTPClientRect rc(m_pTabCtrl);
  257. rc.left = rc.right - GetWidth();
  258. rc.bottom = rcItem.bottom + 1;
  259. rc.top = rcItem.top + ((m_pTabCtrl->GetStyle() & TCS_BOTTOM) != 0 ? -2 : 0);
  260. return rc;
  261. }
  262. void CXTTabCtrlButtons::OnLButtonDown(UINT nFlags, CPoint point)
  263. {
  264. if (m_bShow)
  265. {
  266. if (m_btnClose.PtInRect(point) && m_btnClose.Click(this, point))
  267. {
  268. m_pTabCtrl->SendMessage(WM_COMMAND, XT_IDC_TAB_CLOSE);
  269. }
  270. else if (m_btnLeft.PtInRect(point))
  271. {
  272. m_btnLeft.Click(this, point, TRUE);
  273. }
  274. else if (m_btnRight.PtInRect(point))
  275. {
  276. m_btnRight.Click(this, point, TRUE);
  277. }
  278. }
  279. else
  280. {
  281. CWnd::OnLButtonDown(nFlags, point);
  282. }
  283. }
  284. BOOL CXTTabCtrlButtons::ShowButtons()
  285. {
  286. return m_bShow;
  287. }
  288. void CXTTabCtrlButtons::ShowButtons(BOOL bShow)
  289. {
  290. if (m_bShow != bShow)
  291. {
  292. m_bShow = bShow;
  293. if (m_hWnd && !m_bShow) ShowWindow(SW_HIDE);
  294. }
  295. if (m_bShow && m_hWnd)
  296. {
  297. Refresh();
  298. }
  299. }
  300. void CXTTabCtrlButtons::Refresh()
  301. {
  302. if (!m_hWnd) return;
  303. if (m_bShow)
  304. {
  305. CRect rc = AdjustRect();
  306. SetWindowPos(&CWnd::wndTop, rc.left, rc.top, rc.Width(), rc.Height(),
  307. m_pTabCtrl->GetItemCount() > 0 ? SWP_SHOWWINDOW : SWP_HIDEWINDOW);
  308. CPoint point;
  309. GetCursorPos(&point);
  310. ScreenToClient(&point);
  311. OnMouseMove(0, point);
  312. }
  313. Invalidate(FALSE);
  314. }
  315. void CXTTabCtrlButtons::OnMouseMove(UINT , CPoint point)
  316. {
  317. if (m_bShow)
  318. {
  319. m_btnClose.CheckForMouseOver(this, point);
  320. m_btnLeft.CheckForMouseOver(this, point);
  321. m_btnRight.CheckForMouseOver(this, point);
  322. }
  323. }
  324. void CXTTabCtrlButtons::OnMouseLeave()
  325. {
  326. OnMouseMove(0, CPoint(-1, -1));
  327. }
  328. void CXTTabCtrlButtons::SubclassTabButtons(CWnd* pWnd)
  329. {
  330. if (pWnd && pWnd->GetSafeHwnd() && m_hwndSubclassed != pWnd->GetSafeHwnd())
  331. {
  332. UnSubclassTabButtons();
  333. SubclassWindow(*pWnd);
  334. m_hwndSubclassed = pWnd->GetSafeHwnd();
  335. }
  336. else
  337. {
  338. if (!m_hWnd)
  339. {
  340. VERIFY(CWnd::Create(AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),
  341. 0, WS_CHILD | WS_VISIBLE, CXTPEmptyRect(), m_pTabCtrl, 0));
  342. m_hwndPrimary = m_hWnd;
  343. }
  344. }
  345. }
  346. void CXTTabCtrlButtons::UnSubclassTabButtons()
  347. {
  348. if (m_hWnd)
  349. {
  350. HWND hWnd = UnsubclassWindow();
  351. if (hWnd == m_hwndPrimary)
  352. {
  353. ::DestroyWindow(hWnd);
  354. }
  355. }
  356. m_hwndSubclassed = NULL;
  357. }
  358. void CXTTabCtrlButtons::OnWindowPosChanged(WINDOWPOS* lpwndpos)
  359. {
  360. CWnd::OnWindowPosChanged(lpwndpos);
  361. static BOOL bOnWindowPosChanged = FALSE;
  362. if (m_bShow && !bOnWindowPosChanged)
  363. {
  364. if (m_pTabCtrl->GetItemCount() == 0)
  365. return;
  366. bOnWindowPosChanged = TRUE;
  367. CRect rc = AdjustRect();
  368. SetWindowPos(&CWnd::wndTop, rc.left, rc.top, rc.Width(), rc.Height(), SWP_SHOWWINDOW);
  369. bOnWindowPosChanged = FALSE;
  370. }
  371. }
  372. void CXTTabCtrlButtons::SetButtonStyle(DWORD dwFlags)
  373. {
  374. m_dwFlags = dwFlags;
  375. }