⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 amsedit.cpp

📁 用户管理系统
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	if (nDecimalPos >= 0)
		strNewText = strNewText.Left(nDecimalPos);

	if (m_nDigitsInGroup > 0)
	{
		int nLen = strNewText.GetLength();
		BOOL bIsNegative = (!strNewText.IsEmpty() && strNewText[0] == m_cNegativeSign);

		// Loop in reverse and stick the separator every m_nDigitsInGroup digits.
		for (int iPos = nLen - (m_nDigitsInGroup + 1); iPos >= bIsNegative; iPos -= m_nDigitsInGroup)
			strNewText = strNewText.Left(iPos + 1) + m_cGroupSeparator + strNewText.Mid(iPos + 1);
	}

	// Prepend the prefix, if the number is not empty.
	if (!strNewText.IsEmpty() || nDecimalPos >= 0)
	{
		strNewText = m_strPrefix + strNewText;

		if (nDecimalPos >= 0)
			strNewText += strNumericText.Mid(nDecimalPos);
	}

	return strNewText;
}

CString CAMSEdit::NumericBehavior::_GetValidText() const
{
	CString strText = m_pEdit->GetText();
	CString strNewText;
	BOOL bIsNegative = FALSE;
	int nPrefixLen = m_strPrefix.GetLength();

	// Remove any invalid characters from the number
	for (int iPos = 0, nDecimalPos = -1, nNewLen = 0, nLen = strText.GetLength(); 
	     iPos < nLen; iPos++)
	{
		TCHAR c = strText[iPos];

		// Check for a negative sign
		if (iPos == nPrefixLen && c == m_cNegativeSign && m_bAllowNegative)
		{
			strNewText += c;
			nNewLen++;
			bIsNegative = TRUE;
		}
		// Check for a digit
		else if (_istdigit(c))
		{
			// Make sure it doesn't go beyond the limits
			if (nDecimalPos < 0 && nNewLen == m_nMaxWholeDigits + bIsNegative)
				continue;

			if (nDecimalPos >= 0 && nNewLen > nDecimalPos + m_nMaxDecimalPlaces)
				break;

			strNewText += c;
			nNewLen++;
		}
		// Check for a decimal point
		else if (c == m_cDecimalPoint && nDecimalPos < 0)
		{
			if (m_nMaxDecimalPlaces == 0)
				break;

			strNewText += c;
			nDecimalPos = nNewLen;
			nNewLen++;
		}
	}

	return GetSeparatedText(strNewText);
}

void CAMSEdit::NumericBehavior::_OnChar(UINT uChar, UINT nRepCnt, UINT nFlags)
{
	TCHAR c = (TCHAR)uChar;

	int nStart, nEnd;
	m_pEdit->GetSel(nStart, nEnd);

	CString strText = m_pEdit->GetText();
	CString strNumericText = GetNumericText(strText);
	int nDecimalPos = strText.Find(m_cDecimalPoint);
	int nNumericDecimalPos = strNumericText.Find(m_cDecimalPoint);
	int nLen = strText.GetLength();
	int nNumericLen = strNumericText.GetLength();
	int nPrefixLen = m_strPrefix.GetLength();
	int nSepCount = GetGroupSeparatorCount(strText);
	bool bNeedAdjustment = false;

	// Check if we're in the prefix's location
	if (nStart < nPrefixLen && c != VK_BACK)
	{
		TCHAR cPrefix = m_strPrefix[nStart];

		// Check if it's the same character as the prefix.
		if (cPrefix == c && _ShouldEnter(c))
		{
			if (nLen > nStart)
			{
				m_pEdit->SetSel(nStart, nStart + 1);
				m_pEdit->ReplaceSel(CString(c), TRUE);
			}
			else
				Behavior::_OnChar(uChar, nRepCnt, nFlags);
		}
		// If it's a part of the number, enter the prefix
		else if ((_istdigit(c) || c == m_cNegativeSign || c == m_cDecimalPoint) && _ShouldEnter(c))
		{
			m_pEdit->SetSel(nStart, nPrefixLen);
			m_pEdit->ReplaceSel(m_strPrefix.Mid(nStart), TRUE);

			Behavior::_OnChar(uChar, nRepCnt, nFlags);
		}
		
		return;
	}

	// Check if it's a negative sign
	if (c == m_cNegativeSign && m_bAllowNegative)
	{
		// If it's at the beginning, determine if it should overwritten
		if (nStart == nPrefixLen)
		{
			if (!strNumericText.IsEmpty() && strNumericText[0] == m_cNegativeSign && _ShouldEnter(c))
			{
				m_pEdit->SetSel(nStart, nStart + 1);
				m_pEdit->ReplaceSel(CString(m_cNegativeSign), TRUE);
				return;
			}
		}
		// If we're not at the beginning, toggle the sign
		else if (_ShouldEnter(c))
		{
			if (strNumericText[0] == m_cNegativeSign)
			{
				m_pEdit->SetSel(nPrefixLen, nPrefixLen + 1);
				m_pEdit->ReplaceSel(_T(""), TRUE);
				m_pEdit->SetSel(nStart - 1, nEnd - 1);
			}
			else
			{
				m_pEdit->SetSel(nPrefixLen, nPrefixLen);
				m_pEdit->ReplaceSel(CString(m_cNegativeSign), TRUE);
				m_pEdit->SetSel(nStart + 1, nEnd + 1);
			}

			return;
		}
	}

	// Check if it's a decimal point (only one is allowed).
	else if (c == m_cDecimalPoint && m_nMaxDecimalPlaces > 0)
	{
		if (nDecimalPos >= 0)
		{
			if (_ShouldEnter(c))
				 m_pEdit->SetSel(nDecimalPos + 1, nDecimalPos + 1);
			return;
		}
	}

	// Check if it's a digit
	else if (_istdigit(c))
	{
		// Check if we're on the right of the decimal point.
		if (nDecimalPos >= 0 && nDecimalPos < nStart)
		{
			if (strNumericText.Mid(nNumericDecimalPos + 1).GetLength() == m_nMaxDecimalPlaces)
			{
				if (nStart <= nDecimalPos + m_nMaxDecimalPlaces && _ShouldEnter(c))
				{
					m_pEdit->SetSel(nStart, nStart + 1);
					m_pEdit->ReplaceSel(CString(c), TRUE);
				}
				return;
			}
		}

		// We're on the left side of the decimal point
		else 
		{
			BOOL bIsNegative = (!strNumericText.IsEmpty() && strNumericText[0] == m_cNegativeSign);

			// Make sure we can still enter digits.
			if (nStart == m_nMaxWholeDigits + bIsNegative + nSepCount + nPrefixLen)
				return;

			if (strNumericText.Mid(0, nNumericDecimalPos >= 0 ? nNumericDecimalPos : nNumericLen).GetLength() == m_nMaxWholeDigits + bIsNegative)
			{
				if (_ShouldEnter(c))
				{
					if (strText[nStart] == m_cGroupSeparator)
						nStart++;

					m_pEdit->SetSel(nStart, nStart + 1);
					m_pEdit->ReplaceSel(CString(c), TRUE);
				}
				return;
			}

			bNeedAdjustment = true;
		}
	}

	// Check if it's a non-printable character, such as Backspace or Ctrl+C
	else if (!_istprint(c))
		bNeedAdjustment = true;
	else
		return;

	// Check if the character should be entered
	if (!_ShouldEnter(c))
		return;
	
	Behavior::_OnChar(uChar, nRepCnt, nFlags);

	// If the decimal point was added/removed or a separator needs adding/removing, adjust the text
	if (bNeedAdjustment || nNumericDecimalPos != GetNumericText(m_pEdit->GetText()).Find(m_cDecimalPoint))
		AdjustSeparators(nSepCount);
}

void CAMSEdit::NumericBehavior::_OnKeyDown(UINT uChar, UINT nRepCnt, UINT nFlags) 
{
	switch (uChar)
	{
		case VK_DELETE:
		{
			int nStart, nEnd;
			m_pEdit->GetSel(nStart, nEnd);

			CString strText = m_pEdit->GetText();
			int nLen = strText.GetLength();

			// If deleting the prefix, don't allow it if there's a number after it.
			int nPrefixLen = m_strPrefix.GetLength();
			if (nStart < nPrefixLen && nLen > nPrefixLen)
			{
				if (nEnd == nLen)
					break;
				return;
			}

			// Allow the deletion and then adjust the value
			int nSepCount = GetGroupSeparatorCount(strText);
			Behavior::_OnKeyDown(uChar, nRepCnt, nFlags);

			AdjustSeparators(nSepCount);

			// If everything on the right was deleted, put the selection on the right
			if (nEnd == nLen)
				m_pEdit->SetSel(nStart, nStart);

			return;
		}
	}

	Behavior::_OnKeyDown(uChar, nRepCnt, nFlags);
}


