📄 ymselector.cpp
字号:
// YMSelector.cpp : implementation file
// Control to select year and month
// Designed and developed by Shekar Narayanan, 4th July 1998
// ShekarNarayanan@Hotmail.com
//
// Modified : Jeremy Davis, 3rd December 1998
// jmd@jvf.co.uk
//
// Changes :
// (03/12/98)
// - Month / Year display window more "3D"
// - "Cool-look" flat button for "+" and "-" buttons
// - Dropdown button enlarged to match height of month/Year display window
// - Colour of popup window changed
// - Cell borders removed
// - 3D borders added to popup window and "+" and "-" buttons
// - Cursor / Arrow keys now move month selection in popup window
// - <SPACE> / <RETURN> within the popup window now choose the selection
// - Keith Rule's (keithr@europa.com) CMemDC class used to stop flickering
//
// Future Changes / Additions :
// - Click outside popup window cause the same action as <ESC>
#include "stdafx.h"
#include "YMSelector.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static char *Months[] =
{
"一月",
"二月",
"三月",
"四月",
"五月",
"六月",
"七月",
"八月",
"九月",
"十月",
"十一月",
"十二月"
};
/////////////////////////////////////////////////////////////////////////////
// CYMPopUp
CYMPopUp::CYMPopUp(CPoint p, CWnd* pParent, int nYear, int nMonth)
: m_bkBrush(::GetSysColor(COLOR_INFOBK))
{
if (-1 == nYear)
m_nYear = CTime::GetCurrentTime().GetYear();
else
m_nYear = nYear;
if (-1 == nMonth)
m_nMonth = CTime::GetCurrentTime().GetMonth() -1;
else
m_nMonth = nMonth -1;
m_inPlus = FALSE;
m_inMinus = FALSE;
ASSERT(m_nYear >= START_YEAR && m_nYear <= END_YEAR);
ASSERT(m_nMonth >= 0 && m_nMonth <= 11 );
Create(p, pParent);
}
CYMPopUp::~CYMPopUp()
{
m_bkBrush.DeleteObject();
}
BEGIN_MESSAGE_MAP(CYMPopUp, CWnd)
//{{AFX_MSG_MAP(CYMPopUp)
ON_WM_NCDESTROY()
ON_WM_LBUTTONUP()
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
ON_WM_KEYDOWN()
ON_WM_ERASEBKGND()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CYMPopUp message handlers
BOOL CYMPopUp::Create(CPoint p, CWnd* pParent)
{
m_pParent = pParent;
ASSERT(m_pParent);
CString szClassName = AfxRegisterWndClass(CS_CLASSDC|CS_SAVEBITS|CS_HREDRAW|CS_VREDRAW,
0, (HBRUSH)m_bkBrush,0);
if (!CWnd::CreateEx(0, szClassName, _T(""), WS_VISIBLE|WS_POPUP/*|WS_BORDER*/,
p.x, p.y, 200, 100,
pParent->GetSafeHwnd(), 0, NULL))
return FALSE;
m_pParent->EnableWindow(false);
UpdateWindow();
return TRUE;
}
void CYMPopUp::OnNcDestroy()
{
CWnd::OnNcDestroy();
delete this;
}
void CYMPopUp::OnPaint()
{
CPaintDC PaintDC(this);
CMemDC dc(&PaintDC);
CString Buffer;
CRect rClient;
CRect rCell;
CRect rStart;
CFont fText;
CFont* pfdc;
short nCellHeight;
short nCellWidth;
short nIndex = 0;
GetClientRect(rClient);
dc.FillSolidRect(rClient, ::GetSysColor(COLOR_BTNFACE));
dc.DrawEdge(rClient, EDGE_RAISED, BF_RECT);
rClient.DeflateRect(2,2);
m_rMinus.CopyRect(rClient);
m_rMinus.left = rClient.left + 1;
m_rMinus.top = rClient.top + 1;
m_rMinus.right = m_rMinus.left + 30;
m_rMinus.bottom = m_rMinus.top + 16;
m_rPlus.CopyRect(rClient);
m_rPlus.right = rClient.right - 1;
m_rPlus.top = rClient.top + 1;
m_rPlus.left = m_rPlus.right - 30;
m_rPlus.bottom = m_rPlus.top + 16;
m_rYear.CopyRect(rClient);
m_rYear.left = m_rMinus.right + 5;
m_rYear.right = m_rPlus.left - 5;
m_rYear.bottom = m_rYear.top + 20;
fText.DeleteObject();
fText.CreateFont(-12, 0, 0, 0, 700, 0, 0, 0, 1, 0, 0, DRAFT_QUALITY, 0, _T("MS Sans Serif") );
pfdc = dc.SelectObject(&fText);
dc.SetBkColor(::GetSysColor(COLOR_BTNFACE));
dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
dc.SetBkMode(TRANSPARENT);
Buffer.Format("%d", m_nYear);
dc.DrawText(Buffer, m_rYear, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
if (m_inMinus)
dc.DrawEdge(&m_rMinus, EDGE_RAISED, BF_RECT);
if (m_inPlus)
dc.DrawEdge(&m_rPlus, EDGE_RAISED, BF_RECT);
dc.SelectObject(pfdc);
fText.DeleteObject();
fText.CreatePointFont(80,"MS Sans Serif");
pfdc = dc.SelectObject(&fText);
dc.DrawText("<<", m_rMinus, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
dc.DrawText(">>", m_rPlus, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
dc.SetBkMode(OPAQUE);
nCellHeight = rClient.Height() / 5;
nCellWidth = rClient.Width() / 3;
rCell.left = rClient.left;
rCell.top = rClient.top + nCellHeight;
rCell.right = rCell.left + nCellWidth;
rCell.bottom = rCell.top + nCellHeight;
rStart.CopyRect(rCell);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
CRect rCurSel(rCell);
if ( m_nMonth == nIndex )
{
dc.FillSolidRect(rCurSel,::GetSysColor(COLOR_HIGHLIGHT));
dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
dc.FillSolidRect(rCurSel,::GetSysColor(COLOR_BTNFACE));
dc.SetTextColor(::GetSysColor(COLOR_BTNTEXT));
}
dc.DrawText(Months[nIndex], rCell, DT_VCENTER|DT_CENTER|DT_SINGLELINE);
m_rCells[nIndex].CopyRect(rCell);
rCell.OffsetRect(nCellWidth,0);
nIndex++;
}
rStart.OffsetRect(0,nCellHeight);
rCell.CopyRect(rStart);
}
dc.SelectObject(pfdc);
fText.DeleteObject();
}
void CYMPopUp::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
CWnd::OnLButtonDown(nFlags, point);
for (int i = 0; i < 12; i++)
{
if (m_rCells[i].PtInRect(point))
{
InvalidateRect(m_rCells[m_nMonth]);
m_nMonth = i;
InvalidateRect(m_rCells[i]);
return;
}
}
if (m_rMinus.PtInRect(point))
dc.InvertRect(m_rMinus);
if (m_rPlus.PtInRect(point))
dc.InvertRect(m_rPlus);
}
void CYMPopUp::OnLButtonUp(UINT nFlags, CPoint point)
{
CClientDC dc(this);
CRect rClient;
int nCellHeight;
if (m_rMinus.PtInRect(point))
{
m_nYear--;
if (m_nYear < START_YEAR)m_nYear = START_YEAR;
dc.InvertRect(m_rMinus);
InvalidateRect(m_rYear);
return;
}
if (m_rPlus.PtInRect(point))
{
m_nYear++; if (m_nYear > END_YEAR)m_nYear = END_YEAR;
dc.InvertRect(m_rPlus);
InvalidateRect(m_rYear);
return;
}
GetClientRect(rClient);
rClient.DeflateRect(2,2);
nCellHeight = rClient.Height() / 5;
rClient.top += nCellHeight;
if (rClient.PtInRect(point))
{
m_pParent->EnableWindow(true);
m_pParent->PostMessage(YM_SELECTED, (WPARAM)m_nYear, (LPARAM)m_nMonth);
DestroyWindow();
}
}
void CYMPopUp::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
switch(nChar)
{
case VK_ESCAPE:
m_pParent->EnableWindow(true);
m_pParent->SendMessage(YM_ABORTED);
DestroyWindow();
break;
case VK_RIGHT:
m_nMonth++;
if(m_nMonth == 12)
{
m_nMonth = 0;
m_nYear++;
}
Invalidate();
break;
case VK_LEFT:
m_nMonth--;
if(m_nMonth < 0)
{
m_nMonth = 11;
m_nYear--;
}
Invalidate();
break;
case VK_UP:
m_nMonth -= 3;
if(m_nMonth < 0)
{
m_nMonth += 12;
m_nYear--;
}
Invalidate();
break;
case VK_DOWN:
m_nMonth += 3;
if (m_nMonth > 11)
{
m_nMonth -= 12;
m_nYear++;
}
Invalidate();
break;
case VK_SPACE:
case VK_RETURN:
m_pParent->EnableWindow(true);
m_pParent->PostMessage(YM_SELECTED, (WPARAM)m_nYear, (LPARAM)m_nMonth);
DestroyWindow();
break;
}
}
BOOL CYMPopUp::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
void CYMPopUp::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
BOOL oinPlus = m_inPlus;
BOOL oinMinus = m_inMinus;
if (m_rMinus.PtInRect(point))
m_inMinus = TRUE;
else
m_inMinus = FALSE;
if (m_rPlus.PtInRect(point))
m_inPlus = TRUE;
else
m_inPlus = FALSE;
if (oinMinus != m_inMinus)
InvalidateRect(&m_rMinus);
if (oinPlus != m_inPlus)
InvalidateRect(&m_rPlus);
CWnd::OnMouseMove(nFlags, point);
}
/////////////////////////////////////////////////////////////////////////////
// CYMSelector
CYMSelector::CYMSelector()
{
m_nMonth = CTime::GetCurrentTime().GetMonth();
m_nYear = CTime::GetCurrentTime().GetYear();
}
CYMSelector::~CYMSelector()
{
}
BEGIN_MESSAGE_MAP(CYMSelector, CButton)
//{{AFX_MSG_MAP(CYMSelector)
ON_CONTROL_REFLECT(BN_CLICKED, OnClicked)
//}}AFX_MSG_MAP
ON_MESSAGE(YM_SELECTED, YMSelected)
ON_MESSAGE(YM_ABORTED, YMAborted)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CYMSelector message handlers
void CYMSelector::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT(lpDrawItemStruct);
CString BtnText;
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
CRect rect = lpDrawItemStruct->rcItem;
UINT state = lpDrawItemStruct->itemState;
CRect rArrow(rect);
rArrow.left = rArrow.right - 20;
rArrow.InflateRect(0, 1);
CSize Margins(::GetSystemMetrics(SM_CXEDGE), ::GetSystemMetrics(SM_CYEDGE));
pDC->DrawFrameControl(&rArrow, DFC_SCROLL, DFCS_SCROLLDOWN |
((state & ODS_SELECTED) ? DFCS_PUSHED : 0) |
((state & ODS_DISABLED) ? DFCS_INACTIVE : 0));
rect.right -= rArrow.Width();
pDC->FillSolidRect(rect,::GetSysColor(COLOR_WINDOW));
GetWindowText(BtnText);
if (state & ODS_DISABLED)
pDC->SetTextColor(::GetSysColor(COLOR_GRAYTEXT));
else
pDC->SetTextColor(::GetSysColor(COLOR_BTNTEXT));
pDC->DrawText(BtnText, rect, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
if (state & ODS_FOCUS)
{
rect.DeflateRect(2,2);
pDC->DrawFocusRect(rect);
rect.InflateRect(2,2);
}
rect.InflateRect(1,1);
pDC->DrawEdge(rect,EDGE_SUNKEN,BF_RECT);
rect.DeflateRect(1,1);
pDC->DrawEdge(rect,EDGE_SUNKEN,BF_RECT);
}
void CYMSelector::PreSubclassWindow()
{
CButton::PreSubclassWindow();
CString buffer;
CTime tCurrent = CTime::GetCurrentTime();
buffer = tCurrent.Format("%B, %Y");
SetWindowText(buffer);
m_nYear = tCurrent.GetYear();
m_nMonth = tCurrent.GetMonth() - 1;
}
void CYMSelector::OnClicked()
{
CRect rect;
GetWindowRect(rect);
rect.OffsetRect(0,rect.Height());
GetParent()->EnableWindow(false);
new CYMPopUp(CPoint(rect.left,rect.top), this,GetYear(),GetMonth());
return;
}
LONG CYMSelector::YMSelected(WPARAM wParam , LPARAM lParam )
{
m_nYear = (int) wParam;
m_nMonth = (int)lParam;
CString buffer;
buffer.Format("%s, %d", GetMonthString(), GetYear());
SetWindowText(buffer);
GetParent()->EnableWindow(true);
GetParent()->SetFocus();
return 0;
}
LONG CYMSelector::YMAborted(WPARAM wParam , LPARAM lParam )
{
GetParent()->EnableWindow(true);
GetParent()->SetFocus();
return 0;
}
int CYMSelector::GetYear()
{
return m_nYear;
}
int CYMSelector::GetMonth()
{
return m_nMonth + 1;
}
LPCTSTR CYMSelector::GetMonthString()
{
return Months[m_nMonth];
}
void CYMSelector::SetMonth(int m)
{
m--;
ASSERT(m >= 0 && m <= 11);
m_nMonth = m;
CString buffer;
buffer.Format("%s, %d", GetMonthString(), GetYear());
SetWindowText(buffer);
}
void CYMSelector::SetYear(int y)
{
ASSERT( y >= START_YEAR && y <= END_YEAR);
m_nYear = y;
CString buffer;
buffer.Format("%s, %d", GetMonthString(), GetYear());
SetWindowText(buffer);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -