
这个类虽然是从CEdit类继承,但做了日期时间的格式化规范,用户输入感觉到很方便,可以用左右键来移动选区,用上下键或滚轮来改变数字,也可直接输入。不会得到错误格式的日期时间格式。
用GetDateTime(COleDateTime& dateSrc)来获取编辑框中的日期时间
用SetDateTime(COleDateTime& dateSrc)来设置编辑框中的日期时间
用ClearDateTime()来清除编辑框中的日期时间
可以EnableWindow(BOOL bEnable)来允许或不允许用户操作。
在界面上放一个CEdit控件,直接关联上这个类就可以用。
已经将代码打包,供用户下载,下面是源代码:
DateTimeEdit.h
#if !defined(AFX_DATETIMEEDIT_H__1F29FB0B_67C1_4606_BAB6_BC7A86CC0B26__INCLUDED_)
#define AFX_DATETIMEEDIT_H__1F29FB0B_67C1_4606_BAB6_BC7A86CC0B26__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// DateTimeEdit.h : header file
//Date Time Selection begin position
#define DTS_YEAR 0
#define DTS_MONTH 5
#define DTS_DAY 8
#define DTS_HOUR 11
#define DTS_MINUTE 14
#define DTS_SECOND 17
/////////////////////////////////////////////////////////////////////////////
// CDateTimeEdit window
class CDateTimeEdit : public CEdit
{
// Construction
public:
CDateTimeEdit();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDateTimeEdit)
public:
virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL
// Implementation
public:
BOOL SetDateTime(const COleDateTime& dateSrc);
BOOL GetDateTime(COleDateTime& dateSrc);
BOOL EnableWindow(BOOL bEnable = TRUE);
void ClearDateTime();
virtual ~CDateTimeEdit();
// Generated message map functions
protected:
int SmartSel(int nPos);
//{{AFX_MSG(CDateTimeEdit)
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
//}}AFX_MSG
int m_nPos;
BOOL m_bEnable;
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_DATETIMEEDIT_H__1F29FB0B_67C1_4606_BAB6_BC7A86CC0B26__INCLUDED_)
#define AFX_DATETIMEEDIT_H__1F29FB0B_67C1_4606_BAB6_BC7A86CC0B26__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// DateTimeEdit.h : header file
//Date Time Selection begin position
#define DTS_YEAR 0
#define DTS_MONTH 5
#define DTS_DAY 8
#define DTS_HOUR 11
#define DTS_MINUTE 14
#define DTS_SECOND 17
/////////////////////////////////////////////////////////////////////////////
// CDateTimeEdit window
class CDateTimeEdit : public CEdit
{
// Construction
public:
CDateTimeEdit();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDateTimeEdit)
public:
virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
protected:
virtual void PreSubclassWindow();
//}}AFX_VIRTUAL
// Implementation
public:
BOOL SetDateTime(const COleDateTime& dateSrc);
BOOL GetDateTime(COleDateTime& dateSrc);
BOOL EnableWindow(BOOL bEnable = TRUE);
void ClearDateTime();
virtual ~CDateTimeEdit();
// Generated message map functions
protected:
int SmartSel(int nPos);
//{{AFX_MSG(CDateTimeEdit)
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
//}}AFX_MSG
int m_nPos;
BOOL m_bEnable;
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_DATETIMEEDIT_H__1F29FB0B_67C1_4606_BAB6_BC7A86CC0B26__INCLUDED_)
DateTimeEdit.cpp
// DateTimeEdit.cpp : implementation file
//
#include "stdafx.h"
#include "DateTimeEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDateTimeEdit
CDateTimeEdit::CDateTimeEdit()
{
m_nPos = 0;
m_bEnable = TRUE;
}
CDateTimeEdit::~CDateTimeEdit()
{
}
BEGIN_MESSAGE_MAP(CDateTimeEdit, CEdit)
//{{AFX_MSG_MAP(CDateTimeEdit)
ON_WM_KEYDOWN()
ON_WM_CHAR()
ON_WM_SIZE()
ON_WM_LBUTTONUP()
ON_WM_MOUSEWHEEL()
ON_WM_CTLCOLOR_REFLECT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDateTimeEdit message handlers
BOOL CDateTimeEdit::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
dwStyle |= WS_CHILD | WS_TABSTOP | ES_MULTILINE | ES_READONLY;
dwStyle &= ~ES_WANTRETURN;
return CWnd::Create("EDIT", NULL, dwStyle, rect, pParentWnd, nID, NULL);
}
void CDateTimeEdit::PreSubclassWindow()
{
ModifyStyle(ES_WANTRETURN, WS_CHILD | WS_TABSTOP | ES_MULTILINE | ES_READONLY);//归整样式
SetWindowText(" - - : : ");
//垂直居中,必须有多行样式
CRect rc;
GetClientRect(&rc);
CDC* pDC = GetDC();
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
::InflateRect(&rc, 0, - (rc.Height() - tm.tmHeight) / 2);
SetRect(&rc);
CEdit::PreSubclassWindow();
}
void CDateTimeEdit::OnSize(UINT nType, int cx, int cy)
{
CEdit::OnSize(nType, cx, cy);
if (::IsWindow(m_hWnd))
{//垂直居中
CDC* pDC = GetDC();
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
RECT rc = {0, 0, cx, cy};
::InflateRect(&rc, 0, - (cy - tm.tmHeight) / 2);
SetRect(&rc);
}
}
HBRUSH CDateTimeEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
int nIndex = m_bEnable ? COLOR_WINDOW : COLOR_BTNFACE;
HBRUSH hbr = ::GetSysColorBrush(nIndex);
pDC->SetBkMode(TRANSPARENT);
return hbr;
}
void CDateTimeEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (!m_bEnable)
return;
//yyyy-mm-dd hh:mm:ss
//0123456789012345678
int nStartChar, nEndChar;
switch (nChar)
{
case VK_LEFT:
GetSel(nStartChar, nEndChar);
if (nStartChar > DTS_YEAR)
{
m_nPos = SmartSel(nStartChar - 1);
}
return;
case VK_RIGHT:
GetSel(nStartChar, nEndChar);
if (nEndChar < DTS_SECOND)
{
m_nPos = SmartSel(nEndChar + 1);
}
return;
case VK_UP:
SendMessage(WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), 0);//数字变大
return;
case VK_DOWN:
SendMessage(WM_MOUSEWHEEL, MAKEWPARAM(0, - WHEEL_DELTA), 0);//数字变小
return;
}
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CDateTimeEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (!m_bEnable)
return;
if (nChar >= '0' && nChar <='9')
{
//yyyy-mm-dd hh:mm:ss
//0123456789012345678
int nStartChar, nEndChar;
GetSel(nStartChar, nEndChar);
char str[20];
GetWindowText(str, sizeof(str));
memcpy(str + m_nPos, &nChar, 1);
SetWindowText(str);
SetSel(nStartChar, nEndChar);
switch (m_nPos)
{
case 0:
case 1:
case 2:
case 3:
m_nPos = m_nPos < 3 ? ++ m_nPos : DTS_YEAR;
break;
case 5:
case 6:
m_nPos = m_nPos < 6 ? ++ m_nPos : DTS_MONTH;
break;
case 8:
case 9:
m_nPos = m_nPos < 9 ? ++ m_nPos : DTS_DAY;
break;
case 11:
case 12:
m_nPos = m_nPos < 12 ? ++ m_nPos : DTS_HOUR;
break;
case 14:
case 15:
m_nPos = m_nPos < 15 ? ++ m_nPos : DTS_MINUTE;
break;
case 17:
case 18:
m_nPos = m_nPos < 18 ? ++ m_nPos : DTS_SECOND;
break;
}
return;
}
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
BOOL CDateTimeEdit::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
if (!m_bEnable)
return FALSE;
COleDateTime dateSrc;
if (!GetDateTime(dateSrc))
return FALSE;
int nStartChar, nEndChar;
CString str, s;
int n;
GetSel(nStartChar, nEndChar);
GetWindowText(str);
s = str.Mid(nStartChar, nEndChar - nStartChar);
sscanf(s, "%d", &n);
zDelta > 0 ? n ++ : n --;
if (n < 0)
return FALSE;
int nYear = dateSrc.GetYear();
int nMonth = dateSrc.GetMonth();
int nDay = dateSrc.GetDay();
int nHour = dateSrc.GetHour();
int nMin = dateSrc.GetMinute();
int nSec = dateSrc.GetSecond();
switch (nStartChar)
{
case DTS_YEAR:
nYear = n;
break;
case DTS_MONTH:
nMonth = n;
break;
case DTS_DAY:
nDay = n;
break;
case DTS_HOUR:
nHour = n;
break;
case DTS_MINUTE:
nMin = n;
break;
case DTS_SECOND:
nSec = n;
break;
}
dateSrc.SetDateTime(nYear, nMonth, nDay, nHour, nMin, nSec);
SetDateTime(dateSrc);
SetSel(nStartChar, nEndChar);
return TRUE;
}
void CDateTimeEdit::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bEnable)
{
COleDateTime dateSrc;
if (!GetDateTime(dateSrc))
{//左键点击时,如果日期时间不有效,则设置为当前日期时间
SetDateTime(COleDateTime::GetCurrentTime());
}
m_nPos = SmartSel(CharFromPos(point));
}
CEdit::OnLButtonUp(nFlags, point);
}
int CDateTimeEdit::SmartSel(int nPos)
{//返回选区的初始位置
//yyyy-mm-dd hh:mm:ss
//0123456789012345678
int nStartChar, nEndChar;
switch (nPos)
{
case 0:
case 1:
case 2:
case 3:
case 4:
nStartChar = DTS_YEAR;
nEndChar = DTS_YEAR + 4;
break;
case 5:
case 6:
case 7:
nStartChar = DTS_MONTH;
nEndChar = DTS_MONTH + 2;
break;
case 8:
case 9:
case 10:
nStartChar = DTS_DAY;
nEndChar = DTS_DAY + 2;
break;
case 11:
case 12:
case 13:
nStartChar = DTS_HOUR;
nEndChar = DTS_HOUR + 2;
break;
case 14:
case 15:
case 16:
nStartChar = DTS_MINUTE;
nEndChar = DTS_MINUTE + 2;
break;
case 17:
case 18:
case 19:
nStartChar = DTS_SECOND;
nEndChar = DTS_SECOND + 2;
break;
default:
nStartChar = DTS_SECOND;
}
SetSel(nStartChar, nEndChar);
return nStartChar;
}
BOOL CDateTimeEdit::SetDateTime(const COleDateTime& dateSrc)
{
BOOL bRes = FALSE;
if (dateSrc.GetStatus() == COleDateTime::valid)
{
CString str = dateSrc.Format("%Y-%m-%d %H:%M:%S");
SetWindowText(str);
bRes = TRUE;
}
return bRes;
}
BOOL CDateTimeEdit::GetDateTime(COleDateTime& dateSrc)
{
CString str;
GetWindowText(str);
return dateSrc.ParseDateTime(str);
}
void CDateTimeEdit::ClearDateTime()
{
SetWindowText(" - - : : ");
}
BOOL CDateTimeEdit::EnableWindow(BOOL bEnable)
{
BOOL bRes = FALSE;
if (m_bEnable != bEnable)
{
m_bEnable = bEnable;
Invalidate();
bRes = TRUE;
}
return bRes;
}
//
#include "stdafx.h"
#include "DateTimeEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CDateTimeEdit
CDateTimeEdit::CDateTimeEdit()
{
m_nPos = 0;
m_bEnable = TRUE;
}
CDateTimeEdit::~CDateTimeEdit()
{
}
BEGIN_MESSAGE_MAP(CDateTimeEdit, CEdit)
//{{AFX_MSG_MAP(CDateTimeEdit)
ON_WM_KEYDOWN()
ON_WM_CHAR()
ON_WM_SIZE()
ON_WM_LBUTTONUP()
ON_WM_MOUSEWHEEL()
ON_WM_CTLCOLOR_REFLECT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDateTimeEdit message handlers
BOOL CDateTimeEdit::Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
{
dwStyle |= WS_CHILD | WS_TABSTOP | ES_MULTILINE | ES_READONLY;
dwStyle &= ~ES_WANTRETURN;
return CWnd::Create("EDIT", NULL, dwStyle, rect, pParentWnd, nID, NULL);
}
void CDateTimeEdit::PreSubclassWindow()
{
ModifyStyle(ES_WANTRETURN, WS_CHILD | WS_TABSTOP | ES_MULTILINE | ES_READONLY);//归整样式
SetWindowText(" - - : : ");
//垂直居中,必须有多行样式
CRect rc;
GetClientRect(&rc);
CDC* pDC = GetDC();
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
::InflateRect(&rc, 0, - (rc.Height() - tm.tmHeight) / 2);
SetRect(&rc);
CEdit::PreSubclassWindow();
}
void CDateTimeEdit::OnSize(UINT nType, int cx, int cy)
{
CEdit::OnSize(nType, cx, cy);
if (::IsWindow(m_hWnd))
{//垂直居中
CDC* pDC = GetDC();
TEXTMETRIC tm;
pDC->GetTextMetrics(&tm);
RECT rc = {0, 0, cx, cy};
::InflateRect(&rc, 0, - (cy - tm.tmHeight) / 2);
SetRect(&rc);
}
}
HBRUSH CDateTimeEdit::CtlColor(CDC* pDC, UINT nCtlColor)
{
int nIndex = m_bEnable ? COLOR_WINDOW : COLOR_BTNFACE;
HBRUSH hbr = ::GetSysColorBrush(nIndex);
pDC->SetBkMode(TRANSPARENT);
return hbr;
}
void CDateTimeEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (!m_bEnable)
return;
//yyyy-mm-dd hh:mm:ss
//0123456789012345678
int nStartChar, nEndChar;
switch (nChar)
{
case VK_LEFT:
GetSel(nStartChar, nEndChar);
if (nStartChar > DTS_YEAR)
{
m_nPos = SmartSel(nStartChar - 1);
}
return;
case VK_RIGHT:
GetSel(nStartChar, nEndChar);
if (nEndChar < DTS_SECOND)
{
m_nPos = SmartSel(nEndChar + 1);
}
return;
case VK_UP:
SendMessage(WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA), 0);//数字变大
return;
case VK_DOWN:
SendMessage(WM_MOUSEWHEEL, MAKEWPARAM(0, - WHEEL_DELTA), 0);//数字变小
return;
}
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CDateTimeEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (!m_bEnable)
return;
if (nChar >= '0' && nChar <='9')
{
//yyyy-mm-dd hh:mm:ss
//0123456789012345678
int nStartChar, nEndChar;
GetSel(nStartChar, nEndChar);
char str[20];
GetWindowText(str, sizeof(str));
memcpy(str + m_nPos, &nChar, 1);
SetWindowText(str);
SetSel(nStartChar, nEndChar);
switch (m_nPos)
{
case 0:
case 1:
case 2:
case 3:
m_nPos = m_nPos < 3 ? ++ m_nPos : DTS_YEAR;
break;
case 5:
case 6:
m_nPos = m_nPos < 6 ? ++ m_nPos : DTS_MONTH;
break;
case 8:
case 9:
m_nPos = m_nPos < 9 ? ++ m_nPos : DTS_DAY;
break;
case 11:
case 12:
m_nPos = m_nPos < 12 ? ++ m_nPos : DTS_HOUR;
break;
case 14:
case 15:
m_nPos = m_nPos < 15 ? ++ m_nPos : DTS_MINUTE;
break;
case 17:
case 18:
m_nPos = m_nPos < 18 ? ++ m_nPos : DTS_SECOND;
break;
}
return;
}
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
BOOL CDateTimeEdit::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
if (!m_bEnable)
return FALSE;
COleDateTime dateSrc;
if (!GetDateTime(dateSrc))
return FALSE;
int nStartChar, nEndChar;
CString str, s;
int n;
GetSel(nStartChar, nEndChar);
GetWindowText(str);
s = str.Mid(nStartChar, nEndChar - nStartChar);
sscanf(s, "%d", &n);
zDelta > 0 ? n ++ : n --;
if (n < 0)
return FALSE;
int nYear = dateSrc.GetYear();
int nMonth = dateSrc.GetMonth();
int nDay = dateSrc.GetDay();
int nHour = dateSrc.GetHour();
int nMin = dateSrc.GetMinute();
int nSec = dateSrc.GetSecond();
switch (nStartChar)
{
case DTS_YEAR:
nYear = n;
break;
case DTS_MONTH:
nMonth = n;
break;
case DTS_DAY:
nDay = n;
break;
case DTS_HOUR:
nHour = n;
break;
case DTS_MINUTE:
nMin = n;
break;
case DTS_SECOND:
nSec = n;
break;
}
dateSrc.SetDateTime(nYear, nMonth, nDay, nHour, nMin, nSec);
SetDateTime(dateSrc);
SetSel(nStartChar, nEndChar);
return TRUE;
}
void CDateTimeEdit::OnLButtonUp(UINT nFlags, CPoint point)
{
if (m_bEnable)
{
COleDateTime dateSrc;
if (!GetDateTime(dateSrc))
{//左键点击时,如果日期时间不有效,则设置为当前日期时间
SetDateTime(COleDateTime::GetCurrentTime());
}
m_nPos = SmartSel(CharFromPos(point));
}
CEdit::OnLButtonUp(nFlags, point);
}
int CDateTimeEdit::SmartSel(int nPos)
{//返回选区的初始位置
//yyyy-mm-dd hh:mm:ss
//0123456789012345678
int nStartChar, nEndChar;
switch (nPos)
{
case 0:
case 1:
case 2:
case 3:
case 4:
nStartChar = DTS_YEAR;
nEndChar = DTS_YEAR + 4;
break;
case 5:
case 6:
case 7:
nStartChar = DTS_MONTH;
nEndChar = DTS_MONTH + 2;
break;
case 8:
case 9:
case 10:
nStartChar = DTS_DAY;
nEndChar = DTS_DAY + 2;
break;
case 11:
case 12:
case 13:
nStartChar = DTS_HOUR;
nEndChar = DTS_HOUR + 2;
break;
case 14:
case 15:
case 16:
nStartChar = DTS_MINUTE;
nEndChar = DTS_MINUTE + 2;
break;
case 17:
case 18:
case 19:
nStartChar = DTS_SECOND;
nEndChar = DTS_SECOND + 2;
break;
default:
nStartChar = DTS_SECOND;
}
SetSel(nStartChar, nEndChar);
return nStartChar;
}
BOOL CDateTimeEdit::SetDateTime(const COleDateTime& dateSrc)
{
BOOL bRes = FALSE;
if (dateSrc.GetStatus() == COleDateTime::valid)
{
CString str = dateSrc.Format("%Y-%m-%d %H:%M:%S");
SetWindowText(str);
bRes = TRUE;
}
return bRes;
}
BOOL CDateTimeEdit::GetDateTime(COleDateTime& dateSrc)
{
CString str;
GetWindowText(str);
return dateSrc.ParseDateTime(str);
}
void CDateTimeEdit::ClearDateTime()
{
SetWindowText(" - - : : ");
}
BOOL CDateTimeEdit::EnableWindow(BOOL bEnable)
{
BOOL bRes = FALSE;
if (m_bEnable != bEnable)
{
m_bEnable = bEnable;
Invalidate();
bRes = TRUE;
}
return bRes;
}