/////////////////////////////////////////////////////////////////////////////
// CAMSEdit::DateBehavior

#define AMS_MIN_CTIME			CTime(1970, 1, 1, 0, 0, 0)
#define AMS_MAX_CTIME			CTime(2037, 12, 31, 23, 59, 59)
#define AMS_MIN_OLEDATETIME		COleDateTime(1900, 1, 1, 0, 0, 0)
#define AMS_MAX_OLEDATETIME		COleDateTime(9999, 12, 31, 23, 59, 59)
#define AMS_DATE_SEP			'/'
#define AMS_DATE_SEP_STR		_T("/")


CAMSEdit::DateBehavior::DateBehavior(CAMSEdit* pEdit) :
	Behavior(pEdit),
	m_dateCurrent(COleDateTime::GetCurrentTime()),
	m_dateMin(AMS_MIN_OLEDATETIME),
	m_dateMax(AMS_MAX_OLEDATETIME),
	m_cSep(AMS_DATE_SEP),
	m_uFlags(None)
{
	// Get the system's date separator
	if (::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, &m_cSep, 0))
		::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, &m_cSep, sizeof(m_cSep));

	// Determine if the day should go before the month
	TCHAR szShortDate[MAX_PATH];
	if (::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, szShortDate, 0))
	{
		::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, szShortDate, sizeof(szShortDate));

		for (int iPos = 0; szShortDate[iPos]; iPos++)
		{
			TCHAR c = _totupper(szShortDate[iPos]);
			if (c == 'M')	// see if the month is first
				break;
			if (c == 'D')	// see if the day is first, and then set the flag
			{
				m_uFlags |= DayBeforeMonth;
				break;
			}
		}
	}
 m_uFlags |= DayBeforeMonth; //设置DD-MM-YYYY
}

