📄 bcgpmaskedit.cpp
字号:
// BCGPMaskEdit.cpp : implementation file
//
#include "stdafx.h"
#include "bcgcbpro.h"
#include "BCGPMaskEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CBCGPMaskEdit
IMPLEMENT_DYNAMIC(CBCGPMaskEdit, CEdit)
BEGIN_MESSAGE_MAP(CBCGPMaskEdit, CEdit)
//{{AFX_MSG_MAP(CBCGPMaskEdit)
ON_WM_CHAR()
ON_WM_KEYDOWN()
ON_WM_LBUTTONUP()
ON_WM_CREATE()
ON_CONTROL_REFLECT_EX(EN_UPDATE, OnUpdateR)
ON_CONTROL_REFLECT(EN_SETFOCUS, OnSetFocus)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CBCGPMaskEdit::CBCGPMaskEdit()
{
m_bGetMaskedCharsOnly = TRUE;
m_bSetMaskedCharsOnly = FALSE;
m_bSelectByGroup = TRUE;
m_bMaskKeyInProgress = FALSE;
}
CBCGPMaskEdit::~CBCGPMaskEdit()
{
}
void CBCGPMaskEdit::EnableMask(LPCTSTR lpszMask, LPCTSTR lpszInputTemplate,
TCHAR chMaskInputTemplate, LPCTSTR lpszValid)
{
ASSERT(lpszMask != NULL);
ASSERT(lpszInputTemplate != NULL);
ASSERT(_istprint(chMaskInputTemplate));
m_strMask = lpszMask;
m_strInputTemplate = lpszInputTemplate;
m_chMaskInputTemplate = chMaskInputTemplate;
m_str = lpszInputTemplate;
ASSERT(m_strMask.GetLength() == m_strInputTemplate.GetLength());
if (lpszValid != NULL)
{
m_strValid = lpszValid;
}
else
{
m_strValid.Empty();
}
}
void CBCGPMaskEdit::DisableMask()
{
m_strMask.Empty();
m_strInputTemplate.Empty();
}
void CBCGPMaskEdit::SetValidChars(LPCTSTR lpszValid)
{
if (lpszValid != NULL)
{
m_strValid = lpszValid;
}
else
{
m_strValid.Empty();
}
}
BOOL CBCGPMaskEdit::IsMaskedChar(TCHAR chChar, TCHAR chMaskChar) const
{
// ------------------------------
// Check the key against the mask
// ------------------------------
switch (chMaskChar)
{
case _T('D'): // digit only
if (_istdigit(chChar))
{
return TRUE;
}
break;
case _T('d'): // digit or space
if (_istdigit(chChar))
{
return TRUE;
}
if (_istspace(chChar))
{
return TRUE;
}
break;
case _T('+'): // '+' or '-' or space
if (chChar == _T('+') || chChar == _T('-'))
{
return TRUE;
}
if (_istspace(chChar))
{
return TRUE;
}
break;
case _T('C'): // alpha only
if (_istalpha(chChar))
{
return TRUE;
}
break;
case _T('c'): // alpha or space
if (_istalpha(chChar))
{
return TRUE;
}
if (_istspace(chChar))
{
return TRUE;
}
break;
case _T('A'): // alpha numeric only
if (_istalnum(chChar))
{
return TRUE;
}
break;
case _T('a'): // alpha numeric or space
if (_istalnum(chChar))
{
return TRUE;
}
if (_istspace(chChar))
{
return TRUE;
}
break;
}
return FALSE; // not allowed symbol
}
BOOL CBCGPMaskEdit::SetValue(LPCTSTR lpszString, BOOL bWithDelimiters)
{
ASSERT(m_strMask.IsEmpty() == m_strInputTemplate.IsEmpty());
ASSERT(m_strMask.GetLength() == m_strInputTemplate.GetLength());
ASSERT(lpszString != NULL);
// ------------------------------------------------
// Make sure the string is not longer than the mask
// ------------------------------------------------
CString strSource = lpszString;
if (!m_strMask.IsEmpty())
{
if (bWithDelimiters)
{
if (strSource.GetLength() > m_strMask.GetLength())
{
return FALSE;
}
}
else
{
// Count _T('_') in m_strInputTemplate
int nCount = 0;
for (int i = 0; i < m_strInputTemplate.GetLength(); i++)
{
if (m_strInputTemplate[i] == _T('_'))
{
nCount++;
}
}
if (strSource.GetLength() > nCount)
{
return FALSE;
}
}
}
// ----------------------------------------------------
// Make sure the value has only valid string characters
// ----------------------------------------------------
if (!m_strValid.IsEmpty())
{
BOOL bOk = TRUE;
for (int iPos = 0; bOk && iPos < strSource.GetLength(); iPos++)
{
if (m_strInputTemplate.IsEmpty () || m_strInputTemplate[iPos] == _T('_'))
{
if (m_strInputTemplate.IsEmpty () ||
strSource[iPos] != m_chMaskInputTemplate) // allow m_chMaskInputTemplate
{
bOk = (m_strValid.Find (strSource[iPos]) != -1);
}
}
}
if (!bOk)
{
return FALSE;
}
}
// -----------------------------------
// Use mask, validate against the mask
// -----------------------------------
if (!m_strMask.IsEmpty())
{
ASSERT(m_str.GetLength() == m_strMask.GetLength());
CString strResult = m_strInputTemplate;
// Replace '_' with default char
for (int i=0; i<strResult.GetLength(); i++)
{
if (m_strInputTemplate[i] == _T('_'))
{
strResult.SetAt(i, m_chMaskInputTemplate);
}
}
int iSrcChar = 0;
int iDstChar = 0;
while ((iSrcChar<strSource.GetLength()) &&
(iDstChar<m_strInputTemplate.GetLength()))
{
// iDstChar - character entry position ("_" char)
if (m_strInputTemplate[iDstChar] == _T('_'))
{
TCHAR chChar = strSource[iSrcChar];
if (chChar != m_chMaskInputTemplate) // allow m_chMaskInputTemplate
{
if (!IsMaskedChar(chChar, m_strMask[iDstChar]))
{
return FALSE;
}
}
strResult.SetAt(iDstChar, chChar);
iSrcChar++;
iDstChar++;
}
// iDstChar - delimeter
else
{
if (bWithDelimiters)
{
if (m_strInputTemplate[iDstChar] != strSource[iSrcChar])
{
return FALSE;
}
iSrcChar++;
iDstChar++;
}
else
{
iDstChar++;
}
}
}
m_str = strResult;
}
// --------------
// Don't use mask
// --------------
else
{
m_str = strSource;
}
return TRUE;
}
const CString CBCGPMaskEdit::GetMaskedValue(BOOL bWithSpaces) const
{
ASSERT(m_strMask.IsEmpty() == m_strInputTemplate.IsEmpty());
ASSERT(m_strMask.GetLength() == m_strInputTemplate.GetLength());
// --------------
// Don't use mask
// --------------
if (m_strMask.IsEmpty())
{
return m_str;
}
// --------
// Use mask
// --------
ASSERT(m_str.GetLength() == m_strMask.GetLength());
CString strResult;
for (int iChar=0; iChar < m_strInputTemplate.GetLength(); iChar++)
{
if (m_strInputTemplate[iChar] == _T('_'))
{
TCHAR ch = m_str[iChar];
if (ch == m_chMaskInputTemplate)
{
if (bWithSpaces)
{
strResult += ch;
}
}
else
{
ASSERT((!m_strValid.IsEmpty()) ? (m_strValid.Find(ch) != -1) : TRUE);
ASSERT(IsMaskedChar(ch, m_strMask[iChar]));
strResult += ch;
}
}
}
return strResult;
}
///////////////////////////////////
// Replace standard CWnd operations
void CBCGPMaskEdit::SetWindowText(LPCTSTR lpszString)
{
SetValue(lpszString, !m_bSetMaskedCharsOnly);
CWnd::SetWindowText(m_str);
}
int CBCGPMaskEdit::GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const
{
ASSERT(lpszStringBuf != NULL);
// Receive text
CString strText;
CWnd::GetWindowText(strText);
// Copy text
int nCount = min(nMaxCount, strText.GetLength());
LPCTSTR lpcszTmp = strText;
CopyMemory(lpszStringBuf, lpcszTmp, nCount*sizeof(TCHAR));
// Add terminating null character if possible
if (nMaxCount > nCount)
{
lpszStringBuf[nCount] = _T('\0');
}
return nCount*sizeof(TCHAR);
}
void CBCGPMaskEdit::GetWindowText(CString& strString) const
{
if (m_bGetMaskedCharsOnly)
{
strString = GetMaskedValue();
}
else
{
strString = GetValue();
}
}
///////////////////////////////////
// Handlers
int CBCGPMaskEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CEdit::OnCreate(lpCreateStruct) == -1)
return -1;
CWnd::SetWindowText(m_str);
return 0;
}
void CBCGPMaskEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// --------------------------------------
// Make sure the mask has entry positions
// --------------------------------------
int nGroupStart, nGroupEnd;
GetGroupBounds(nGroupStart, nGroupEnd);
if (nGroupStart == -1)
{
// mask has no entry positions
MessageBeep((UINT)-1);
return;
}
switch (nChar)
{
case VK_END:
{
// ----------------------
// Calc last group bounds
// ----------------------
int nGroupStart, nGroupEnd;
CEdit::GetSel(nGroupStart, nGroupEnd);
ASSERT(nGroupStart != -1);
GetGroupBounds(nGroupStart, nGroupEnd, nGroupEnd, TRUE);
if (nGroupStart == -1)
{
GetGroupBounds(nGroupStart, nGroupEnd, m_str.GetLength(), FALSE);
}
ASSERT(nGroupStart != -1);
CEdit::SetSel(nGroupEnd, nGroupEnd);
return;
}
case VK_HOME:
{
// -----------------------
// Calc first group bounds
// -----------------------
int nGroupStart, nGroupEnd;
CEdit::GetSel(nGroupStart, nGroupEnd);
ASSERT(nGroupStart != -1);
GetGroupBounds(nGroupStart, nGroupEnd, nGroupStart, FALSE);
if (nGroupStart == -1)
{
GetGroupBounds(nGroupStart, nGroupEnd, 0, TRUE);
}
ASSERT(nGroupStart != -1);
CEdit::SetSel(nGroupStart, nGroupStart);
return;
}
case VK_UP:
case VK_LEFT:
{
// -----------------------
// Calc first group bounds
// -----------------------
int nGroupStart, nGroupEnd;
CEdit::GetSel(nGroupStart, nGroupEnd);
ASSERT(nGroupStart != -1);
GetGroupBounds(nGroupStart, nGroupEnd, nGroupStart, FALSE);
if (nGroupStart == -1)
{
GetGroupBounds(nGroupStart, nGroupEnd, 0, TRUE);
}
ASSERT(nGroupStart != -1);
if (::GetKeyState(VK_SHIFT)&0x80)
{
int nStart, nEnd;
CEdit::GetSel(nStart, nEnd);
if (m_bSelectByGroup)
{
int nNewStart = max(nStart-1, nGroupStart);
// additional
nNewStart = min(nNewStart, nGroupEnd);
CEdit::SetSel(nNewStart, nEnd);
}
else
{
CEdit::SetSel(nStart-1, nEnd);
}
return;
}
else if (::GetKeyState(VK_CONTROL)&0x80)
{
// move to the previous group
int nStart, nEnd;
CEdit::GetSel(nStart, nEnd);
ASSERT(nStart != -1);
if (nStart > 1) // can search previous group
{
GetGroupBounds(nGroupStart, nGroupEnd, nStart-1, FALSE);
}
if ((nGroupStart != -1) && // if previous group was found
(nGroupStart != nStart || nGroupEnd != nEnd)) // and it's not the same
{
CEdit::SetSel(nGroupStart, nGroupEnd);
}
else // no more groups
{
MessageBeep((UINT)-1);
}
return;
}
else
{
int nStart, nEnd;
CEdit::GetSel(nStart, nEnd);
// move to the previous group
if ((nStart==nEnd) && (nStart==nGroupStart))
{
if (nStart > 1) // can search previous group
{
GetGroupBounds(nGroupStart, nGroupEnd, nStart-1, FALSE);
}
if ((nGroupStart != -1) && (nGroupEnd < nStart)) // if previous group was found
{
CEdit::SetSel(nGroupEnd, nGroupEnd);
}
else // no more groups
{
MessageBeep((UINT)-1);
}
}
else
{
int nNewStart = max(nStart-1, nGroupStart);
// additional
nNewStart = min(nNewStart, nGroupEnd);
CEdit::SetSel(nNewStart, nNewStart);
}
return;
}
}
case VK_DOWN:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -