| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- #include "StdAfx.h"
- #include "MaskEdit.h"
- #include <math.h>
- // 跟日期输入控件的格式相关的字符串常量
- // 注意:函数CDateEdit::ProcessMask的代码和日期格式有关联
- static LPCTSTR lpszDateMask = _T("0000-00-00");
- static LPCTSTR lpszDateLiteral = _T("____-__-__");
- static LPCTSTR lpszDateFormat = _T("%Y-%m-%d");
- // 跟时间输入控件的格式相关的字符串常量
- // 注意:函数CTimeEdit::ProcessMask的代码和时间格式有关联
- static LPCTSTR lpszTime1Mask = _T("00:00:00"); // 包含“秒”
- static LPCTSTR lpszTime1Literal = _T("__:__:__");
- static LPCTSTR lpszTime1Format = _T("%H:%M:%S");
- static LPCTSTR lpszTime2Mask = _T("00:00"); // 不包含“秒”
- static LPCTSTR lpszTime2Literal = _T("__:__");
- static LPCTSTR lpszTime2Format = _T("%H:%M");
- /////////////////////////////////////////////////////////////////////////////
- // CMaskEdit class
- /////////////////////////////////////////////////////////////////////////////
- CMaskEdit::CMaskEdit( )
- {
- }
- IMPLEMENT_DYNAMIC(CMaskEdit, CEdit)
- BEGIN_MESSAGE_MAP(CMaskEdit, CEdit)
- ON_MASKEDIT_REFLECT()
- END_MESSAGE_MAP()
- void CMaskEdit::SetEditMask(LPCTSTR lpszMask,LPCTSTR lpszLiteral,LPCTSTR lpszDefault /*=NULL*/)
- {
- CMaskEditT<CEdit>::SetEditMask(lpszMask, lpszLiteral, lpszDefault);
- }
- /////////////////////////////////////////////////////////////////////////////
- // CDateEdit class
- /////////////////////////////////////////////////////////////////////////////
- CDateEdit::CDateEdit( )
- {
- m_bUseMask = TRUE;
- m_strMask = lpszDateMask;
- m_strLiteral = lpszDateLiteral;
- }
- IMPLEMENT_DYNAMIC(CDateEdit, CMaskEdit)
- CString CDateEdit::DateToString(COleDateTime dt)
- {
- // 如果输入的COleDateTime对象不合法,则使用缺省构造函数产生的日期
- if (dt.GetStatus() == COleDateTime::valid)
- return dt.Format(lpszDateFormat);
- else
- return COleDateTime().Format(lpszDateFormat);
- }
- COleDateTime CDateEdit::StringToOleDateTime(CString strText, TCHAR chPrompt)
- {
- // 删除文本中的提示字符
- CString strPromptChar(chPrompt);
- strText.Replace(strPromptChar, NULL);
- // 从文本中获取日期/时间
- COleDateTime dt;
- dt.ParseDateTime(strText);
- return dt;
- }
- void CDateEdit::SetDateTime(COleDateTime dt)
- {
- m_strWindowText = DateToString(dt);
- SetWindowText(m_strWindowText);
- }
- COleDateTime CDateEdit::GetDateTime( )
- {
- CString strText;
- GetWindowText(strText);
- COleDateTime dt = StringToOleDateTime(strText, m_chPrompt);
- if (dt.GetStatus() == COleDateTime::valid)
- SetDateTime(dt);
- return dt;
- }
- BOOL CDateEdit::ProcessMask(UINT& nChar,int nEndPos)
- {
- // check the key against the mask
- switch ( m_strMask.GetAt( nEndPos ) )
- {
- case '0': // digit only //completely changed this
- {
- BOOL bReturn = TRUE;
- if ( _istdigit( ( TCHAR )nChar ) )
- {
- if ( nEndPos == 8 ) // 日期的十位
- {
- if ( nChar > '3' ) {
- bReturn = FALSE;
- }
- }
- else if ( nEndPos == 9 ) // 日期的个位
- {
- if ( m_strWindowText.GetAt(8) == '3' )
- {
- if ( nChar > '1' ) {
- bReturn = FALSE;
- }
- }
- }
- else if ( nEndPos == 5 ) // 月份的十位
- {
- if ( nChar > '1' ) {
- bReturn = FALSE;
- }
- }
- else if ( nEndPos == 6 ) // 月份的个位
- {
- if ( m_strWindowText.GetAt(5) == '1' )
- {
- if ( nChar > '2') {
- bReturn = FALSE;
- }
- }
- }
- return bReturn;
- }
- break;
- }
- }
- return FALSE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CTimeEdit class
- /////////////////////////////////////////////////////////////////////////////
- CTimeEdit::CTimeEdit(BOOL bHasSecond /* = FALSE */ )
- {
- m_bHasSecond = bHasSecond;
- m_bUseMask = TRUE;
- m_strMask = m_bHasSecond ? lpszTime1Mask : lpszTime2Mask;
- m_strLiteral = m_bHasSecond ? lpszTime1Literal : lpszTime2Literal;
- }
- IMPLEMENT_DYNAMIC(CTimeEdit, CDateEdit)
- CString CTimeEdit::TimeToString(COleDateTime dt, BOOL bHasSecond /* = FALSE */ )
- {
- // 如果输入的COleDateTime对象不合法,则使用缺省构造函数产生的时间
- LPCTSTR lpsz = bHasSecond ? lpszTime1Format : lpszTime2Format;
- if (dt.GetStatus() == COleDateTime::valid)
- return dt.Format(lpsz);
- else
- return COleDateTime().Format(lpsz);
- }
- void CTimeEdit::SetDateTime(COleDateTime dt)
- {
- m_strWindowText = TimeToString(dt, m_bHasSecond);
- SetWindowText(m_strWindowText);
- }
- BOOL CTimeEdit::ProcessMask(UINT& nChar,int nEndPos)
- {
- // check the key against the mask
- switch ( m_strMask.GetAt( nEndPos ) )
- {
- case '0': // digit only //completely changed this
- {
- if ( _istdigit( (TCHAR)nChar ) )
- {
- switch (nEndPos)
- {
- case 0: // 小时的十位
- if (nChar > '2')
- {
- return FALSE;
- }
- break;
- case 1: // 小时的个位
- if (m_strWindowText.GetAt(0) == '2' && nChar > '3')
- {
- return FALSE;
- }
- break;
- case 3: // 分钟的十位
- if (nChar > '5')
- {
- return FALSE;
- }
- break;
- case 4: // 分钟的个位
- if (nChar > '9')
- {
- return FALSE;
- }
- break;
- case 6: // 秒的十位
- if (nChar > '5')
- {
- return FALSE;
- }
- break;
- case 7: // 秒的个位
- if (nChar > '9')
- {
- return FALSE;
- }
- break;
- }
- return TRUE;
- }
- break;
- }
- }
- return FALSE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // 类 CDegreeEdit
- /////////////////////////////////////////////////////////////////////////////
- CDegreeEdit::CDegreeEdit(int nSecondPrecision /* = 2 */)
- {
- // 确保秒的小数部分的位数在有效范围之内
- const int nMinPrecision = 0; // 最小有效位数
- const int nMaxPrecision = 3; // 最大有效位数
- ASSERT(nSecondPrecision >= nMinPrecision && nSecondPrecision <= nMaxPrecision);
- m_nSecondPrecision = nSecondPrecision;
- if (m_nSecondPrecision < nMinPrecision)
- {
- m_nSecondPrecision = nMinPrecision;
- }
- else if (m_nSecondPrecision > nMaxPrecision)
- {
- m_nSecondPrecision = nMaxPrecision;
- }
- m_chPrompt = _T(' '); // 使用空格做提示字符
- if (m_nSecondPrecision == 0)
- {
- m_strMask = _T("#000°00'00\"");
- m_strLiteral = _T(" ° ' \"");
- }
- else
- {
- m_strMask = _T("#000°00'00.") + CString(_T('0'), m_nSecondPrecision) + _T('\"');
- m_strLiteral = _T(" ° ' .") + CString(_T(' '), m_nSecondPrecision) + _T('\"');
- }
- }
- IMPLEMENT_DYNAMIC(CDegreeEdit, CMaskEdit)
- void CDegreeEdit::SetDegree(double fDegree)
- {
- // 以度分秒的格式显示度
- m_strWindowText = CDegreeEdit::DegreeToString(fDegree, m_nSecondPrecision);
- SetWindowText( m_strWindowText );
- }
- double CDegreeEdit::GetDegree()
- {
- CString strText;
- GetWindowText(strText);
- // 读取数据
- double fDegree = CDegreeEdit::StringToDegree(strText);
- SetDegree(fDegree);
- return fDegree;
- }
- CString CDegreeEdit::DegreeToString(double fDegree, int nSecondPrecision /* = 2 */)
- {
- // 计算度分秒
- int degree, minute;
- double second;
- double temp = fabs(fDegree)+(1E-6/3600);// 由于浮点数存在舍入误差,可能给取整计算度和分
- degree = (int)temp; // 带来问题。例如10.7表示为 double 类型时,其值
- temp = (temp-degree) * 60; // 为10.699...99,取整得到的度等于10,分等于41,
- minute = (int)temp; // 秒用格式%05.2f输出得到60.00。这显然不合理。
- second = (temp-minute) * 60; // 如果加一个很小的数,既能解决这个问题,又不会
- // 影响数值的精确度。这里加的是百万分之一秒。
- // 生成度分秒格式的文本
- CString strFormat; // 格式字符串
- CString strMaxSecond; // 秒的最大值(文本格式)
- if (nSecondPrecision == 0)
- {
- strFormat = _T("%3d°%02d'%02.0f\"");
- strMaxSecond = _T("59");
- }
- else
- {
- strFormat.Format( _T("%%3d°%%02d'%%0%d.%df\""), 3+nSecondPrecision, nSecondPrecision);
- strMaxSecond = _T("59.") + CString(_T('9'), nSecondPrecision);
- }
- #ifdef _UNICODE
- char ansi_buf[256];
- ::WideCharToMultiByte(CP_ACP, 0, strMaxSecond, -1, ansi_buf, 256, NULL, NULL);
- double fMaxSecond = atof(ansi_buf); // 秒的最大值(浮点数格式)
- #else
- double fMaxSecond = atof(strMaxSecond); // 秒的最大值(浮点数格式)
- #endif
- CString strText;
- strText.Format( strFormat,
- min(999,degree), // 不超出999
- minute,
- min(fMaxSecond,second) ); // 避免出现类似59.999"被格式化输出成60.00"的情况
- if (fDegree >= 0)
- strText = _T(' ') + strText;
- else
- strText = _T('-') + strText;
- return strText;
- }
- double CDegreeEdit::StringToDegree(CString strText)
- {
- // 删除文本中的提示字符
- CString strPromptChar( _T(' ') );
- strText.Replace(strPromptChar, NULL);
- // 读取数据
- int degree = 0, minute = 0;
- float second = 0;
- #ifdef _UNICODE
- char ansi_buf[256];
- ::WideCharToMultiByte(CP_ACP, 0, strText, -1, ansi_buf, 256, NULL, NULL);
- sscanf(ansi_buf, "%d°%d'%f", °ree, &minute, &second);
- #else
- sscanf(strText, "%d°%d'%f", °ree, &minute, &second);
- #endif
- double fDegree = abs(degree) + minute/60.0 + second/3600.0;
- fDegree = min(999, fDegree); // 不超出999
- if (strText.Find( _T('-') ) >= 0)
- fDegree = -fDegree;
- return fDegree;
- }
- /////////////////////////////////////////////////////////////////////////////
- // DDX_ routines
- /////////////////////////////////////////////////////////////////////////////
- void AFXAPI DDX_OleDateTime(CDataExchange* pDX, int nIDC, COleDateTime& rDateTime)
- {
- // 从控件ID获取CDateEdit对象指针
- HWND hControl = ::GetDlgItem(pDX->m_pDlgWnd->m_hWnd, nIDC);
- CWnd* pControl = CWnd::FromHandlePermanent(hControl);
- ASSERT(pControl);
- ASSERT(pControl->IsKindOf(RUNTIME_CLASS(CDateEdit)));
- CDateEdit* pDateEdit = (CDateEdit*)pControl;
- // 进行数据交换
- if ( pDX->m_bSaveAndValidate )
- {
- COleDateTime dt = pDateEdit->GetDateTime( );
- if (dt.GetStatus() != COleDateTime::valid)
- {
- if (pDateEdit->IsKindOf(RUNTIME_CLASS(CTimeEdit)))
- // 时间编辑控件
- AfxMessageBox( _T("请键入一个合法的时间。") );
- else
- // 日期编辑控件
- AfxMessageBox( _T("请键入一个合法的日期。") );
- pDX->PrepareCtrl(nIDC);
- pDX->Fail(); // 该函数把输入焦点传给控件,然后抛出一个异常
- }
- rDateTime = dt;
- }
- else
- {
- pDateEdit->SetDateTime( rDateTime );
- }
- }
- void AFXAPI DDX_Degree(CDataExchange* pDX, int nIDC, double& value)
- {
- // 从控件ID获取CDegreeEdit对象指针
- HWND hControl = ::GetDlgItem(pDX->m_pDlgWnd->m_hWnd, nIDC);
- CWnd* pControl = CWnd::FromHandlePermanent(hControl);
- ASSERT(pControl);
- ASSERT(pControl->IsKindOf(RUNTIME_CLASS(CDegreeEdit)));
- CDegreeEdit* pDegreeEdit = (CDegreeEdit*)pControl;
- // 进行数据交换
- if ( pDX->m_bSaveAndValidate )
- {
- value = pDegreeEdit->GetDegree();
- }
- else
- {
- pDegreeEdit->SetDegree( value );
- }
- }
|