YMSelector.cpp
上传用户:baiduw
上传日期:2007-01-01
资源大小:23k
文件大小:12k
源码类别:

界面编程

开发平台:

Visual C++

  1. // YMSelector.cpp : implementation file
  2. // Control to select year and month
  3. // Designed and developed by Shekar Narayanan, 4th July 1998
  4. // ShekarNarayanan@Hotmail.com
  5. // 
  6. // Modified : Jeremy Davis, 3rd December 1998
  7. //            jmd@jvf.co.uk
  8. //
  9. // Changes :
  10. // (03/12/98)
  11. // - Month / Year  display window more "3D"
  12. // - "Cool-look" flat button for "+" and "-" buttons
  13. // - Dropdown button enlarged to match height of month/Year display window
  14. // - Colour of popup window changed
  15. //  - Cell borders removed
  16. // - 3D borders added to popup window and "+" and "-" buttons
  17. // - Cursor / Arrow keys now move month selection in popup window
  18. // - <SPACE> / <RETURN> within the popup window now choose the selection
  19. //  - Keith Rule's (keithr@europa.com) CMemDC class used to stop flickering
  20. //
  21. // Future Changes / Additions :
  22. // - Click outside popup window cause the same action as <ESC>
  23. #include "stdafx.h"
  24. #include "YMSelector.h"
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30. static char *Months[] =
  31. {
  32.     "January",
  33.     "February",
  34.     "March",
  35.     "April",
  36.     "May",
  37.     "June",
  38.     "July",
  39.     "August",
  40.     "September",
  41.     "October",
  42.     "November",
  43.     "December"
  44. };
  45. /////////////////////////////////////////////////////////////////////////////
  46. // CYMPopUp
  47. CYMPopUp::CYMPopUp(CPoint p, CWnd* pParent, int nYear, int nMonth) 
  48. : m_bkBrush(::GetSysColor(COLOR_INFOBK))
  49. {
  50.     if  (-1 == nYear)
  51.         m_nYear     = CTime::GetCurrentTime().GetYear();
  52.     else
  53.         m_nYear     = nYear;
  54.     if  (-1 == nMonth)
  55.         m_nMonth    = CTime::GetCurrentTime().GetMonth() -1;
  56.     else
  57.         m_nMonth    = nMonth -1;
  58. m_inPlus = FALSE;
  59. m_inMinus = FALSE;
  60.     ASSERT(m_nYear >= START_YEAR && m_nYear <= END_YEAR);
  61.     ASSERT(m_nMonth >= 0   && m_nMonth <= 11 );
  62.     Create(p, pParent);
  63. }
  64. CYMPopUp::~CYMPopUp()
  65. {
  66.     m_bkBrush.DeleteObject();
  67. }
  68. BEGIN_MESSAGE_MAP(CYMPopUp, CWnd)
  69. //{{AFX_MSG_MAP(CYMPopUp)
  70. ON_WM_NCDESTROY()
  71. ON_WM_LBUTTONUP()
  72. ON_WM_PAINT()
  73. ON_WM_LBUTTONDOWN()
  74. ON_WM_KEYDOWN()
  75. ON_WM_ERASEBKGND()
  76. ON_WM_MOUSEMOVE()
  77. //}}AFX_MSG_MAP
  78. END_MESSAGE_MAP()
  79. /////////////////////////////////////////////////////////////////////////////
  80. // CYMPopUp message handlers
  81. BOOL CYMPopUp::Create(CPoint p, CWnd* pParent)
  82. {
  83.     m_pParent = pParent;
  84.     ASSERT(m_pParent);
  85.     CString szClassName = AfxRegisterWndClass(CS_CLASSDC|CS_SAVEBITS|CS_HREDRAW|CS_VREDRAW,
  86.                                               0, (HBRUSH)m_bkBrush,0);
  87.     if (!CWnd::CreateEx(0, szClassName, _T(""), WS_VISIBLE|WS_POPUP/*|WS_BORDER*/, 
  88.                         p.x, p.y, 200, 100, 
  89.                         pParent->GetSafeHwnd(), 0, NULL))
  90.         return FALSE;
  91.     m_pParent->EnableWindow(false);
  92.     UpdateWindow();
  93.     return TRUE;
  94. }
  95. void CYMPopUp::OnNcDestroy() 
  96. {
  97. CWnd::OnNcDestroy();
  98.     delete this;
  99. }
  100. void CYMPopUp::OnPaint() 
  101. {
  102. CPaintDC PaintDC(this);
  103. CMemDC dc(&PaintDC);
  104.     CString     Buffer;
  105.     CRect       rClient;
  106.     CRect       rCell;
  107.     CRect       rStart;
  108.     CFont       fText;
  109.     CFont*      pfdc;
  110.     short       nCellHeight;
  111.     short       nCellWidth;
  112.     short       nIndex = 0;
  113.     GetClientRect(rClient);
  114. dc.FillSolidRect(rClient, ::GetSysColor(COLOR_BTNFACE));
  115. dc.DrawEdge(rClient, EDGE_RAISED, BF_RECT);
  116.     rClient.DeflateRect(2,2);
  117.     m_rMinus.CopyRect(rClient);
  118. m_rMinus.left = rClient.left + 1;
  119. m_rMinus.top = rClient.top + 1;
  120.     m_rMinus.right  = m_rMinus.left + 30;
  121.     m_rMinus.bottom = m_rMinus.top + 16;
  122.     m_rPlus.CopyRect(rClient);
  123. m_rPlus.right = rClient.right - 1;
  124. m_rPlus.top = rClient.top + 1;
  125.     m_rPlus.left    = m_rPlus.right - 30;
  126.     m_rPlus.bottom  = m_rPlus.top + 16;
  127.     m_rYear.CopyRect(rClient);
  128.     m_rYear.left    = m_rMinus.right + 5;
  129.     m_rYear.right   = m_rPlus.left   - 5;
  130.     m_rYear.bottom  = m_rYear.top    + 20;
  131.     fText.DeleteObject();
  132.     fText.CreateFont(-12, 0, 0, 0, 700, 0, 0, 0, 1, 0, 0, DRAFT_QUALITY, 0, _T("MS Sans Serif") );
  133.     pfdc = dc.SelectObject(&fText);
  134.     dc.SetBkColor(::GetSysColor(COLOR_BTNFACE));
  135.     dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
  136. dc.SetBkMode(TRANSPARENT);
  137.     Buffer.Format("%d", m_nYear);
  138.     dc.DrawText(Buffer, m_rYear, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
  139. if (m_inMinus)
  140. dc.DrawEdge(&m_rMinus, EDGE_RAISED, BF_RECT);
  141. if (m_inPlus)
  142. dc.DrawEdge(&m_rPlus, EDGE_RAISED, BF_RECT);
  143. dc.SelectObject(pfdc);
  144.     fText.DeleteObject();
  145.     fText.CreatePointFont(80,"MS Sans Serif");
  146. pfdc = dc.SelectObject(&fText);
  147.     dc.DrawText("<<", m_rMinus, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
  148.     dc.DrawText(">>", m_rPlus, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
  149.     dc.SetBkMode(OPAQUE);
  150.     
  151.     nCellHeight     = rClient.Height() / 5;
  152.     nCellWidth      = rClient.Width() / 3;
  153.     rCell.left      = rClient.left;
  154.     rCell.top       = rClient.top + nCellHeight;
  155.     rCell.right     = rCell.left  + nCellWidth;
  156.     rCell.bottom    = rCell.top   + nCellHeight;
  157.     rStart.CopyRect(rCell);
  158.     for (int i = 0; i < 4; i++)
  159.     {
  160.         for (int j = 0; j < 3; j++)
  161.         {
  162.             CRect   rCurSel(rCell);
  163.             
  164.             if  ( m_nMonth == nIndex )
  165.             {
  166.                 dc.FillSolidRect(rCurSel,::GetSysColor(COLOR_HIGHLIGHT));
  167.                 dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
  168.             }
  169.             else
  170.             {
  171.                 dc.FillSolidRect(rCurSel,::GetSysColor(COLOR_BTNFACE));
  172.                 dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
  173.             }
  174.             dc.DrawText(Months[nIndex], rCell, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
  175.             m_rCells[nIndex].CopyRect(rCell);
  176.             rCell.OffsetRect(nCellWidth,0);
  177.             nIndex++;
  178.         }
  179.         rStart.OffsetRect(0,nCellHeight);
  180.         rCell.CopyRect(rStart);
  181.     }
  182.     dc.SelectObject(pfdc);
  183.     fText.DeleteObject();
  184. }
  185. void CYMPopUp::OnLButtonDown(UINT nFlags, CPoint point) 
  186. {
  187.     CClientDC   dc(this);
  188. CWnd::OnLButtonDown(nFlags, point);
  189.     for (int i = 0; i < 12; i++)
  190.     {
  191.         if  (m_rCells[i].PtInRect(point))
  192.         {
  193.             InvalidateRect(m_rCells[m_nMonth]);
  194.             m_nMonth = i;
  195.             InvalidateRect(m_rCells[i]);
  196.             return;
  197.         }
  198.     }
  199.     if  (m_rMinus.PtInRect(point))
  200.         dc.InvertRect(m_rMinus);
  201.     if  (m_rPlus.PtInRect(point))
  202.         dc.InvertRect(m_rPlus);
  203. }
  204. void CYMPopUp::OnLButtonUp(UINT nFlags, CPoint point) 
  205. {
  206.     CClientDC   dc(this);
  207.     CRect       rClient;
  208.     int         nCellHeight;
  209.     if  (m_rMinus.PtInRect(point))
  210.     {
  211.         m_nYear--; 
  212. if   (m_nYear < START_YEAR)m_nYear = START_YEAR;
  213.         dc.InvertRect(m_rMinus);
  214.         InvalidateRect(m_rYear);
  215.         return;
  216.     }
  217.     if  (m_rPlus.PtInRect(point))
  218.     {
  219.         m_nYear++; if   (m_nYear > END_YEAR)m_nYear = END_YEAR;
  220.         dc.InvertRect(m_rPlus);
  221.         InvalidateRect(m_rYear);
  222.         return;
  223.     }
  224.     GetClientRect(rClient);
  225.     rClient.DeflateRect(2,2);
  226.     nCellHeight     = rClient.Height() / 5;
  227.     rClient.top += nCellHeight;
  228.     if  (rClient.PtInRect(point))
  229.     {
  230.         m_pParent->EnableWindow(true);
  231.         m_pParent->PostMessage(YM_SELECTED, (WPARAM)m_nYear, (LPARAM)m_nMonth);
  232.         DestroyWindow();
  233.     }
  234. }
  235. void CYMPopUp::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  236. {
  237. CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  238. switch(nChar)
  239. {
  240. case VK_ESCAPE:
  241. m_pParent->EnableWindow(true);
  242.         m_pParent->SendMessage(YM_ABORTED);
  243.         DestroyWindow();
  244. break;
  245. case VK_RIGHT:
  246. m_nMonth++;
  247. if(m_nMonth == 12)
  248. {
  249. m_nMonth = 0;
  250. m_nYear++;
  251. }
  252. Invalidate();
  253. break;
  254. case VK_LEFT:
  255. m_nMonth--;
  256. if(m_nMonth < 0)
  257. {
  258. m_nMonth = 11;
  259. m_nYear--;
  260. }
  261. Invalidate();
  262. break;
  263. case VK_UP:
  264. m_nMonth -= 3;
  265. if(m_nMonth < 0)
  266. {
  267. m_nMonth += 12;
  268. m_nYear--;
  269. }
  270. Invalidate();
  271. break;
  272. case VK_DOWN:
  273. m_nMonth += 3;
  274. if (m_nMonth > 11)
  275. {
  276. m_nMonth -= 12;
  277. m_nYear++;
  278. }
  279. Invalidate();
  280. break;
  281. case VK_SPACE:
  282. case VK_RETURN:
  283. m_pParent->EnableWindow(true);
  284.         m_pParent->PostMessage(YM_SELECTED, (WPARAM)m_nYear, (LPARAM)m_nMonth);
  285.         DestroyWindow();
  286. break;
  287.     }
  288. }
  289. BOOL CYMPopUp::OnEraseBkgnd(CDC* pDC) 
  290. {
  291.   return FALSE;
  292. }
  293. void CYMPopUp::OnMouseMove(UINT nFlags, CPoint point) 
  294. {
  295. // TODO: Add your message handler code here and/or call default
  296. CClientDC   dc(this);
  297.     BOOL oinPlus = m_inPlus;
  298. BOOL oinMinus = m_inMinus;
  299.     if  (m_rMinus.PtInRect(point))
  300. m_inMinus = TRUE;
  301. else
  302. m_inMinus = FALSE;
  303.     if  (m_rPlus.PtInRect(point))
  304. m_inPlus = TRUE;
  305. else
  306. m_inPlus = FALSE;
  307. if (oinMinus != m_inMinus)
  308. InvalidateRect(&m_rMinus);
  309. if (oinPlus != m_inPlus)
  310. InvalidateRect(&m_rPlus);
  311. CWnd::OnMouseMove(nFlags, point);
  312. }
  313. /////////////////////////////////////////////////////////////////////////////
  314. // CYMSelector
  315. CYMSelector::CYMSelector()
  316. {
  317.     m_nMonth = CTime::GetCurrentTime().GetMonth();
  318.     m_nYear  = CTime::GetCurrentTime().GetYear();
  319. }
  320. CYMSelector::~CYMSelector()
  321. {
  322. }
  323. BEGIN_MESSAGE_MAP(CYMSelector, CButton)
  324. //{{AFX_MSG_MAP(CYMSelector)
  325. ON_CONTROL_REFLECT(BN_CLICKED, OnClicked)
  326. //}}AFX_MSG_MAP
  327.     ON_MESSAGE(YM_SELECTED, YMSelected)
  328.     ON_MESSAGE(YM_ABORTED,  YMAborted)
  329. END_MESSAGE_MAP()
  330. /////////////////////////////////////////////////////////////////////////////
  331. // CYMSelector message handlers
  332. void CYMSelector::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
  333. {
  334.     ASSERT(lpDrawItemStruct);
  335.     CString BtnText;
  336.     CDC*    pDC     = CDC::FromHandle(lpDrawItemStruct->hDC);
  337.     CRect   rect    = lpDrawItemStruct->rcItem;
  338.     UINT    state   = lpDrawItemStruct->itemState;
  339.     
  340.     CRect   rArrow(rect);
  341.     rArrow.left    = rArrow.right - 20;
  342. rArrow.InflateRect(0, 1);
  343.     CSize Margins(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
  344.     pDC->DrawFrameControl(&rArrow, DFC_SCROLL, DFCS_SCROLLDOWN  | 
  345.                           ((state & ODS_SELECTED) ? DFCS_PUSHED : 0) |
  346.                           ((state & ODS_DISABLED) ? DFCS_INACTIVE : 0));
  347.     rect.right -= rArrow.Width();
  348.     pDC->FillSolidRect(rect,::GetSysColor(COLOR_WINDOW));
  349.     GetWindowText(BtnText);
  350.     if  (state & ODS_DISABLED)
  351.         pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
  352.     else
  353.         pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
  354.     pDC->DrawText(BtnText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  355.     if (state & ODS_FOCUS) 
  356.     {
  357.         rect.DeflateRect(2,2);
  358.         pDC->DrawFocusRect(rect);
  359. rect.InflateRect(2,2);
  360.     }
  361.     rect.InflateRect(1,1);
  362.     pDC->DrawEdge(rect,EDGE_SUNKEN,BF_RECT);
  363. rect.DeflateRect(1,1);
  364.     pDC->DrawEdge(rect,EDGE_SUNKEN,BF_RECT);
  365. }
  366. void CYMSelector::PreSubclassWindow() 
  367. {
  368. CButton::PreSubclassWindow();
  369.     CString buffer;
  370.     CTime   tCurrent = CTime::GetCurrentTime();
  371.     buffer = tCurrent.Format("%B, %Y");
  372.     SetWindowText(buffer);
  373.     m_nYear  = tCurrent.GetYear();
  374.     m_nMonth = tCurrent.GetMonth() - 1;
  375. }
  376. void CYMSelector::OnClicked() 
  377. {
  378.     CRect rect;
  379.     GetWindowRect(rect);
  380.     rect.OffsetRect(0,rect.Height());
  381.     GetParent()->EnableWindow(false);
  382.     new CYMPopUp(CPoint(rect.left,rect.top), this,GetYear(),GetMonth());
  383.     return;
  384. }
  385. LONG CYMSelector::YMSelected(WPARAM wParam , LPARAM lParam )
  386. {
  387.     m_nYear   = (int) wParam;
  388.     m_nMonth  = (int)lParam;
  389.     CString buffer;
  390.     buffer.Format("%s, %d", GetMonthString(), GetYear());
  391.     SetWindowText(buffer);
  392.     GetParent()->EnableWindow(true);
  393.     GetParent()->SetFocus();
  394.     return 0;
  395. }
  396. LONG CYMSelector::YMAborted(WPARAM wParam , LPARAM lParam )
  397. {
  398.     GetParent()->EnableWindow(true);
  399.     GetParent()->SetFocus();
  400.     return 0;
  401. }
  402. int CYMSelector::GetYear()
  403. {
  404.     return m_nYear;
  405. }
  406. int CYMSelector::GetMonth()
  407. {
  408.     return m_nMonth + 1;
  409. }
  410. LPCTSTR CYMSelector::GetMonthString()
  411. {
  412.     return Months[m_nMonth];
  413. }
  414. void CYMSelector::SetMonth(int m)
  415. {
  416.     m--;
  417.     ASSERT(m >= 0 && m <= 11);
  418.     m_nMonth = m;
  419.     CString buffer;
  420.     buffer.Format("%s, %d", GetMonthString(), GetYear());
  421.     SetWindowText(buffer);
  422. }
  423. void CYMSelector::SetYear(int y)
  424. {
  425.     ASSERT( y >= START_YEAR && y <= END_YEAR);
  426.     m_nYear = y;
  427.     CString buffer;
  428.     buffer.Format("%s, %d", GetMonthString(), GetYear());
  429.     SetWindowText(buffer);
  430. }