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

📄 amsedit.cpp

📁 一款密码保险箱源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		*pcDecimal = m_cDecimalPoint;
	if (pcGroup)
		*pcGroup = m_cGroupSeparator;
}

// Sets the text to be automatically inserted in front of the number (such as a currency sign).
void CAMSEdit::NumericBehavior::SetPrefix(const CString& strPrefix)
{
	if (m_strPrefix == strPrefix)
		return;

	m_strPrefix = strPrefix;
	_Redraw();
}

// Returns the text to be automatically inserted in front of the number (such as a currency sign).
const CString& CAMSEdit::NumericBehavior::GetPrefix() const
{
	return m_strPrefix;
}

// Parses the given strMask to set the control's configuration.
void CAMSEdit::NumericBehavior::SetMask(const CString& strMask)
{
	int nDecimalPos = -1;
	int nLen = strMask.GetLength();

	m_nMaxWholeDigits = 0;
	m_nMaxDecimalPlaces = 0;
	m_nDigitsInGroup = 0;
	m_uFlags = (m_uFlags & ~CannotBeNegative);  // allow it to be negative
	m_strPrefix = _T("");

	for (int iPos = nLen - 1; iPos >= 0; iPos--)
	{
		TCHAR c = strMask[iPos];
		if (c == '#')
		{
			if (nDecimalPos >= 0)
				m_nMaxWholeDigits++;
			else
				m_nMaxDecimalPlaces++;
		}
		else if ((c == '.' || c == m_cDecimalPoint) && nDecimalPos < 0)
		{
			nDecimalPos = iPos;
			m_cDecimalPoint = c;
		}
		else if (c == ',' || c == m_cGroupSeparator)
		{
			if (!m_nDigitsInGroup)
			{
				m_nDigitsInGroup = (((nDecimalPos >= 0) ? nDecimalPos : nLen) - iPos) - 1;
				m_cGroupSeparator = c;
			}
		}
		else
		{
			m_strPrefix = strMask.Left(iPos + 1);
			break;
		}
	}

	if (nDecimalPos < 0)
	{
		m_nMaxWholeDigits = m_nMaxDecimalPlaces;
		m_nMaxDecimalPlaces = 0;
	}

	ASSERT(m_nMaxWholeDigits > 0);	// must have at least one digit on left side of decimal point
	_Redraw();
}

// Gets the mask corresponding to the maximum number than can be entered into the control
CString CAMSEdit::NumericBehavior::GetMask() const
{
	CString strMask;

	for (int iDigit = 0; iDigit < m_nMaxWholeDigits; iDigit++)
		strMask += '0';

	if (m_nMaxDecimalPlaces)
		strMask += m_cDecimalPoint;

	for (iDigit = 0; iDigit < m_nMaxDecimalPlaces; iDigit++)
		strMask += '0';

	strMask = GetSeparatedText(strMask);

	for (int iPos = 0, nLen = strMask.GetLength(); iPos < nLen; iPos++)
	{
		if (strMask[iPos] == '0')
			strMask.SetAt(iPos, '#');
	}

	return strMask;
}

// Sets the range of allowed values to the given minimum and maximum double values.
void CAMSEdit::NumericBehavior::SetRange(double dMin, double dMax)
{
	ASSERT(dMin <= dMax);

	m_dMin = dMin;
	m_dMax = dMax;

	_Redraw();
}

// Retrieves the range of allowed values inside the given set of double pointers.
void CAMSEdit::NumericBehavior::GetRange(double* pdMin, double* pdMax) const
{
	if (pdMin)
		*pdMin = m_dMin;
	if (pdMax)
		*pdMax = m_dMax;
}

// Returns the number of group separator characters in the given strText.
int CAMSEdit::NumericBehavior::GetGroupSeparatorCount(const CString& strText) const
{
	for (int iPos = 0, nSepCount = 0, nLen = strText.GetLength(); iPos < nLen; iPos++)
	{
		if (strText[iPos] == m_cGroupSeparator)
			nSepCount++;
	}

	return nSepCount;
}

// Returns the given strText as a numeric string.
CString CAMSEdit::NumericBehavior::GetNumericText(const CString& strText, bool bUseMathSymbols /*= false*/) const
{
	CString strNewText;
	bool bIsNegative = false;
	bool bHasDecimalPoint = false;

	for (int iPos = 0, nLen = strText.GetLength(); iPos < nLen; iPos++)
	{
		TCHAR c = strText[iPos];
		if (_istdigit(c))
			strNewText += c;
		else if (c == m_cNegativeSign)
			bIsNegative = true;
		else if (c == m_cDecimalPoint && !bHasDecimalPoint)
		{
			bHasDecimalPoint = true;
			strNewText += (bUseMathSymbols ? '.' : m_cDecimalPoint);
		}
	}

	// Add the negative sign to the front of the number
	if (bIsNegative)
		strNewText.Insert(0, bUseMathSymbols ? '-' : m_cNegativeSign);

	return strNewText;
}

// Returns the current double as a text value.
// If bTrimTrailingZeros is true, any insignificant zeros after the decimal point are removed.
CString CAMSEdit::NumericBehavior::GetDoubleText(double dText, bool bTrimTrailingZeros /*= true*/) const
{
	CString strText;
	strText.Format(_T("%lf"), dText);

	if (m_cDecimalPoint != '.')
		strText.Replace('.', m_cDecimalPoint);

	if (bTrimTrailingZeros)
	{
		strText.TrimRight('0');
		strText.TrimRight(m_cDecimalPoint);
	}

	return strText;
}

// Sets the control's text to the given double value.
// If bTrimTrailingZeros is true, any insignificant zeros after the decimal point are removed.
void CAMSEdit::NumericBehavior::SetDouble(double dText, bool bTrimTrailingZeros /*= true*/)
{
	m_pEdit->SetWindowText(GetDoubleText(dText, bTrimTrailingZeros));
}

// Returns the current text as a double value.
double CAMSEdit::NumericBehavior::GetDouble() const
{
	return _tcstod(GetNumericText(m_pEdit->GetText()), NULL);
}

// Sets the control's text to the given integer value.
void CAMSEdit::NumericBehavior::SetInt(int nText)
{
	CString strText;
	strText.Format(_T("%d"), nText);
	m_pEdit->SetWindowText(strText);
}

// Returns the current text as an integer value.
int CAMSEdit::NumericBehavior::GetInt() const
{
	return _ttoi(GetNumericText(m_pEdit->GetText()));
}

// Adjusts the location of separators based on the nCurrentSeparatorCount.
void CAMSEdit::NumericBehavior::AdjustSeparators(int nCurrentSeparatorCount)
{
	SelectionSaver selection = m_pEdit;
	m_bAdjustingSeparators = true;

	CString strText = _GetValidText();
	if (strText != m_pEdit->GetText())
		m_pEdit->SetWindowText(strText);

	// Adjust the current selection if separators were added/removed
	int nNewSeparatorCount = GetGroupSeparatorCount(strText);
	if (nCurrentSeparatorCount != nNewSeparatorCount && selection.GetStart() > m_strPrefix.GetLength())
		selection += (nNewSeparatorCount - nCurrentSeparatorCount);

	m_bAdjustingSeparators = false;
}

// Returns the given text with the group separator characters inserted in the proper places.
CString CAMSEdit::NumericBehavior::GetSeparatedText(const CString& strText) const
{
	CString strNumericText = GetNumericText(strText);
	CString strNewText = strNumericText;

	// Retrieve the number without the decimal point
	int nDecimalPos = strNumericText.Find(m_cDecimalPoint);
	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;
}

// Inserts nCount zeros into the given string at the given position.
// If nPos is less than 0, the zeros are appended.
void CAMSEdit::NumericBehavior::InsertZeros(CString* pStrText, int nPos, int nCount)
{
	ASSERT(pStrText);

	if (nPos < 0 && nCount > 0)
		nPos = pStrText->GetLength();

	for (int iZero = 0; iZero < nCount; iZero++)
		pStrText->Insert(nPos, '0');
}

// Returns the control's value in a valid format.
CString CAMSEdit::NumericBehavior::_GetValidText() const
{
	CString strText = m_pEdit->GetText();
	CString strNewText;
	bool bIsNegative = false;

	// 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 (c == m_cNegativeSign && IsNegativeAllowed())
			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)
				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++;
		}
	}

	// Check if we need to pad the number with zeros after the decimal point
	if (m_nMaxDecimalPlaces > 0 && nNewLen > 0 &&
		((m_uFlags & PadWithZerosAfterDecimalWhenTextChanges) ||
		(!m_bAdjustingSeparators && (m_uFlags & PadWithZerosAfterDecimalWhenTextIsSet))))
	{
		if (nDecimalPos < 0)
		{
			if (nNewLen == 0 || strNewText == '-')
			{
				strNewText = '0';
				nNewLen = 1;
			}
			strNewText += m_cDecimalPoint;
			nDecimalPos = nNewLen++;
		}

		InsertZeros(&strNewText, -1, m_nMaxDecimalPlaces - (nNewLen - nDecimalPos - 1));
	}

	// Insert the negative sign if it's there
	if (bIsNegative)
		strNewText.Insert(0, m_cNegativeSign);

	return GetSeparatedText(strNewText);
}

// Handles the WM_CHAR message, which is called when the user enters a regular character or Backspace
void CAMSEdit::NumericBehavior::_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();
	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 && _istprint(c))
	{
		TCHAR cPrefix = m_strPrefix[nStart];

		// Check if it's the same character as the prefix.
		if (cPrefix == c && _ShouldEnter(c))
		{
			if (nLen > nStart)
			{
				nEnd = (nEnd == nLen ? nEnd : (nStart + 1));
				m_pEdit->SetSel(nStart, nEnd);
				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))
		{
			nEnd = (nEnd == nLen ? nEnd : (nPrefixLen));
			m_pEdit->SetSel(nStart, nEnd);
			m_pEdit->ReplaceSel(m_strPrefix.Mid(nStart), TRUE);

			NumericBehavior::_OnChar(uChar, nRepCnt, nFlags);
		}

		return;
	}

	// Check if it's a negative sign
	if (c == m_cNegativeSign && IsNegativeAllowed())
	{
		// If it's at the beginning, determine if it should overwritten
		if (nStart == nPrefixLen)
		{
			if (!strNumericText.IsEmpty() && strNumericText[0] == m_cNegativeSign && _ShouldEnter(c))
			{
				nEnd = (nEnd == nLen ? nEnd : (nStart + 1));
				m_pEdit->SetSel(nStart, nEnd);
				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)
		{
			// Check if we're replacing the decimal point
			if (nDecimalPos >= nStart && nDecimalPos < nEnd)
				bNeedAdjustment = true;
			else
			{	// Otherwise, put the caret on it
				if (_ShouldEnter(c))
					m_pEdit->SetSel(nDecimalPos + 1, nDecimalPos + 1);
				return;
			}
		}
		else
			bNeedAdjustment = true;
	}

	// 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))
				{
					nEnd = (nEnd == nLen ? nEnd : (nStart + 1));
					m_pEdit->SetSel(nStart, nEnd);
					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)
			{
				if (m_uFlags & AddDecimalAfterMaxWholeDigits && m_nMaxDecimalPlaces > 0)
				{
					nEnd = (nEnd == nLen ? nEnd : (nStart + 2));
					m_pEdit->SetSel(nStart, nEnd);
					m_pEdit->ReplaceSel(CString(m_cDecimalPoint) + c, TRUE);
				}
				return;
			}

			if (strNumericText.Mid(0, nNumericDecimalPos >= 0 ? nNumericDecimalPos : nNumericLen).GetLength() == m_nMaxWholeDigits + bIsNegative)

⌨️ 快捷键说明

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