You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1087 lines
22 KiB
1087 lines
22 KiB
#include "stdafx.h"
|
|
#include "SDateTimeEdit.h"
|
|
|
|
namespace SOUI{
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDxMaskEdit
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
SMaskEdit::SMaskEdit()
|
|
: m_nStartChar(0)
|
|
, m_nEndChar(0)
|
|
, m_bOverType(FALSE)
|
|
, m_bUseMask(TRUE)
|
|
, m_bModified(FALSE)
|
|
, m_strWindowText(_T(""))
|
|
, m_strMask(_T(""))
|
|
, m_strLiteral(_T(""))
|
|
, m_strDefault(_T(""))
|
|
, m_chPrompt(_T('_'))
|
|
{
|
|
}
|
|
|
|
void SMaskEdit::SetUseMask(BOOL bUseMask)
|
|
{
|
|
m_bUseMask = bUseMask;
|
|
}
|
|
|
|
BOOL SMaskEdit::CanUseMask() const
|
|
{
|
|
return m_bUseMask && ((m_dwStyle & ES_READONLY) == 0) && !m_strMask.IsEmpty();
|
|
}
|
|
|
|
void SMaskEdit::SetOverType(BOOL bOverType)
|
|
{
|
|
m_bOverType = bOverType;
|
|
}
|
|
|
|
BOOL SMaskEdit::CanOverType() const
|
|
{
|
|
return m_bOverType;
|
|
}
|
|
|
|
BOOL SMaskEdit::PosInRange(int nPos) const
|
|
{
|
|
return ((nPos >= 0) && (nPos < m_strLiteral.GetLength()));
|
|
}
|
|
|
|
TCHAR SMaskEdit::GetPromptChar() const
|
|
{
|
|
return m_chPrompt;
|
|
}
|
|
|
|
SStringT SMaskEdit::GetPromptString(int nLength) const
|
|
{
|
|
SStringT strPrompt;
|
|
|
|
while (nLength--)
|
|
strPrompt += m_chPrompt;
|
|
|
|
return strPrompt;
|
|
}
|
|
|
|
void SMaskEdit::SetPromptChar(TCHAR ch, BOOL bAutoReplace)
|
|
{
|
|
if (m_chPrompt == ch)
|
|
return;
|
|
|
|
if (bAutoReplace)
|
|
{
|
|
GetMaskState();
|
|
|
|
for (int i = 0; i < m_strLiteral.GetLength(); i++)
|
|
if (m_strLiteral[i] == m_chPrompt) m_strLiteral.SetAt(i, ch);
|
|
|
|
for (int j = 0; j < m_strWindowText.GetLength(); j++)
|
|
if (m_strWindowText[j] == m_chPrompt) m_strWindowText.SetAt(j, ch);
|
|
|
|
SetMaskState();
|
|
}
|
|
|
|
m_chPrompt = ch;
|
|
}
|
|
|
|
BOOL SMaskEdit::MaskCut()
|
|
{
|
|
//if (!CanUseMask())
|
|
// return (BOOL)DefWindowProc(WM_CUT, 0, 0);
|
|
|
|
MaskCopy();
|
|
MaskClear();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL SMaskEdit::MaskCopy()
|
|
{
|
|
//if (!CanUseMask())
|
|
// return (BOOL)DefWindowProc(WM_COPY, 0, 0);
|
|
|
|
GetMaskState();
|
|
|
|
SStringT strMaskedText = GetMaskedText(m_nStartChar, m_nEndChar);
|
|
CopyToClipboard(strMaskedText);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void SMaskEdit::MaskReplaceSel(LPCTSTR lpszNewText)
|
|
{
|
|
SASSERT(CanUseMask());
|
|
|
|
if (m_nStartChar != m_nEndChar)
|
|
MaskDeleteSel();
|
|
|
|
int x = m_nStartChar, nNewTextLen = (int)_tcslen(lpszNewText);
|
|
int nWindowTextLen = m_strWindowText.GetLength();
|
|
|
|
if (x >= nWindowTextLen)
|
|
return;
|
|
|
|
for (int i = 0; i < nNewTextLen; ++i)
|
|
{
|
|
TCHAR ch = lpszNewText[i];
|
|
|
|
if (ch == m_chPrompt || CheckChar(ch, x))
|
|
{
|
|
InsertCharAt(x, ch);
|
|
x++;
|
|
|
|
while (x < nWindowTextLen && !IsPromptPos(x))
|
|
x++;
|
|
|
|
if (x >= m_strWindowText.GetLength())
|
|
break;
|
|
}
|
|
}
|
|
CorrectPosition(x);
|
|
m_nStartChar = m_nEndChar = x;
|
|
}
|
|
|
|
BOOL SMaskEdit::MaskPaste()
|
|
{
|
|
//if (!CanUseMask())
|
|
// return (BOOL)DefWindowProc(WM_PASTE, 0, 0);
|
|
|
|
GetMaskState();
|
|
|
|
if (!OpenClipboard(NULL))
|
|
return FALSE;
|
|
|
|
#ifndef _UNICODE
|
|
HGLOBAL hglbPaste = ::GetClipboardData(CF_TEXT);
|
|
#else
|
|
HGLOBAL hglbPaste = ::GetClipboardData(CF_UNICODETEXT);
|
|
#endif
|
|
|
|
if (hglbPaste != NULL)
|
|
{
|
|
TCHAR* lpszClipboard = (TCHAR*)GlobalLock(hglbPaste);
|
|
|
|
MaskReplaceSel(lpszClipboard);
|
|
|
|
GlobalUnlock(hglbPaste);
|
|
|
|
SetMaskState();
|
|
}
|
|
::CloseClipboard();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void SMaskEdit::MaskDeleteSel()
|
|
{
|
|
if (m_nStartChar == m_nEndChar)
|
|
return;
|
|
|
|
SStringT strMaskedText = GetMaskedText(m_nEndChar);
|
|
SetMaskedText(strMaskedText, m_nStartChar, FALSE);
|
|
|
|
m_nEndChar = m_nStartChar;
|
|
}
|
|
|
|
BOOL SMaskEdit::MaskClear()
|
|
{
|
|
//if (!CanUseMask())
|
|
// return (BOOL)DefWindowProc(WM_CLEAR, 0, 0);
|
|
|
|
GetMaskState();
|
|
|
|
MaskDeleteSel();
|
|
|
|
SetMaskState();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void SMaskEdit::MaskSelectAll()
|
|
{
|
|
if (!CanUseMask())
|
|
{
|
|
SetSel(0, -1);
|
|
}
|
|
else
|
|
{
|
|
m_nStartChar = 0;
|
|
CorrectPosition(m_nStartChar);
|
|
SetSel(m_nStartChar, -1);
|
|
}
|
|
}
|
|
|
|
BOOL SMaskEdit::IsModified() const
|
|
{
|
|
return m_bModified;
|
|
}
|
|
|
|
void SMaskEdit::SetMaskedText(LPCTSTR lpszMaskedText, int nPos, BOOL bUpdateWindow)
|
|
{
|
|
int nMaskedTextLength = (int)_tcslen(lpszMaskedText);
|
|
|
|
m_strWindowText = m_strWindowText.Left(nPos);
|
|
|
|
int nIndex = 0;
|
|
for (; (nPos < m_strLiteral.GetLength()) && (nIndex < nMaskedTextLength) ; nPos++)
|
|
{
|
|
TCHAR uChar = lpszMaskedText[nIndex];
|
|
|
|
if (IsPromptPos(nPos) && ((uChar == m_chPrompt) || ProcessMask(uChar, nPos)))
|
|
{
|
|
m_strWindowText += (TCHAR)uChar;
|
|
nIndex ++;
|
|
}
|
|
else
|
|
{
|
|
m_strWindowText += m_strLiteral[nPos];
|
|
}
|
|
}
|
|
|
|
if (bUpdateWindow)
|
|
{
|
|
SetMaskState();
|
|
}
|
|
else
|
|
{
|
|
CorrectWindowText();
|
|
}
|
|
}
|
|
|
|
BOOL SMaskEdit::SetEditMask(LPCTSTR lpszMask, LPCTSTR lpszLiteral, LPCTSTR lpszDefault)
|
|
{
|
|
SASSERT(lpszMask);
|
|
SASSERT(lpszLiteral);
|
|
|
|
// initialize the mask for the control.
|
|
m_strMask = lpszMask;
|
|
m_strLiteral = lpszLiteral;
|
|
|
|
SASSERT(m_strMask.GetLength() == m_strLiteral.GetLength());
|
|
|
|
if (m_strMask.GetLength() != m_strLiteral.GetLength())
|
|
return FALSE;
|
|
|
|
if (lpszDefault == NULL)
|
|
{
|
|
m_strWindowText = m_strDefault = lpszLiteral;
|
|
}
|
|
else
|
|
{
|
|
m_strWindowText = m_strDefault = lpszDefault;
|
|
|
|
if (m_strDefault.GetLength() != m_strLiteral.GetLength())
|
|
{
|
|
SetMaskedText(m_strDefault, 0, FALSE);
|
|
m_strDefault = m_strWindowText;
|
|
}
|
|
}
|
|
|
|
SASSERT(m_strWindowText.GetLength() == m_strLiteral.GetLength());
|
|
|
|
// set the window text for the control.
|
|
m_bModified = FALSE;
|
|
SetWindowText(S_CT2W(m_strWindowText));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
TCHAR SMaskEdit::ConvertUnicodeAlpha(TCHAR nChar, BOOL bUpperCase) const
|
|
{
|
|
SStringT strTemp(nChar);
|
|
if (bUpperCase)
|
|
strTemp.MakeUpper();
|
|
else
|
|
strTemp.MakeLower();
|
|
|
|
return strTemp[0];
|
|
}
|
|
|
|
BOOL SMaskEdit::CheckChar(TCHAR& nChar, int nPos)
|
|
{
|
|
// do not use mask
|
|
if (!CanUseMask())
|
|
return FALSE;
|
|
|
|
// control character, OK
|
|
if (!IsPrintChar(nChar))
|
|
return TRUE;
|
|
|
|
// make sure the string is not longer than the mask
|
|
if (nPos >= m_strMask.GetLength())
|
|
return FALSE;
|
|
|
|
if (!IsPromptPos(nPos))
|
|
return FALSE;
|
|
|
|
return ProcessMask(nChar, nPos);
|
|
}
|
|
|
|
BOOL SMaskEdit::ProcessMask(TCHAR& nChar, int nEndPos)
|
|
{
|
|
SASSERT(nEndPos < m_strMask.GetLength());
|
|
if (nEndPos < 0 || nEndPos >= m_strMask.GetLength())
|
|
return FALSE;
|
|
|
|
// check the key against the mask
|
|
switch (m_strMask.GetAt(nEndPos))
|
|
{
|
|
case '0': // digit only //completely changed this
|
|
return _istdigit(nChar);
|
|
|
|
case '9': // digit or space
|
|
return _istdigit(nChar) || _istspace(nChar);
|
|
|
|
case '#': // digit or space or '+' or '-'
|
|
return _istdigit(nChar) || (_istspace(nChar) || nChar == _T('-') || nChar == _T('+'));
|
|
|
|
case 'd': // decimal
|
|
return _istdigit(nChar) || (_istspace(nChar) || nChar == _T('-') || nChar == _T('+') || nChar == _T('.') || nChar == _T(','));
|
|
|
|
case 'L': // alpha only
|
|
return IsAlphaChar(nChar);
|
|
|
|
case '?': // alpha or space
|
|
return IsAlphaChar(nChar) || _istspace(nChar);
|
|
|
|
case 'A': // alpha numeric only
|
|
return _istalnum(nChar) || IsAlphaChar(nChar);
|
|
|
|
case 'a': // alpha numeric or space
|
|
return _istalnum(nChar) || IsAlphaChar(nChar) || _istspace(nChar);
|
|
|
|
case '&': // all print character only
|
|
return IsPrintChar(nChar);
|
|
|
|
case 'H': // hex digit
|
|
return _istxdigit(nChar);
|
|
|
|
case 'X': // hex digit or space
|
|
return _istxdigit(nChar) || _istspace(nChar);
|
|
|
|
case '>':
|
|
if (IsAlphaChar(nChar))
|
|
{
|
|
nChar = ConvertUnicodeAlpha(nChar, TRUE);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
|
|
case '<':
|
|
if (IsAlphaChar(nChar))
|
|
{
|
|
nChar = ConvertUnicodeAlpha(nChar, FALSE);
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#if 0
|
|
BOOL CDxMaskEdit::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
if (!CanUseMask())
|
|
return TBase::PreTranslateMessage(pMsg);
|
|
|
|
// intercept Ctrl+C (copy), Ctrl+V (paste), Ctrl+X (cut) and Ctrl+Z (undo)
|
|
// before CEdit base class gets a hold of them.
|
|
|
|
if (pMsg->message == WM_KEYDOWN)
|
|
{
|
|
if (::GetKeyState(VK_SUBTRACT) < 0)
|
|
{
|
|
OnChar('-', 1, 1);
|
|
return TRUE;
|
|
}
|
|
|
|
if (::GetKeyState(VK_ADD) < 0)
|
|
{
|
|
OnChar('+', 1, 1);
|
|
return TRUE;
|
|
}
|
|
|
|
if (::GetKeyState(VK_CONTROL) < 0)
|
|
{
|
|
switch (pMsg->wParam)
|
|
{
|
|
case 'X':
|
|
case 'x':
|
|
{
|
|
MaskCut();
|
|
return TRUE;
|
|
}
|
|
|
|
case 'C':
|
|
case 'c':
|
|
{
|
|
MaskCopy();
|
|
return TRUE;
|
|
}
|
|
|
|
case 'V':
|
|
case 'v':
|
|
{
|
|
MaskPaste();
|
|
return TRUE;
|
|
}
|
|
|
|
case 'Z':
|
|
case 'z':
|
|
{
|
|
MaskUndo();
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return TBase::PreTranslateMessage(pMsg);
|
|
}
|
|
#endif
|
|
|
|
void SMaskEdit::DeleteCharAt(int nPos)
|
|
{
|
|
SASSERT(PosInRange(nPos));
|
|
|
|
if (!PosInRange(nPos))
|
|
return;
|
|
|
|
SStringT strMaskedText = GetMaskedText(nPos + 1) + m_chPrompt;
|
|
|
|
SetMaskedText(strMaskedText, nPos, FALSE);
|
|
}
|
|
|
|
void SMaskEdit::InsertCharAt(int nPos, TCHAR nChar)
|
|
{
|
|
SASSERT(PosInRange(nPos));
|
|
|
|
if (!PosInRange(nPos))
|
|
return;
|
|
|
|
SStringT strMaskedText = SStringT(nChar) + GetMaskedText(nPos);
|
|
|
|
SetMaskedText(strMaskedText, nPos, FALSE);
|
|
}
|
|
|
|
BOOL SMaskEdit::CopyToClipboard(const SStringT& strText)
|
|
{
|
|
if (!OpenClipboard(NULL))
|
|
return FALSE;
|
|
|
|
::EmptyClipboard();
|
|
|
|
int nLen = (strText.GetLength() + 1) * sizeof(TCHAR);
|
|
|
|
HGLOBAL hglbCopy = ::GlobalAlloc(GMEM_MOVEABLE, nLen);
|
|
|
|
if (hglbCopy == NULL)
|
|
{
|
|
::CloseClipboard();
|
|
return FALSE;
|
|
}
|
|
|
|
LPTSTR lptstrCopy = (TCHAR*)GlobalLock(hglbCopy);
|
|
_tcscpy_s(lptstrCopy, strText.GetLength() + 1, (LPCTSTR)strText);
|
|
GlobalUnlock(hglbCopy);
|
|
|
|
#ifndef _UNICODE
|
|
::SetClipboardData(CF_TEXT, hglbCopy);
|
|
#else
|
|
::SetClipboardData(CF_UNICODETEXT, hglbCopy);
|
|
#endif
|
|
|
|
if (!::CloseClipboard())
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
SStringT SMaskEdit::GetMaskedText(int nStartPos, int nEndPos) const
|
|
{
|
|
if (nEndPos == -1)
|
|
nEndPos = m_strWindowText.GetLength();
|
|
else
|
|
nEndPos = min(nEndPos, m_strWindowText.GetLength());
|
|
|
|
SStringT strBuffer;
|
|
|
|
for (int i = nStartPos; i < nEndPos; ++i)
|
|
{
|
|
if (IsPromptPos(i))
|
|
{
|
|
strBuffer += m_strWindowText[i];
|
|
}
|
|
}
|
|
|
|
return strBuffer;
|
|
}
|
|
|
|
void SMaskEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (!CanUseMask())
|
|
{
|
|
__super::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
return;
|
|
}
|
|
|
|
BOOL bShift = (::GetKeyState(VK_SHIFT) < 0);
|
|
BOOL bCtrl = (::GetKeyState(VK_CONTROL) < 0);
|
|
|
|
switch (nChar)
|
|
{
|
|
case VK_UP:
|
|
case VK_LEFT:
|
|
case VK_HOME:
|
|
{
|
|
__super::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
|
|
GetMaskState(FALSE);
|
|
|
|
int nStartChar = m_nStartChar;
|
|
CorrectPosition(nStartChar, FALSE);
|
|
|
|
if (m_nStartChar < nStartChar)
|
|
{
|
|
m_nStartChar = nStartChar;
|
|
|
|
if (!bShift)
|
|
m_nEndChar = nStartChar;
|
|
}
|
|
|
|
SetMaskState();
|
|
}
|
|
return;
|
|
|
|
case VK_DOWN:
|
|
case VK_RIGHT:
|
|
case VK_END:
|
|
{
|
|
__super::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
|
|
GetMaskState(FALSE);
|
|
|
|
int iEndChar = m_nEndChar;
|
|
CorrectPosition(iEndChar);
|
|
|
|
if (m_nEndChar > iEndChar)
|
|
{
|
|
m_nEndChar = iEndChar;
|
|
|
|
if (!bShift)
|
|
m_nStartChar = iEndChar;
|
|
}
|
|
|
|
SetMaskState();
|
|
}
|
|
return;
|
|
|
|
case VK_INSERT:
|
|
{
|
|
if (bCtrl)
|
|
{
|
|
MaskCopy();
|
|
}
|
|
else if (bShift)
|
|
{
|
|
MaskPaste();
|
|
}
|
|
else
|
|
{
|
|
m_bOverType = !m_bOverType; // set the type-over flag
|
|
}
|
|
}
|
|
return;
|
|
|
|
case VK_DELETE:
|
|
{
|
|
GetMaskState();
|
|
|
|
if (m_nStartChar == m_nEndChar)
|
|
{
|
|
m_nEndChar = m_nStartChar +1;
|
|
}
|
|
else if (bShift)
|
|
{
|
|
MaskCopy();
|
|
}
|
|
|
|
MaskDeleteSel();
|
|
SetMaskState();
|
|
}
|
|
return;
|
|
|
|
case VK_SPACE:
|
|
{
|
|
GetMaskState();
|
|
|
|
if (!PosInRange(m_nStartChar) || !IsPromptPos(m_nStartChar))
|
|
{
|
|
NotifyPosNotInRange();
|
|
return;
|
|
}
|
|
|
|
TCHAR chSpace = _T(' ');
|
|
|
|
if (!ProcessMask(chSpace, m_nStartChar))
|
|
chSpace = m_chPrompt;
|
|
|
|
ProcessChar(chSpace);
|
|
|
|
SetMaskState();
|
|
}
|
|
return;
|
|
|
|
case VK_BACK:
|
|
{
|
|
GetMaskState(FALSE);
|
|
|
|
if (((m_nStartChar > 0) || (m_nStartChar == 0 && m_nEndChar != 0)) && (m_nStartChar <= m_strLiteral.GetLength()))
|
|
{
|
|
if (m_nStartChar == m_nEndChar)
|
|
{
|
|
m_nStartChar--;
|
|
CorrectPosition(m_nStartChar, FALSE);
|
|
|
|
if (m_bOverType && PosInRange(m_nStartChar))
|
|
{
|
|
m_strWindowText.SetAt(m_nStartChar, m_strDefault[m_nStartChar]);
|
|
m_nEndChar = m_nStartChar;
|
|
}
|
|
}
|
|
|
|
MaskDeleteSel();
|
|
SetMaskState();
|
|
}
|
|
else
|
|
{
|
|
NotifyPosNotInRange();
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
__super::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void SMaskEdit::ProcessChar(TCHAR nChar)
|
|
{
|
|
int nLen = m_strLiteral.GetLength();
|
|
|
|
if (m_nStartChar >= nLen)
|
|
{
|
|
NotifyPosNotInRange();
|
|
return;
|
|
}
|
|
|
|
if (m_nStartChar != m_nEndChar)
|
|
{
|
|
MaskDeleteSel();
|
|
}
|
|
|
|
SASSERT(m_nStartChar == m_nEndChar);
|
|
|
|
CorrectPosition(m_nStartChar);
|
|
|
|
if (CanOverType())
|
|
{
|
|
m_strWindowText.SetAt(m_nStartChar, nChar);
|
|
}
|
|
else
|
|
{
|
|
InsertCharAt(m_nStartChar, nChar);
|
|
}
|
|
|
|
if (m_nStartChar < nLen)
|
|
m_nStartChar++;
|
|
|
|
CorrectPosition(m_nStartChar);
|
|
|
|
m_nEndChar = m_nStartChar;
|
|
}
|
|
|
|
int SMaskEdit::OnCreate(LPVOID)
|
|
{
|
|
int nRet = __super::OnCreate(NULL);
|
|
if (nRet != 0)
|
|
return nRet;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void SMaskEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (!CanUseMask())
|
|
{
|
|
__super::OnChar(nChar, nRepCnt, nFlags);
|
|
return;
|
|
}
|
|
|
|
switch (nChar)
|
|
{
|
|
case VK_SPACE:
|
|
case VK_BACK:
|
|
return; // handled in WM_KEYDOWN
|
|
}
|
|
|
|
GetMaskState();
|
|
|
|
if (!PosInRange(m_nStartChar) || !IsPromptPos(m_nStartChar))
|
|
{
|
|
NotifyPosNotInRange();
|
|
return;
|
|
}
|
|
|
|
TCHAR ch = (TCHAR)nChar;
|
|
|
|
if (!CheckChar(ch, m_nStartChar))
|
|
{
|
|
NotifyInvalidCharacter(ch, m_strMask[m_nStartChar]);
|
|
return;
|
|
}
|
|
|
|
if (IsPrintChar(ch))
|
|
{
|
|
ProcessChar(ch);
|
|
SetMaskState();
|
|
}
|
|
else
|
|
{
|
|
if (nChar != 127)
|
|
__super::OnChar(nChar, nRepCnt, nFlags);
|
|
}
|
|
}
|
|
|
|
void SMaskEdit::OnSetFocus(SWND wndOld)
|
|
{
|
|
__super::OnSetFocus(wndOld);
|
|
|
|
if (!CanUseMask())
|
|
{
|
|
return;
|
|
}
|
|
|
|
MaskGetSel();
|
|
CorrectPosition(m_nStartChar);
|
|
|
|
m_nEndChar = m_nStartChar;
|
|
SetSel(m_nStartChar, m_nEndChar);
|
|
}
|
|
|
|
// Some goodies
|
|
BOOL SMaskEdit::CorrectPosition(int& nPos, BOOL bForward)
|
|
{
|
|
int nLen = m_strLiteral.GetLength();
|
|
|
|
if (IsPromptPos(nPos))
|
|
return TRUE;
|
|
|
|
if (bForward)
|
|
{
|
|
for (; nPos < nLen; nPos++)
|
|
{
|
|
if (IsPromptPos(nPos))
|
|
return TRUE;
|
|
}
|
|
|
|
for (; nPos >= 0; nPos--)
|
|
{
|
|
if (IsPromptPos(nPos - 1))
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (; nPos >= 0; nPos--)
|
|
{
|
|
if (IsPromptPos(nPos))
|
|
return TRUE;
|
|
}
|
|
|
|
for (; nPos < nLen; nPos++)
|
|
{
|
|
if (IsPromptPos(nPos))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL SMaskEdit::IsPrintChar(TCHAR nChar)
|
|
{
|
|
return _istprint(nChar) || IsAlphaChar(nChar);
|
|
}
|
|
|
|
BOOL SMaskEdit::IsAlphaChar(TCHAR nChar)
|
|
{
|
|
if (_istalpha(nChar))
|
|
return TRUE;
|
|
|
|
if (ConvertUnicodeAlpha(nChar, TRUE) != nChar)
|
|
return TRUE;
|
|
|
|
if (ConvertUnicodeAlpha(nChar, FALSE) != nChar)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void SMaskEdit::NotifyPosNotInRange()
|
|
{
|
|
::MessageBeep((UINT)-1);
|
|
}
|
|
|
|
void SMaskEdit::NotifyInvalidCharacter(TCHAR /*nChar*/, TCHAR /*chMask*/)
|
|
{
|
|
::MessageBeep((UINT)-1);
|
|
}
|
|
|
|
BOOL SMaskEdit::IsPromptPos(int nPos) const
|
|
{
|
|
return IsPromptPos(m_strLiteral, nPos);
|
|
}
|
|
|
|
BOOL SMaskEdit::IsPromptPos(const SStringT& strLiteral, int nPos) const
|
|
{
|
|
return (nPos >= 0 && nPos < strLiteral.GetLength()) && (strLiteral[nPos] == m_chPrompt);
|
|
}
|
|
|
|
void SMaskEdit::CorrectWindowText()
|
|
{
|
|
int nLiteralLength = m_strLiteral.GetLength();
|
|
int nWindowTextLength = m_strWindowText.GetLength();
|
|
|
|
if (nWindowTextLength > nLiteralLength)
|
|
{
|
|
m_strWindowText = m_strWindowText.Left(nLiteralLength);
|
|
}
|
|
else if (nWindowTextLength < nLiteralLength)
|
|
{
|
|
m_strWindowText += m_strLiteral.Mid(nWindowTextLength, nLiteralLength - nWindowTextLength);
|
|
}
|
|
}
|
|
|
|
void SMaskEdit::GetMaskState(BOOL bCorrectSelection)
|
|
{
|
|
SASSERT(m_bUseMask);
|
|
|
|
MaskGetSel();
|
|
m_strWindowText = GetWindowText();
|
|
|
|
SASSERT(m_strDefault.GetLength() == m_strLiteral.GetLength());
|
|
SASSERT(m_strMask.GetLength() == m_strLiteral.GetLength());
|
|
|
|
CorrectWindowText();
|
|
|
|
if (bCorrectSelection)
|
|
{
|
|
CorrectPosition(m_nStartChar);
|
|
CorrectPosition(m_nEndChar);
|
|
|
|
if (m_nEndChar < m_nStartChar)
|
|
m_nEndChar = m_nStartChar;
|
|
}
|
|
}
|
|
|
|
void SMaskEdit::MaskGetSel()
|
|
{
|
|
SSendMessage(EM_GETSEL,(WPARAM)&m_nStartChar,(LPARAM)&m_nEndChar);
|
|
}
|
|
|
|
void SMaskEdit::SetMaskState()
|
|
{
|
|
SASSERT(m_bUseMask);
|
|
|
|
SStringT strWindowText = GetWindowText();
|
|
|
|
CorrectWindowText();
|
|
GetContainer()->GetCaret()->SetVisible(FALSE);
|
|
|
|
if (strWindowText != m_strWindowText)
|
|
{
|
|
SetWindowText(S_CT2W(m_strWindowText));
|
|
|
|
m_bModified = TRUE;
|
|
}
|
|
|
|
SetSel(m_nStartChar, m_nEndChar, FALSE);
|
|
GetContainer()->GetCaret()->SetVisible(TRUE);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDxDateEdit class
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
SDateEdit::SDateEdit()
|
|
{
|
|
m_bUseMask = true;
|
|
m_strMask = _T("0000/00/00");
|
|
m_strLiteral = _T("____/__/__");
|
|
m_strDefault = _T("0000/00/00");
|
|
}
|
|
|
|
int SDateEdit::OnCreate(LPVOID)
|
|
{
|
|
int nRet = __super::OnCreate(NULL);
|
|
if (nRet != 0)
|
|
return nRet;
|
|
|
|
__time64_t tm=::_time64(NULL);
|
|
|
|
SetDateTime(tm);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void SDateEdit::SetDateTime(LPCTSTR strDate)
|
|
{
|
|
m_strWindowText = m_strDefault = strDate;
|
|
SetWindowText(S_CT2W(strDate));
|
|
}
|
|
|
|
void SDateEdit::SetDateTime(STime tm )
|
|
{
|
|
TCHAR szBuf[256];
|
|
struct tm ttm;
|
|
_tcsftime(szBuf,256,_T("%Y/%m/%d"),tm.GetLocalTm(&ttm));
|
|
SetDateTime(szBuf);
|
|
}
|
|
|
|
SStringT SDateEdit::GetWindowDateTime()
|
|
{
|
|
SStringT strText = GetWindowText();
|
|
return strText;
|
|
}
|
|
|
|
BOOL SDateEdit::ProcessMask(TCHAR& nChar, int nEndPos)
|
|
{
|
|
// check the key against the mask
|
|
if (m_strMask[nEndPos] == _T('0') && _istdigit((TCHAR)nChar))
|
|
{
|
|
// Allow d/m/y and m/d/y
|
|
|
|
if (nEndPos == 0 || nEndPos == 3)
|
|
{
|
|
if (nChar > '3')
|
|
return FALSE;
|
|
}
|
|
if (nEndPos == 1 || nEndPos == 4)
|
|
{
|
|
if (m_strWindowText.GetAt(0) == _T('3'))
|
|
{
|
|
if (nChar > _T('1'))
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CDxTimeEdit class
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
STimeEdit::STimeEdit()
|
|
{
|
|
m_bMilitary = false;
|
|
m_bUseMask = true;
|
|
m_strMask = _T("00:00");
|
|
m_strLiteral = _T("__:__");
|
|
m_strDefault = _T("00:00");
|
|
m_nHours = 0;
|
|
m_nMins = 0;
|
|
}
|
|
|
|
int STimeEdit::OnCreate(LPVOID)
|
|
{
|
|
int nRet = __super::OnCreate(NULL);
|
|
if (nRet != 0)
|
|
return nRet;
|
|
|
|
SetDateTime(STime::GetCurrentTime());
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL STimeEdit::ProcessMask(TCHAR& nChar, int nEndPos)
|
|
{
|
|
// check the key against the mask
|
|
if (m_strMask[nEndPos] == _T('0') && _istdigit(nChar))
|
|
{
|
|
switch (nEndPos)
|
|
{
|
|
case 0:
|
|
if (m_bMilitary)
|
|
{
|
|
if (nChar > _T('2'))
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (nChar > _T('1'))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
|
|
case 1:
|
|
if (m_bMilitary)
|
|
{
|
|
if (m_strWindowText.GetAt(0) == _T('2'))
|
|
{
|
|
if (nChar > _T('3'))
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_strWindowText.GetAt(0) == _T('1'))
|
|
{
|
|
if (nChar > _T('2'))
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
|
|
case 3:
|
|
if (nChar > _T('5'))
|
|
return FALSE;
|
|
return TRUE;
|
|
|
|
case 4:
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void STimeEdit::SetHours(int nHours)
|
|
{
|
|
m_nHours = nHours;
|
|
|
|
SStringW strText;
|
|
strText.Format(L"%02d:%02d", m_nHours, m_nMins);
|
|
SetWindowText(strText);
|
|
}
|
|
|
|
void STimeEdit::SetMins(int nMins)
|
|
{
|
|
m_nMins = nMins;
|
|
|
|
SStringW strText;
|
|
strText.Format(L"%02d:%02d", m_nHours, m_nMins);
|
|
SetWindowText(strText);
|
|
}
|
|
|
|
void STimeEdit::SetTime(int nHours, int nMins)
|
|
{
|
|
m_nHours = nHours;
|
|
m_nMins = nMins;
|
|
|
|
SStringW strText;
|
|
strText.Format(L"%02d:%02d", m_nHours, m_nMins);
|
|
SetWindowText(strText);
|
|
}
|
|
|
|
}//end of namespace SOUI
|
|
|