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

📄 amsedit.cpp

📁 一款密码保险箱源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			{
				if (_ShouldEnter(c))
				{
					if (strText[nStart] == m_cGroupSeparator)
						nStart++;

					nEnd = (nEnd == nLen ? nEnd : (nStart + 1));
					m_pEdit->SetSel(nStart, nEnd);
					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)
		AdjustSeparators(nSepCount);
}

// Handles the WM_KEYDOWN message, which is called when the user enters a special character such as Delete or the arrow keys.
void CAMSEdit::NumericBehavior::_OnKeyDown(UINT uChar, UINT nRepCnt, UINT nFlags)
{
	switch (uChar)
	{
		case VK_DELETE:
		{
			int nStart = 0, nEnd = 0;
			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;
			}

			if (nStart < nLen && strText[nStart] == m_cGroupSeparator && nStart == nEnd)
				Behavior::_OnKeyDown(VK_RIGHT, nRepCnt, nFlags);

			// 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);
}

// Handles the WM_KILLFOCUS message, which is called when the user leaves the control.
// It's used here to check if zeros need to be added to the value.
void CAMSEdit::NumericBehavior::_OnKillFocus(CWnd* pNewWnd)
{
	Behavior::_OnKillFocus(pNewWnd);

	// Check if the value is empty and we don't want to touch it
	CString strOriginalText = GetNumericText(m_pEdit->GetText());
	CString strText = strOriginalText;
	int nLen = strText.GetLength();

	// If desired, remove any extra leading zeros but always leave one in front of the decimal point
	if (m_uFlags & OnKillFocus_RemoveExtraLeadingZeros && nLen > 0)
	{
		bool bIsNegative = (strText[0] == m_cNegativeSign);
		if (bIsNegative)
			strText.Delete(0);
		strText.TrimLeft('0');
		if (strText.IsEmpty() || strText[0] == m_cDecimalPoint)
			strText.Insert(0, '0');
		if (bIsNegative)
			strText.Insert(0, m_cNegativeSign);
	}
	else if (!(m_uFlags & OnKillFocus_Max) || (nLen == 0 && m_uFlags & OnKillFocus_DontPadWithZerosIfEmpty))
		return;

	int nDecimalPos = strText.Find(m_cDecimalPoint);

	// Check if we need to pad the number with zeros after the decimal point
	if (m_uFlags & OnKillFocus_PadWithZerosAfterDecimal && m_nMaxDecimalPlaces > 0)
	{
		if (nDecimalPos < 0)
		{
			if (nLen == 0 || strText == '-')
			{
				strText = '0';
				nLen = 1;
			}
			strText += m_cDecimalPoint;
			nDecimalPos = nLen++;
		}

		InsertZeros(&strText, -1, m_nMaxDecimalPlaces - (nLen - nDecimalPos - 1));
	}

	// Check if we need to pad the number with zeros before the decimal point
	if (m_uFlags & OnKillFocus_PadWithZerosBeforeDecimal && m_nMaxWholeDigits > 0)
	{
		if (nDecimalPos < 0)
			nDecimalPos = nLen;

		if (nLen && strText[0] == '-')
			nDecimalPos--;

		InsertZeros(&strText, (nLen ? strText[0] == '-' : -1), m_nMaxWholeDigits - nDecimalPos);
	}

	if (strText != strOriginalText)
	{
		SelectionSaver selection = m_pEdit;	// remember the current selection
		m_pEdit->SetWindowText(strText);
	}

	// If it's empty, take action based on the flag
	if (strText.IsEmpty())
	{
		if (m_uFlags & OnKillFocus_Beep_IfEmpty)
			MessageBeep(MB_ICONEXCLAMATION);

		if (m_uFlags & OnKillFocus_SetValid_IfEmpty)
			AdjustWithinRange();

		if ((m_uFlags & OnKillFocus_ShowMessage_IfEmpty) == OnKillFocus_ShowMessage_IfEmpty)
			ShowErrorMessage();

		if (m_uFlags & OnKillFocus_SetFocus_IfEmpty)
			m_pEdit->SetFocus();

		return;
	}

	if (!IsValid())
	{
		if (m_uFlags & OnKillFocus_Beep_IfInvalid)
			MessageBeep(MB_ICONEXCLAMATION);

		if (m_uFlags & OnKillFocus_SetValid_IfInvalid)
			AdjustWithinRange();

		if ((m_uFlags & OnKillFocus_ShowMessage_IfInvalid) == OnKillFocus_ShowMessage_IfInvalid)
			ShowErrorMessage();

		if (m_uFlags & OnKillFocus_SetFocus_IfInvalid)
			m_pEdit->SetFocus();
	}
}

// Returns true if the control's value is valid and falls within the allowed range.
bool CAMSEdit::NumericBehavior::IsValid() const
{
	double dValue = GetDouble();
	return (dValue >= m_dMin && dValue <= m_dMax);
}

// Returns true if the control's value is valid and falls within the allowed range.
// If bShowErrorIfNotValid is true, an error message box is shown and the control gets the focus.
bool CAMSEdit::NumericBehavior::CheckIfValid(bool bShowErrorIfNotValid /*= true*/)
{
	if (!m_pEdit->IsWindowEnabled())
		return true;

	bool bValid = IsValid();
	if (!bValid && bShowErrorIfNotValid)
	{
		ShowErrorMessage();
		m_pEdit->SetFocus();
	}

	return bValid;
}

// Shows a message box informing the user to enter a valid value within the allowed range.
void CAMSEdit::NumericBehavior::ShowErrorMessage() const
{
	CString strMessage = _T("Please specify a valid numeric value.");

	if (m_dMin > AMS_MIN_NUMBER && m_dMax < AMS_MAX_NUMBER)
		strMessage = _T("Please specify a numeric value between ") + GetDoubleText(m_dMin) + _T(" and ") + GetDoubleText(m_dMax) + _T(".");
	else if (m_dMin > AMS_MIN_NUMBER)
		strMessage = _T("Please specify a numeric value greater than or equal to ") + GetDoubleText(m_dMin) + _T(".");
	else if (m_dMax < AMS_MAX_NUMBER)
		strMessage = _T("Please specify a numeric value less than or equal to ") + GetDoubleText(m_dMax) + _T(".");

	AfxMessageBox(strMessage, MB_ICONEXCLAMATION);
}

// Adjusts the control's value to be within the range of allowed numeric values.
void CAMSEdit::NumericBehavior::AdjustWithinRange()
{
	// Check if it's already within the range
	if (IsValid())
		return;

	// If it's empty, set it a valid number
	if (m_pEdit->GetText().IsEmpty())
		m_pEdit->SetWindowText(_T(" "));
	else
		_Redraw();

	// Make it fall within the range
	double dValue = GetDouble();
    if (dValue < m_dMin)
		SetDouble(m_dMin);
    else if (dValue > m_dMax)
		SetDouble(m_dMax);
}

#endif	// (AMSEDIT_COMPILED_CLASSES & AMSEDIT_NUMERIC_CLASS)


#if	(AMSEDIT_COMPILED_CLASSES & AMSEDIT_DATE_CLASS)

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

// Constructs the object with the given control.
CAMSEdit::DateBehavior::DateBehavior(CAMSEdit* pEdit) :
	Behavior(pEdit),
	m_dateMin(AMS_MIN_OLEDATETIME),
	m_dateMax(AMS_MAX_OLEDATETIME),
	m_cSep('/')
{
	// Get the system's date separator
	if (::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, NULL, 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, NULL, 0))
	{
		::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SSHORTDATE, szShortDate, sizeof(szShortDate)/sizeof(TCHAR));

		for (int iPos = 0; szShortDate[iPos]; iPos++)
		{
			TCHAR c = static_cast<TCHAR>(_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;
			}
		}
	}
}

// Handles the WM_CHAR message, which is called when the user enters a regular character or Backspace
void CAMSEdit::DateBehavior::_OnChar(UINT uChar, UINT nRepCnt, UINT nFlags)
{
	// Check to see if it's read only
	if (m_pEdit->IsReadOnly())
		return;

	TCHAR c = static_cast<TCHAR>(uChar);

	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);
				}
				// Check if we can insert the digit with a leading zero
				else if (nLen == nStart && GetMinDayDigit(0) == '0' && IsValidDayDigit(c, 1) && _ShouldEnter(c))
				{
					m_pEdit->SetSel(nStart, nStart + 2);
					m_pEdit->ReplaceSel(CString('0') + c, TRUE);
				}
			}
			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);
				}
				// Check if we can insert the digit with a leading zero
				else if (nLen == nStart && GetMinMonthDigit(0) == '0' && IsValidMonthDigit(c, 1) && _ShouldEnter(c))
				{
					m_pEdit->SetSel(nStart, nStart + 2);
					m_pEdit->ReplaceSel(CString('0') + c, TRUE);
				}
			}
			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);
				}
				// Check if it's a slash and the first digit (preceded by a zero) is a valid month
				else if (c == m_cSep && nLen == nStart && GetMinDayDigit(0) == '0' && IsValidDay(_ttoi(CString('0') + strText[0])) && _ShouldEnter(c))
				{
					m_pEdit->SetSel(0, nStart);
					m_pEdit->ReplaceSel(CString('0') + strText[0] + c, TRUE);
				}
			}
			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);
				}
				// Check if it's a slash and the first digit (preceded by a zero) is a valid month
				else if (c == m_cSep && nLen == nStart && GetMinMonthDigit(0) == '0' && IsValidMonth(_ttoi(CString('0') + strText[0])) && _ShouldEnter(c))
				{
					m_pEdit->SetSel(0, nStart);
					m_pEdit->ReplaceSel(CString('0') + strText[0] + c, TRUE);
				}
			}
			break;
		}

		case 2:		// FIRST SLASH
		{
			int nSlash = 0;
			if (c == m_cSep)
				nSlash = 1;
			else
			{
				if (m_uFlags & DayBeforeMonth)
					nSlash = (IsValidMonthDigit(c, 0) || (nLen == nStart && GetMinMonthDigit(0) == '0' && IsValidMonthDigit(c, 1))) ? 2 : 0;
				else
					nSlash = (IsValidDayDigit(c, 0) || (nLen == nStart && GetMinDayDigit(0) == '0' && IsValidDayDigit(c, 1))) ? 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);
							}
						}
					}
					else
						Behavior::_OnChar(uChar, nRepCnt, nFlags);

					AdjustMaxDay();
				}
				// Check if we can insert the digit with a leading zero
				else if (nLen == nStart && GetMinMonthDigit(0) == '0' && IsValidMonthDigit(c, 1) && _ShouldEnter(c))
				{
					m_pEdit->SetSel(nStart, nStart + 2);
					m_pEdit->ReplaceSel(CString('0') + c, TRUE);
					AdjustMaxDay();
				}
			}
			else
			{

⌨️ 快捷键说明

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