void CAMSEdit::DateBehavior::_OnChar(UINT uChar, UINT nRepCnt, UINT nFlags) 
{
	TCHAR c = (TCHAR)uChar;
	int nDigit = _ttoi(CString(c));

	int nStart, nEnd;
	m_pEdit->GetSel(nStart, nEnd);

	CString strText = m_pEdit->GetText();
	int nLen = strText.GetLength();

	// Check for a non-printable character (such as Ctrl+C)
	if (!_istprint(c))
	{
		if (c == VK_BACK && nStart != nLen)
		{
			m_pEdit->SendMessage(WM_KEYDOWN, VK_LEFT); // move the cursor left
			return;
		}
		
		// Allow backspace only if the cursor is all the way to the right
		if (_ShouldEnter(c))
			Behavior::_OnChar(uChar, nRepCnt, nFlags);
		return;
	}

	// Add the digit depending on its location
	switch (nStart)
	{
		case 0:		// FIRST DIGIT
		{
			if (m_uFlags & DayBeforeMonth)
			{
				if (IsValidDayDigit(c, 0) && _ShouldEnter(c))
				{
					if (nLen > nStart)
					{
						m_pEdit->SetSel(nStart, nStart + 1);
						m_pEdit->ReplaceSel(CString(c), TRUE);

						if (nLen > nStart + 1)
						{
							if (!IsValidDay(GetDay()))
							{
								m_pEdit->SetSel(nStart + 1, nStart + 2);
								m_pEdit->ReplaceSel(CString(GetMinDayDigit(1)), TRUE);
								m_pEdit->SetSel(nStart + 1, nStart + 2);
							}
						}
					}
					else
						Behavior::_OnChar(uChar, nRepCnt, nFlags);
				}
			}
			else
			{
				if (IsValidMonthDigit(c, 0) && _ShouldEnter(c))
				{
					if (nLen > nStart)
					{
						m_pEdit->SetSel(nStart, nStart + 1);
						m_pEdit->ReplaceSel(CString(c), TRUE);

						if (nLen > nStart + 1)
						{
							if (!IsValidMonth(GetMonth()))
							{
								m_pEdit->SetSel(nStart + 1, nStart + 2);
								m_pEdit->ReplaceSel(CString(GetMinMonthDigit(1)), TRUE);
								m_pEdit->SetSel(nStart + 1, nStart + 2);
							}
						}
						AdjustMaxDay();
					}
					else
						Behavior::_OnChar(uChar, nRepCnt, nFlags);
				}
			}
			break;
		}
		case 1:		// SECOND DIGIT
		{
			if (m_uFlags & DayBeforeMonth)
			{
				if (IsValidDayDigit(c, 1) && _ShouldEnter(c))
				{
					if (nLen > nStart)
					{
						m_pEdit->SetSel(nStart, nStart + 1);
						m_pEdit->ReplaceSel(CString(c), TRUE);
					}
					else
						Behavior::_OnChar(uChar, nRepCnt, nFlags);
				}
			}
			else
			{
				if (IsValidMonthDigit(c, 1) && _ShouldEnter(c))
				{
					if (nLen > nStart)
					{
						m_pEdit->SetSel(nStart, nStart + 1);
						m_pEdit->ReplaceSel(CString(c), TRUE);

						if (GetDay() > 0 && AdjustMaxDay())
							m_pEdit->SetSel(GetDayStartPosition(), GetDayStartPosition() + 2);
					}
					else
						Behavior::_OnChar(uChar, nRepCnt, nFlags);
				}
			}
			break;
		}
		
		case 2:		// FIRST SLASH
		{
			int nSlash = 0;
			if (c == m_cSep)
				nSlash = 1;
			else
			{
				if (m_uFlags & DayBeforeMonth)
					nSlash = (IsValidMonthDigit(c, 0) ? 2 : 0);
				else
					nSlash = (IsValidDayDigit(c, 0) ? 2 : 0);
			}

			// If we need the slash, enter it
			if (nSlash && _ShouldEnter(c))
			{
				m_pEdit->SetSel(nStart, nStart + 1, FALSE);
				m_pEdit->ReplaceSel(CString(m_cSep), TRUE);
			}

			// If the slash is to be preceded by a valid digit, "type" it in.
			if (nSlash == 2)
				keybd_event((BYTE)c, 0, 0, 0);
			break;
		}

		case 3:		// THIRD DIGIT
		{
			if (m_uFlags & DayBeforeMonth)
			{
				if (IsValidMonthDigit(c, 0) && _ShouldEnter(c))
				{
					if (nLen > nStart)
					{
						m_pEdit->SetSel(nStart, nStart + 1);
						m_pEdit->ReplaceSel(CString(c), TRUE);

						if (nLen > nStart + 1)
						{
							if (!IsValidMonth(GetMonth()))
							{
								m_pEdit->SetSel(nStart + 1, nStart + 2);
								m_pEdit->ReplaceSel(CString(GetMinMonthDigit(1)), TRUE);
								m_pEdit->SetSel(nStart + 1, nStart + 2);
							}
						}
						AdjustMaxDay();
					}
					else
						Behavior::_OnChar(uChar, nRepCnt, nFlags);
				}
			}
			else
			{
				if (IsValidDayDigit(c, 0) && _ShouldEnter(c))
				{
					if (nLen > nStart)
					{
						m_pEdit->SetSel(nStart, nStart + 1);
						m_pEdit->ReplaceSel(CString(c), TRUE);

						if (nLen > nStart + 1)
						{
							if (!IsValidDay(GetDay()))
							{
								m_pEdit->SetSel(nStart + 1, nStart + 2);
								m_pEdit->ReplaceSel(CString(GetMinDayDigit(1)), TRUE);
								m_pEdit->SetSel(nStart + 1, nStart + 2);
							}
						}
					}
					else
						Behavior::_OnChar(uChar, nRepCnt, nFlags);
				}
			}
			break;			
		}

		case 4:		// FOURTH DIGIT
		{
			if (m_uFlags & DayBeforeMonth)
			{
				if (IsValidMonthDigit(c, 1) && _ShouldEnter(c))
				{
					if (nLen > nStart)
					{
						m_pEdit->SetSel(nStart, nStart + 1);
						m_pEdit->ReplaceSel(CString(c), TRUE);

						if (GetDay() > 0 && AdjustMaxDay())
							m_pEdit->SetSel(GetDayStartPosition(), GetDayStartPosition() + 2);
					}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -