📄 medit.cpp
字号:
// mEdit.cpp : implementation file
//
#include <afxwin.h>
#include "mEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CmEdit
void AFXAPI DDX_CmEdit(CDataExchange* pDX, int nIDC, CmEdit& rControl, CString& data)
{
DDX_Control(pDX, nIDC, (CWnd&)rControl);
if (!pDX->m_bSaveAndValidate)
{
rControl.SetData(data);
}
else
{
data = rControl.GetData();
}
}
IMPLEMENT_DYNCREATE(CmEdit, CEdit)
CmEdit::CmEdit()
: m_bInit(FALSE)
, m_strPrompt("_")
, m_iNumChars(0)
, m_iCurrentChar(0)
, m_bShiftDown(FALSE)
{
for (int i = 0; i < MAX_CHARS; i++)
m_Char[i] = NULL;
// SubclassWindow(pParent->m_hWnd);
// pParent->SubclassWindow(this->m_hWnd);
}
CmEdit::~CmEdit()
{
for (int i = 0; i < MAX_CHARS; i++)
{
if (m_Char[i] != NULL)
{
delete m_Char[i];
m_Char[i] = NULL;
}
}
}
BEGIN_MESSAGE_MAP(CmEdit, CEdit)
//{{AFX_MSG_MAP(CmEdit)
ON_WM_CHAR()
ON_WM_KEYDOWN()
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SETFOCUS()
ON_WM_LBUTTONUP()
ON_WM_KEYUP()
ON_WM_LBUTTONDBLCLK()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CmEdit message handlers
int CmEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CEdit::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
void CmEdit::OnDestroy()
{
CEdit::OnDestroy();
}
BOOL CmEdit::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= WS_TABSTOP | WS_VISIBLE | WS_DISABLED | ES_AUTOHSCROLL;
cs.dwExStyle |= WS_EX_OVERLAPPEDWINDOW;
return CEdit::PreCreateWindow(cs);
}
void CmEdit::SetData(const CString& data)
{
CString strWindowText;
CString strData;
int iNextDataChar = 0;
for (int i = 1; i <= m_iNumChars; i++)
{
if (m_Char[i - 1]->m_bStaticChar)
{
strWindowText += m_Char[i - 1]->m_strValids;
}
else
{
if (iNextDataChar < data.GetLength())
{
strData = data[iNextDataChar++];
if (m_Char[i - 1]->m_strValids.Find(strData[0]) < 0)
strData = m_strPrompt;
}
else
{
strData = m_strPrompt;
}
strWindowText += strData[0];
}
}
SetWindowText(strWindowText);
}
CString CmEdit::GetData()
{
CString strWindowText;
GetWindowText(strWindowText);
CString strData;
for (int i = 1; i <= m_iNumChars; i++)
{
if (!m_Char[i - 1]->m_bStaticChar)
{
if (strWindowText.GetLength() >= i)
{
if (strWindowText[i - 1] != m_strPrompt)
strData += strWindowText[i - 1];
}
else
strData += m_strPrompt;
}
}
return strData;
}
void CmEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch (nChar)
{
case VK_TAB: // (((CWnd*)GetParent())->GetNextDlgTabItem(this, m_bShiftDown))->SetFocus();
break;
case VK_BACK: if (m_iCurrentChar > 0)
{
int iNewNext = FindNextChar(m_iCurrentChar - 1, FALSE, FALSE);
if (iNewNext >= 0)
{
SetSel(iNewNext, iNewNext + 1);
ReplaceSel(m_strPrompt);
m_iCurrentChar = iNewNext;
SetSel(m_iCurrentChar, m_iCurrentChar);
}
} break;
default: int x, y, z;
GetSel(x,y);
if (x != y)
{
CString szReplaceText = "";
for (z=x; z<y; z++)
{
if (m_Char[z]->m_bStaticChar)
{
szReplaceText += m_Char[z]->m_strValids;
}
else
{
szReplaceText += m_strPrompt;
}
}
ReplaceSel(szReplaceText);
m_iCurrentChar = FindNextChar(x, FALSE, TRUE);
SetSel(m_iCurrentChar, m_iCurrentChar);
}
if (m_iCurrentChar < m_iNumChars)
{
if (m_Char[m_iCurrentChar]->m_strValids.Find((TCHAR)nChar) >= 0)
{
int iNewNext = FindNextChar(m_iCurrentChar + 1, FALSE, TRUE);
SetSel(m_iCurrentChar, m_iCurrentChar + 1);
ReplaceSel((CString)(char)nChar);
if (iNewNext >= 0)
{
m_iCurrentChar = iNewNext;
}
else
{
m_iCurrentChar++;
}
SetSel(m_iCurrentChar, m_iCurrentChar);
}
} break;
}
// CEdit::OnChar(nChar, nRepCnt, nFlags);
}
void CmEdit::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch (nChar)
{
case VK_SHIFT: m_bShiftDown = FALSE; break;
default: break;
}
CEdit::OnKeyUp(nChar, nRepCnt, nFlags);
}
void CmEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
int iNext = 0;
CWnd *pNextItem = NULL;
switch (nChar)
{
case VK_TAB: pNextItem = (((CWnd*)GetParent())->GetNextDlgTabItem(this, (m_bShiftDown) ? TRUE : FALSE));
if (pNextItem->IsKindOf(RUNTIME_CLASS(CmEdit)))
((CmEdit*)pNextItem)->m_bShiftDown = m_bShiftDown;
(((CWnd*)GetParent())->GetNextDlgTabItem(this, (m_bShiftDown) ? TRUE : FALSE))->SetFocus();
break;
case VK_SHIFT: m_bShiftDown = TRUE; break;
case VK_LEFT: iNext = FindNextChar(m_iCurrentChar - 1, FALSE, FALSE);
if (iNext >= 0)
{
m_iCurrentChar = iNext;
SetSel(m_iCurrentChar, m_iCurrentChar);
} break;
case VK_RIGHT: iNext = FindNextChar(m_iCurrentChar + 1, FALSE, TRUE);
if (iNext >= 0)
m_iCurrentChar = iNext;
else
{
m_iCurrentChar = FindNextChar(m_iNumChars - 1, FALSE, FALSE) + 1;
}
SetSel(m_iCurrentChar, m_iCurrentChar);
break;
case VK_HOME: if (m_bShiftDown)
{
SetSel(0, m_iCurrentChar);
}
else
{
m_iCurrentChar = FindNextChar(0, FALSE, TRUE);
SetSel(m_iCurrentChar, m_iCurrentChar);
}
break;
case VK_END: if (m_bShiftDown)
{
int iLast = FindNextChar(m_iNumChars - 1, FALSE, FALSE) + 1;
SetSel(m_iCurrentChar, iLast);
}
else
{
m_iCurrentChar = FindNextChar(m_iNumChars - 1, FALSE, FALSE) + 1;
SetSel(m_iCurrentChar, m_iCurrentChar);
}
break;
case VK_INSERT: break;
case VK_DELETE: int x, y, z;
GetSel(x,y);
if (x != y)
{
CString szReplaceText = "";
for (z = x; z < y; z++)
{
if (m_Char[z]->m_bStaticChar)
{
szReplaceText += m_Char[z]->m_strValids;
}
else
{
szReplaceText += m_strPrompt;
}
}
ReplaceSel(szReplaceText);
m_iCurrentChar = FindNextChar(x, FALSE, TRUE);
SetSel(m_iCurrentChar, m_iCurrentChar);
}
else if (m_iCurrentChar <= FindNextChar(m_iNumChars - 1, FALSE, FALSE))
{
SetSel(m_iCurrentChar, m_iCurrentChar + 1);
ReplaceSel(m_strPrompt);
iNext = FindNextChar(m_iCurrentChar + 1, FALSE, TRUE);
if (iNext >= 0)
m_iCurrentChar = iNext;
else
m_iCurrentChar++;
SetSel(m_iCurrentChar, m_iCurrentChar);
} break;
default: break;
}
// CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
BOOL CmEdit::Init(CString strMask, CString strInitialData)
{
m_bInit = FALSE;
if (!Parse(strMask))
{
SetWindowText("Init failed.");
EnableWindow(FALSE);
return FALSE;
}
if (!SetValidChars(strMask))
{
SetWindowText("SetValidChars failed.");
EnableWindow(FALSE);
return FALSE;
}
SetData(strInitialData);
m_iCurrentChar = FindNextChar(0, FALSE, TRUE);
this->SetFocus();
SetSel(m_iCurrentChar, m_iCurrentChar);
EnableWindow(TRUE); // This line is important !
m_bInit = TRUE;
return TRUE;
}
int CmEdit::FindNextChar(int iStartPos, BOOL bStatic, BOOL bForward)
{
int iIndex = 0;
int iReturnVal = -1;
if (bForward)
{
for (int iIndex = iStartPos; iIndex < m_iNumChars; iIndex++)
{
if (m_Char[iIndex]->m_bStaticChar == bStatic)
{
iReturnVal = iIndex;
break;
}
}
}
else
{
for (int iIndex = iStartPos; iIndex >= 0; iIndex--)
{
if (m_Char[iIndex]->m_bStaticChar == bStatic)
{
iReturnVal = iIndex;
break;
}
}
}
return iReturnVal;
}
BOOL CmEdit::SetValidChars(const CString& strMask)
{
CString strChars;
CString strRangeLow;
BOOL bInside = FALSE;
BOOL bInsideEscape = FALSE;
BOOL bInsideRange = FALSE;
int iNextChar = 0;
int i;
/*
Clear valid chars.
*/
for (i = 0; i < MAX_CHARS; i++)
{
if (m_Char[i] != NULL)
{
delete m_Char[i];
m_Char[i] = NULL;
}
}
/*
Walk through mask string.
*/
for (i = 0; i < strMask.GetLength(); i++)
{
switch (strMask[i])
{
case '[': bInside = TRUE; // Done.
break;
case ']': bInside = FALSE;
m_Char[iNextChar++] = new CmEditChar(strChars, FALSE);
strChars = "";
break;
case '-': if (bInside)
{
if (bInsideEscape)
{
strChars += "-";
bInsideEscape = FALSE; // Done.
}
else
{
if (strChars.GetLength() == 0)
return FALSE;
bInsideRange = TRUE;
strRangeLow = strChars.Right(1);
strChars = strChars.Left(strChars.GetLength() - 1); //done
}
}
else
{
m_Char[iNextChar++] = new CmEditChar("-", TRUE); //done
}
break;
case '\\': if (bInside)
{
if (!bInsideEscape)
{
bInsideEscape = TRUE; // Done.
}
else
{
if (bInsideRange)
{
strChars += GetRange(strRangeLow, "\\");
strRangeLow = "";
bInsideRange = FALSE; // Done.
}
else
{
strChars += "\\";
bInsideEscape = FALSE; // Done.
}
}
}
else
{
m_Char[iNextChar++] = new CmEditChar("\\", TRUE); //done
}
break;
default: if (bInside)
{
if (bInsideEscape)
{
bInsideEscape = FALSE; // Done.
}
if (bInsideRange)
{
strChars += GetRange(strRangeLow, strMask[i]);
strRangeLow = "";
bInsideRange = FALSE; // Done.
}
else
{
strChars += strMask[i]; // Done.
}
}
else
{
m_Char[iNextChar++] = new CmEditChar(strMask[i], TRUE); //done
}
break;
}
}
m_iNumChars = iNextChar;
SetLimitText(m_iNumChars);
return TRUE;
}
CString CmEdit::GetRange(CString szLow, CString szHigh)
{
CString szReturn = "";
if (szLow.GetLength() == 1 && szHigh.GetLength() == 1)
{
char first = szLow[0];
char last = szHigh[0];
for (int i = first; i <= last; i++)
szReturn += (CString)(char)i;
}
return szReturn;
}
BOOL CmEdit::Parse(const CString& strMask)
{
BOOL bValid = TRUE;
int iBracketState = 0;
// int iDashState = 0;
for (int i = 1; i <= strMask.GetLength(); i++)
{
switch (strMask[i - 1])
{
case '[': iBracketState++; break;
case ']': iBracketState--; break;
// case '-': if (iBracketState > 0)
// iDashState = 1;
// break;
default: // if (iBracketState > 0) && iDashState == 1)
// iDashState = 0;
break;
}
/*
Make sure the [ ] are in sync.
*/
if (iBracketState < 0 || iBracketState > 1)
bValid = FALSE;
/*
Make sure there is a character after a '-' inside the [ ]
// if (iBracketState == 0 && iDashState == 1)
// bValid = FALSE;
*/
}
return (iBracketState == 0 /*&& iDashState == 0*/ && bValid) ? TRUE : FALSE;
}
BOOL CmEdit::SetPromptChar(CString strPromptChar)
{
if (strPromptChar.GetLength() != 1)
return FALSE;
m_strPrompt = strPromptChar;
return TRUE;
}
void CmEdit::OnSetFocus(CWnd* pOldWnd)
{
CEdit::OnSetFocus(pOldWnd);
// SetSel(m_iCurrentChar, m_iCurrentChar);
SetSel(0, -1);
}
void CmEdit::OnLButtonUp(UINT nFlags, CPoint point)
{
int x, y;
GetSel(x, y);
if (x == y)
{
m_iCurrentChar = x;
SetSel(m_iCurrentChar, m_iCurrentChar);
}
CEdit::OnLButtonUp(nFlags, point);
}
void CmEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
{
SetSel(0, -1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -