Ftab.cpp
上传用户:wenjimin
上传日期:2014-08-12
资源大小:111k
文件大小:16k
源码类别:

金融证券系统

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////
  2. // If this code works, it was written by Paul DiLascia.
  3. // If not, I don't know who wrote it.
  4. // Compiles with Visual Studio 6.0 on Windows XP. Tab size=3.
  5. //
  6. #include "stdafx.h"
  7. #include "ftab.h"
  8. #ifdef _DEBUG
  9. #define new DEBUG_NEW
  10. #undef THIS_FILE
  11. static char THIS_FILE[] = __FILE__;
  12. #endif
  13. //////////////////
  14. // Private class to represent one folder tab
  15. //
  16. class CFolderTab {
  17. private:
  18. CString m_sText; // tab text
  19. CRect m_rect; // bounding rect
  20. CRgn m_rgn; // polygon region to fill (trapezoid)
  21. int ComputeRgn(CDC& dc, int x);
  22. int Draw(CDC& dc, CFont& font, BOOL bSelected);
  23. BOOL HitTest(CPoint pt) { return m_rgn.PtInRegion(pt); }
  24. CRect GetRect() const { return m_rect; }
  25. void GetTrapezoid(const CRect& rc, CPoint* pts) const;
  26. friend class CFolderTabCtrl;
  27. public:
  28. CFolderTab(LPCTSTR lpszText) : m_sText(lpszText) { }
  29. LPCTSTR GetText() const { return m_sText; }
  30. void   SetText(LPCTSTR lpszText) { m_sText = lpszText; }
  31. };
  32. const CXOFFSET = 8; // defined pitch of trapezoid slant
  33. const CXMARGIN = 2; // left/right text margin
  34. const CYMARGIN = 1; // top/bottom text margin
  35. const CYBORDER = 1; // top border thickness
  36. const CXBUTTON = GetSystemMetrics(SM_CXVSCROLL);
  37. //////////////////
  38. // Compute the the points, rect and region for a tab.
  39. // Input x is starting x pos.
  40. //
  41. int CFolderTab::ComputeRgn(CDC& dc, int x)
  42. {
  43. m_rgn.DeleteObject();
  44. CRect& rc = m_rect;
  45. rc.SetRectEmpty();
  46. // calculate desired text rectangle
  47. dc.DrawText(m_sText, &rc, DT_CALCRECT);
  48. rc.right  += 2*CXOFFSET + 2*CXMARGIN; // add margins
  49. rc.bottom = rc.top + GetSystemMetrics(SM_CYHSCROLL); // ht = scrollbar ht
  50. rc += CPoint(x,0); // shift right
  51. // create trapezoid region
  52. CPoint pts[4];
  53. GetTrapezoid(rc, pts);
  54. m_rgn.CreatePolygonRgn(pts, 4, WINDING);
  55. return rc.Width();
  56. }
  57. //////////////////
  58. // Given the boundint rect, compute trapezoid region.
  59. // Note that the right and bottom edges not included in rect or
  60. // trapezoid; these are normal rules of geometry. 
  61. //
  62. void CFolderTab::GetTrapezoid(const CRect& rc, CPoint* pts) const
  63. {
  64. pts[0] = rc.TopLeft();
  65. pts[1] = CPoint(rc.left + CXOFFSET,   rc.bottom);
  66. pts[2] = CPoint(rc.right- CXOFFSET-1, rc.bottom);
  67. pts[3] = CPoint(rc.right-1, rc.top);
  68. }
  69. //////////////////
  70. // Draw tab in normal or highlighted state
  71. //
  72. int CFolderTab::Draw(CDC& dc, CFont& font, BOOL bSelected)
  73. {
  74. COLORREF bgColor = GetSysColor(bSelected ? COLOR_WINDOW     : COLOR_3DFACE);
  75. COLORREF fgColor = GetSysColor(bSelected ? COLOR_WINDOWTEXT : COLOR_BTNTEXT);
  76. CBrush brush(bgColor);  // background brush
  77. dc.SetBkColor(bgColor);  // text background
  78. dc.SetTextColor(fgColor);  // text color = fg color
  79. CPen blackPen(PS_SOLID, 1, RGB(0,0,0)); // black
  80. CPen shadowPen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
  81. // Fill trapezoid
  82. CPoint pts[4];
  83. CRect rc = m_rect;
  84. GetTrapezoid(rc, pts);
  85. CPen* pOldPen = dc.SelectObject(&blackPen);
  86. dc.FillRgn(&m_rgn, &brush);
  87. // Draw edges. This is requires two corrections:
  88. // 1) Trapezoid dimensions don't include the right and bottom edges,
  89. // so must use one pixel less on bottom (cybottom)
  90. // 2) the endpoint of LineTo is not included when drawing the line, so
  91. // must add one pixel (cytop)
  92. //
  93. pts[1].y--; // correction #1: true bottom edge y-coord
  94. pts[2].y--; // ...ditto
  95. pts[3].y--; // correction #2: extend final LineTo
  96. dc.MoveTo(pts[0]); // upper left
  97. dc.LineTo(pts[1]); // bottom left
  98. dc.SelectObject(&shadowPen); // bottom line is shadow color
  99. dc.MoveTo(pts[1]); // line is inside trapezoid bottom
  100. dc.LineTo(pts[2]); // ...
  101. dc.SelectObject(&blackPen); // upstroke is black
  102. dc.LineTo(pts[3]); // y-1 to include endpoint
  103. if (!bSelected) {
  104. // if not highlighted, upstroke has a 3D shadow, one pixel inside
  105. pts[2].x--; // offset left one pixel
  106. pts[3].x--; // ...ditto
  107. dc.SelectObject(&shadowPen);
  108. dc.MoveTo(pts[2]);
  109. dc.LineTo(pts[3]);
  110. }
  111. dc.SelectObject(pOldPen);
  112. // draw text
  113. rc.DeflateRect(CXOFFSET + CXMARGIN, CYMARGIN);
  114. CFont* pOldFont = dc.SelectObject(&font);
  115. dc.DrawText(m_sText, &rc, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
  116. dc.SelectObject(pOldFont);
  117. return m_rect.right;
  118. }
  119. //////////////////////////////////////////////////////////////////
  120. // CFolderTabCtrl
  121. IMPLEMENT_DYNAMIC(CFolderTabCtrl, CWnd)
  122. BEGIN_MESSAGE_MAP(CFolderTabCtrl, CWnd)
  123. ON_WM_CREATE()
  124. ON_WM_PAINT()
  125. ON_WM_SIZE()
  126. ON_WM_LBUTTONDOWN()
  127. ON_BN_CLICKED(FTBPREV,OnPrevTab)
  128. ON_BN_CLICKED(FTBNEXT,OnNextTab)
  129. END_MESSAGE_MAP()
  130. CFolderTabCtrl::CFolderTabCtrl()
  131. {
  132. m_iCurItem =
  133. m_dwFtabStyle =
  134. m_cxDesired =
  135. m_cxButtons =
  136. m_iFirstTab = 0;
  137. }
  138. CFolderTabCtrl::~CFolderTabCtrl()
  139. {
  140. while (!m_lsTabs.IsEmpty())
  141. delete (CFolderTab*)m_lsTabs.RemoveHead();
  142. }
  143. //////////////////
  144. // Create folder tab control from static control.
  145. // Destroys the static control. This is convenient for dialogs
  146. //
  147. BOOL CFolderTabCtrl::CreateFromStatic(UINT nID, CWnd* pParent)
  148. {
  149. CStatic wndStatic;
  150. if (!wndStatic.SubclassDlgItem(nID, pParent))
  151. return FALSE;
  152. CRect rc;
  153. wndStatic.GetWindowRect(&rc);
  154. pParent->ScreenToClient(&rc);
  155. wndStatic.DestroyWindow();
  156. rc.bottom = rc.top + GetDesiredHeight();
  157. return Create(WS_CHILD|WS_VISIBLE, rc, pParent, nID);
  158. }
  159. //////////////////
  160. // Create folder tab control.
  161. //
  162. BOOL CFolderTabCtrl::Create(DWORD dwStyle, const RECT& rc,
  163. CWnd* pParent, UINT nID, DWORD dwFtabStyle)
  164. {
  165. ASSERT(pParent);
  166. ASSERT(dwStyle & WS_CHILD);
  167. m_dwFtabStyle = dwFtabStyle;
  168. static LPCTSTR lpClassName = _T("PDFolderTab");
  169. static BOOL bRegistered = FALSE; // registered?
  170. if (!bRegistered) {
  171. WNDCLASS wc;
  172. memset(&wc, 0, sizeof(wc));
  173. wc.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
  174. wc.lpfnWndProc = (WNDPROC)::DefWindowProc; // will get hooked by MFC
  175. wc.hInstance = AfxGetInstanceHandle();
  176.       wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  177.       wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
  178.       wc.lpszMenuName = NULL;
  179.       wc.lpszClassName = lpClassName;
  180. if (!AfxRegisterClass(&wc)) {
  181. TRACE("*** CFolderTabCtrl::AfxRegisterClass failed!n");
  182. return FALSE;
  183. }
  184. bRegistered = TRUE;
  185. }
  186. if (!CWnd::CreateEx(0, lpClassName, NULL, dwStyle, rc, pParent, nID))
  187. return FALSE;
  188. // initialize fonts
  189. LOGFONT lf;
  190. memset(&lf, 0, sizeof(lf));
  191. lf.lfHeight = GetSystemMetrics(SM_CYHSCROLL)-CYMARGIN;
  192. lf.lfWeight = FW_NORMAL;
  193. lf.lfCharSet = DEFAULT_CHARSET;
  194. _tcscpy(lf.lfFaceName, _T("Arial"));
  195. m_fontNormal.CreateFontIndirect(&lf);
  196. lf.lfHeight -= 2;
  197. m_fontSelected.CreateFontIndirect(&lf);
  198. return TRUE;
  199. }
  200. //////////////////
  201. // Folder tab was created: create scroll buttons if style says so.
  202. //
  203. int CFolderTabCtrl::OnCreate(LPCREATESTRUCT lpcs)
  204. {
  205. if (CWnd::OnCreate(lpcs)!=0)
  206. return -1;
  207. if (m_dwFtabStyle & FTS_BUTTONS) {
  208. CRect rc;
  209. for (int id=FTBPREV; id<=FTBNEXT; id++) {
  210. VERIFY(m_wndButton[id-1].Create(WS_VISIBLE|WS_CHILD, this, rc, id));
  211. }
  212. m_cxButtons = 2*CXBUTTON;
  213. }
  214. return 0;
  215. }
  216. //////////////////
  217. // Get folder tab text
  218. //
  219. LPCTSTR CFolderTabCtrl::GetItemText(int iItem)
  220. {
  221. CFolderTab* pft = GetTab(iItem);
  222. return pft ? pft->GetText() : NULL;
  223. }
  224. //////////////////
  225. // Set folder tab text
  226. //
  227. void CFolderTabCtrl::SetItemText(int iItem, LPCTSTR lpText)
  228. {
  229. CFolderTab* pft = GetTab(iItem);
  230. if (pft) {
  231. pft->SetText(lpText);
  232. }
  233. }
  234. //////////////////
  235. // copy a font
  236. //
  237. static void CopyFont(CFont& dst, CFont& src)
  238. {
  239. dst.DeleteObject();
  240. LOGFONT lf;
  241. VERIFY(src.GetLogFont(&lf));
  242. dst.CreateFontIndirect(&lf);
  243. }
  244. //////////////////
  245. // Set normal, selected fonts
  246. //
  247. void CFolderTabCtrl::SetFonts(CFont& fontNormal, CFont& fontSelected)
  248. {
  249. CopyFont(m_fontNormal, fontNormal);
  250. CopyFont(m_fontSelected, fontSelected);
  251. }
  252. //////////////////
  253. // Paint function
  254. //
  255. void CFolderTabCtrl::OnPaint() 
  256. {
  257. CPaintDC dc(this); // device context for painting
  258. int xOrigin = m_cxButtons - GetTab(m_iFirstTab)->GetRect().left;
  259. dc.SetViewportOrg(xOrigin,0);
  260. CRect rc;
  261. GetClientRect(&rc);
  262. CFolderTab* pCurTab = NULL;
  263. // draw all the normal (non-selected) tabs
  264. int n = GetItemCount();
  265. for (int i=0; i<n; i++) {
  266. CFolderTab* pTab = GetTab(i);
  267. ASSERT(pTab);
  268. if (i==m_iCurItem) {
  269. pCurTab = pTab;
  270. } else {
  271. pTab->Draw(dc, m_fontNormal, FALSE);
  272. }
  273. }
  274. // draw selected tab last so it will be "on top" of the others
  275. if (pCurTab)
  276. pCurTab->Draw(dc, m_fontSelected, TRUE);
  277. // draw border: line along the top edge, excluding seleted tab
  278. CRect rcCurTab(0,0,0,0);
  279. if (pCurTab)
  280. rcCurTab = pCurTab->GetRect();
  281. rc.right -= xOrigin;
  282. CPen blackPen(PS_SOLID, 1, RGB(0,0,0)); // black
  283. CPen* pOldPen = dc.SelectObject(&blackPen);
  284. dc.MoveTo(rcCurTab.right, rcCurTab.top);
  285. dc.LineTo(rc.right, rc.top);
  286. if (m_dwFtabStyle & FTS_FULLBORDER) {
  287. dc.MoveTo(rc.right-1, rc.top);
  288. dc.LineTo(rc.right-1, rc.bottom-1);
  289. dc.LineTo(rc.left,  rc.bottom-1);
  290. dc.LineTo(rc.left,  rc.top);
  291. } else {
  292. dc.MoveTo(rc.left, rc.top);
  293. }
  294. dc.LineTo(rcCurTab.TopLeft());
  295. dc.SelectObject(pOldPen);
  296. }
  297. //////////////////
  298. // Handle mouse click: select new tab, if any. Notify parent, of course
  299. //
  300. void CFolderTabCtrl::OnLButtonDown(UINT nFlags, CPoint pt)
  301. {
  302. int iTab = HitTest(pt);
  303. if (iTab>=0 && iTab!=m_iCurItem) {
  304. SelectItem(iTab);
  305. NMFOLDERTAB nm;
  306. nm.hwndFrom = m_hWnd;
  307. nm.idFrom = GetDlgCtrlID();
  308. nm.code = FTN_TABCHANGED;
  309. nm.iItem = iTab;
  310. CWnd* pParent = GetParent();
  311. pParent->SendMessage(WM_NOTIFY, nm.idFrom, (LPARAM)&nm);
  312. }
  313. }
  314. //////////////////
  315. // Find which tab is under mouse, -1 if none
  316. //
  317. int CFolderTabCtrl::HitTest(CPoint pt)
  318. {
  319. CRect rc;
  320. GetClientRect(&rc);
  321. rc.left += m_cxButtons;
  322. if (rc.PtInRect(pt)) {
  323. int xOrigin = m_cxButtons - GetTab(m_iFirstTab)->GetRect().left;
  324. pt.x -= xOrigin;
  325. int n = GetItemCount();
  326. for (int i=0; i<n; i++) {
  327. if (GetTab(i)->HitTest(pt))
  328. return i;
  329. }
  330. }
  331. return -1;
  332. }
  333. //////////////////
  334. // Select ith tab. Returns index selected
  335. //
  336. int CFolderTabCtrl::SelectItem(int iTab)
  337. {
  338. int count = GetItemCount();
  339. if (iTab<0 || iTab>=count)
  340. return -1; // bad
  341. if (iTab == m_iCurItem)
  342. return iTab; // already selected
  343. if (m_iCurItem < count)
  344. InvalidateTab(m_iCurItem); // invalidate old tab (repaint)
  345. m_iCurItem = iTab; // set new selected tab
  346. InvalidateTab(m_iCurItem); // repaint new tab
  347. return m_iCurItem;
  348. }
  349. //////////////////
  350. /// Invalidate a tab: invaldate its rect
  351. //
  352. void CFolderTabCtrl::InvalidateTab(int iTab, BOOL bErase)
  353. {
  354. CRect rc = GetTab(iTab)->GetRect();
  355. int xOrigin = m_cxButtons - GetTab(m_iFirstTab)->GetRect().left;
  356. rc += CPoint(xOrigin,0);
  357. InvalidateRect(rc, bErase);
  358. }
  359. //////////////////
  360. // Load folder tab control from resource string:
  361. // newline-separated list of tab names.
  362. //
  363. BOOL CFolderTabCtrl::Load(UINT nIDRes)
  364. {
  365. CString s;
  366. if (!s.LoadString(nIDRes))
  367. return FALSE;
  368. CString sTab;
  369. for (int i=0; AfxExtractSubString(sTab, s, i); i++) {
  370. AddItem(sTab);
  371. }
  372. return TRUE;
  373. }
  374. //////////////////
  375. // Add a tab.
  376. //
  377. int CFolderTabCtrl::AddItem(LPCTSTR lpszText)
  378. {
  379. m_lsTabs.AddTail(new CFolderTab(lpszText));
  380. RecomputeLayout();
  381. return m_lsTabs.GetCount() - 1;
  382. }
  383. //////////////////
  384. // Remove tab at given index.
  385. //
  386. BOOL CFolderTabCtrl::RemoveItem(int iPos)
  387. {
  388. POSITION pos = m_lsTabs.FindIndex(iPos);
  389. if (pos) {
  390. CFolderTab* pTab = (CFolderTab*)m_lsTabs.GetAt(pos);
  391. m_lsTabs.RemoveAt(pos);
  392. delete pTab;
  393. }
  394. RecomputeLayout();
  395. return pos!=NULL;
  396. }
  397. CFolderTab* CFolderTabCtrl::GetTab(int iPos)
  398. {
  399. POSITION pos = m_lsTabs.FindIndex(iPos);
  400. return pos ? static_cast<CFolderTab*>(m_lsTabs.GetAt(pos)) : NULL;
  401. }
  402. //////////////////
  403. // Recalculate layout based on having added or removed a tab.
  404. //
  405. void CFolderTabCtrl::RecomputeLayout()
  406. {
  407. CClientDC dc(this);
  408. CFont* pOldFont = dc.SelectObject(&m_fontNormal);
  409. int x = 0;
  410. int n = GetItemCount();
  411. CFolderTab* pTab;
  412. for (int i=0; i<n; i++) {
  413. pTab = GetTab(i);
  414. if (pTab) 
  415. x += pTab->ComputeRgn(dc, x) - CXOFFSET;
  416. }
  417. dc.SelectObject(pOldFont);
  418. m_cxDesired = m_cxButtons;
  419. if (pTab) {
  420. CRect rc = pTab->GetRect();
  421. m_cxDesired += rc.right;
  422. }
  423. }
  424. //////////////////
  425. // Folder tabs changed size: reposition scroll buttons.
  426. //
  427. void CFolderTabCtrl::OnSize(UINT nType, int cx, int cy)
  428. {
  429. if (m_wndButton[0].m_hWnd) {
  430. int w = cy;
  431. CRect rc(0,0,w,cy);
  432. for (int i=FTBPREV; i<=FTBNEXT; i++) {
  433. m_wndButton[i-1].MoveWindow(&rc);
  434. rc += CPoint(w,0);
  435. }
  436. UpdateButtons();
  437. }
  438. }
  439. //////////////////
  440. // Determine enabled state of scroll buttons
  441. //
  442. void CFolderTabCtrl::UpdateButtons()
  443. {
  444. if (m_wndButton[0].m_hWnd && !m_lsTabs.IsEmpty()) {
  445. // enable prev button iff more tabs to left.
  446. m_wndButton[0].EnableWindow(m_iFirstTab>0);
  447. // enable next button iff more tabs to right
  448. CRect rc;
  449. GetClientRect(&rc);
  450. int xOrigin = m_cxButtons - GetTab(m_iFirstTab)->GetRect().left;
  451. CRect rcLast = ((CFolderTab*)m_lsTabs.GetTail())->GetRect();
  452. m_wndButton[1].EnableWindow(xOrigin + rcLast.right>rc.right);
  453. }
  454. }
  455. //////////////////
  456. // User clicked next button: increment starting tab and repaint
  457. //
  458. void CFolderTabCtrl::OnNextTab()
  459. {
  460. if (m_iFirstTab < m_lsTabs.GetCount()-1) {
  461. m_iFirstTab++;
  462. Invalidate();
  463. UpdateButtons();
  464. }
  465. }
  466. //////////////////
  467. // User clicked prev button: decrement starting tab and repaint
  468. //
  469. void CFolderTabCtrl::OnPrevTab()
  470. {
  471. if (m_iFirstTab > 0) {
  472. m_iFirstTab--;
  473. Invalidate();
  474. UpdateButtons();
  475. }
  476. }
  477. ////////////////////////////////////////////////////////////////
  478. // CFolderButton
  479. //
  480. IMPLEMENT_DYNAMIC(CFolderButton, CButton)
  481. BEGIN_MESSAGE_MAP(CFolderButton, CButton)
  482. ON_WM_LBUTTONDOWN()
  483. ON_WM_LBUTTONUP()
  484. ON_WM_LBUTTONDBLCLK()
  485. ON_WM_TIMER()
  486. END_MESSAGE_MAP()
  487. //////////////////
  488. // Draw sroll button: draw a black triangle.
  489. //
  490. void CFolderButton::DrawItem(LPDRAWITEMSTRUCT lpDis)
  491. {
  492. DRAWITEMSTRUCT& dis = *lpDis;
  493. CDC& dc = *CDC::FromHandle(dis.hDC);
  494. CRect rc;
  495. GetClientRect(&rc);
  496. // fill background with 3D face color
  497. dc.FillSolidRect(&rc,GetSysColor(COLOR_3DFACE));
  498. // shift southeast if button is pressed (bDown)
  499. BOOL bDown = dis.itemState & ODS_SELECTED;
  500. if (bDown) {
  501. rc += CPoint(1,1);
  502. }
  503. // draw line above to match folder tabs
  504. CPen pen(PS_SOLID,1,
  505. dis.itemState & ODS_DISABLED ? GetSysColor(COLOR_3DSHADOW) : RGB(0,0,0));
  506. CPen* pOldPen = dc.SelectObject(&pen);
  507. dc.MoveTo(rc.TopLeft());
  508. dc.LineTo(rc.right,rc.top);
  509. // Draw 3D highlight rect for 3D look
  510. CRect rc2=rc;
  511. for (int i=0; i<2; i++) {
  512. dc.Draw3dRect(&rc2,
  513. GetSysColor(bDown ? COLOR_3DFACE : COLOR_3DHIGHLIGHT),
  514. GetSysColor(COLOR_3DSHADOW));
  515. rc2.right--;
  516. rc2.bottom--;
  517. }
  518. // Draw triangle pointing the right way. Use shadow color if disabled.
  519. CSize szArrow = CSize(4,7);
  520. int cyMargin = (rc.Height()-szArrow.cy)/2;
  521. int cxMargin = (rc.Width()-szArrow.cx)/2;
  522. int x, incr;
  523. if (dis.CtlID==FTBNEXT) {
  524. x = rc.left + cxMargin;
  525. incr = 1;
  526. } else {
  527. x = rc.right - cxMargin - 1;
  528. incr = -1;
  529. }
  530. int y = rc.top + cyMargin;
  531. int h = 7;
  532. for (int j=0; j<4; j++) {
  533. dc.MoveTo(x,y);
  534. dc.LineTo(x,y+h);
  535. h-=2;
  536. x += incr;
  537. y++;
  538. }
  539. dc.SelectObject(pOldPen);
  540. }
  541. //////////////////
  542. // User clicked button.
  543. //
  544. void CFolderButton::OnLButtonDown(UINT nFlags, CPoint pt)
  545. {
  546. Default();  // will send WM_COMMAND to parent
  547. SetTimer(1,500,NULL);  // set timer for continual scroll
  548. m_nTimerClick = 0;  // counter for initial delay
  549. }
  550. //////////////////
  551. // User let go the mouse.
  552. //
  553. void CFolderButton::OnLButtonUp(UINT nFlags, CPoint pt)
  554. {
  555. KillTimer(1);  // no more repeat
  556. Default();
  557. }
  558. //////////////////
  559. // Double-click: treat as another click.
  560. //
  561. void CFolderButton::OnLButtonDblClk(UINT nFlags, CPoint pt)
  562. {
  563. SendMessage(WM_LBUTTONDOWN,nFlags,MAKELONG(pt.x,pt.y));
  564. }
  565. //////////////////
  566. // Timer click: send another WM_COMMMAND, as if button clicked.
  567. //
  568. void CFolderButton::OnTimer(UINT nIDEvent)
  569. {
  570. if (IsWindowEnabled()) {
  571. if (m_nTimerClick++ == 0) {
  572. KillTimer(1);
  573. SetTimer(1,150,NULL);
  574. }
  575. GetParent()->SendMessage(WM_COMMAND, GetDlgCtrlID());
  576. } else {
  577. KillTimer(1);
  578. }
  579. }