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

📄 amsedit.cpp

📁 一款密码保险箱源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	}

	if (_ShouldEnter(c))
		Behavior::_OnChar(uChar, nRepCnt, nFlags);
}

#endif	// (AMSEDIT_COMPILED_CLASSES & AMSEDIT_ALPHANUMERIC_CLASS)


#if (AMSEDIT_COMPILED_CLASSES & AMSEDIT_MASKED_CLASS)

/////////////////////////////////////////////////////////////////////////////
// CAMSEdit::MaskedBehavior

// Constructs the object using the given mask.
CAMSEdit::MaskedBehavior::MaskedBehavior(CAMSEdit* pEdit, const CString& strMask /*= _T("")*/) :
	Behavior(pEdit),
	m_strMask(strMask)
{
	m_arraySymbols.Add(Symbol('#', _istdigit));  // default mask symbol
}

// Returns the mask
const CString& CAMSEdit::MaskedBehavior::GetMask() const
{
	return m_strMask;
}

// Sets the mask and redraws the control to accomodate it
void CAMSEdit::MaskedBehavior::SetMask(const CString& strMask)
{
	if (m_strMask == strMask)
		return;

	m_strMask = strMask;
	_Redraw();
}

// Returns the numeric portion of the control's value as a string
CString CAMSEdit::MaskedBehavior::GetNumericText() const
{
	CString strText = m_pEdit->GetText();
	CString strResult;

	for (int iPos = 0, nLen = strText.GetLength(); iPos < nLen; iPos++)
	{
		TCHAR c = strText[iPos];
		if (_istdigit(c))
			strResult += c;
	}

	return strResult;
}

// Returns the control's value in a valid format.
CString CAMSEdit::MaskedBehavior::_GetValidText() const
{
	CString strText = m_pEdit->GetText();
	int nMaskLen = m_strMask.GetLength();

	// If the mask is empty, allow anything
	if (!nMaskLen)
		return strText;

	CString strNewText;

	// Accomodate the text to the mask as much as possible
	for (int iPos = 0, iMaskPos = 0, nLen = strText.GetLength(); iPos < nLen; iPos++, iMaskPos++)
	{
		TCHAR c = strText[iPos];
		TCHAR cMask = static_cast<TCHAR>(iMaskPos < nMaskLen ? m_strMask[iMaskPos] : 0);

		// If we've reached the end of the mask, break
		if (!cMask)
			break;

		// Match the character to any of the symbols
		for (int iSymbol = 0, nSymbolCount = m_arraySymbols.GetSize(); iSymbol < nSymbolCount; iSymbol++)
		{
			const Symbol& symbol = m_arraySymbols[iSymbol];

			// Find the symbol that applies for the given character
			if (cMask != symbol || !symbol.Validate(c))
				continue;

			// Try to add matching characters in the mask until a different symbol is reached
			for (; iMaskPos < nMaskLen; iMaskPos++)
			{
				cMask = m_strMask[iMaskPos];
				if (cMask == symbol)
				{
					strNewText += symbol.Convert(c);
					break;
				}
				else
				{
					for (int iSymbol2 = 0; iSymbol2 < nSymbolCount; iSymbol2++)
					{
						if (cMask == m_arraySymbols[iSymbol2])
						{
							strNewText += symbol.Convert(c);
							break;
						}
					}

					if (iSymbol2 < nSymbolCount)
						break;

					strNewText += cMask;
				}
			}

			break;
		}

		// If the character was not matched to a symbol, stop
		if (iSymbol == nSymbolCount)
		{
			if (c == cMask)
			{
				// Match the character to any of the symbols
				for (iSymbol = 0; iSymbol < nSymbolCount; iSymbol++)
				{
					if (cMask == m_arraySymbols[iSymbol])
						break;
				}

				if (iSymbol == nSymbolCount)
				{
					strNewText += c;
					continue;
				}
			}

			break;
		}
	}

	return strNewText;
}

// Handles the WM_CHAR message, which is called when the user enters a regular character or Backspace
void CAMSEdit::MaskedBehavior::_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);

	// If the mask is empty, allow anything
	int nMaskLen = m_strMask.GetLength();
	if (!nMaskLen)
	{
		if (_ShouldEnter(c))
			Behavior::_OnChar(uChar, nRepCnt, nFlags);
		return;
	}

	// Check that we haven't gone past the mask's length
	int nStart, nEnd;
	m_pEdit->GetSel(nStart, nEnd);
	if (nStart >= nMaskLen && c != VK_BACK)
		return;

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

	TCHAR cMask = m_strMask[nStart];

	// Check if the mask's character matches with any of the symbols in the array.
	for (int iSymbol = 0, nSymbolCount = m_arraySymbols.GetSize(); iSymbol < nSymbolCount; iSymbol++)
	{
		const Symbol& symbol = m_arraySymbols[iSymbol];
		if (cMask == symbol)
		{
			if (symbol.Validate(c) && _ShouldEnter(c))
			{
				nEnd = (nEnd == nLen ? nEnd : (nStart + 1));
				m_pEdit->SetSel(nStart, nEnd);
				m_pEdit->ReplaceSel(CString(symbol.Convert(c)), TRUE);
			}
			return;
		}
	}

	// Check if it's the same character as the mask.
	if (cMask == c && _ShouldEnter(c))
	{
		nEnd = (nEnd == nLen ? nEnd : (nStart + 1));
		m_pEdit->SetSel(nStart, nEnd);
		m_pEdit->ReplaceSel(CString(c), TRUE);
		return;
	}

	// Concatenate all the mask symbols
	CString strSymbols;
	for (iSymbol = 0; iSymbol < nSymbolCount; iSymbol++)
		strSymbols += m_arraySymbols[iSymbol];

	// If it's a valid character, find the next symbol on the mask and add any non-mask characters in between.
	for (iSymbol = 0; iSymbol < nSymbolCount; iSymbol++)
	{
		const Symbol& symbol = m_arraySymbols[iSymbol];

		// See if the character is valid for any other symbols
		if (!symbol.Validate(c))
			continue;

		// Find the position of the next symbol
		CString strMaskPortion = m_strMask.Mid(nStart);
		int nMaskPos = strMaskPortion.FindOneOf(strSymbols);

		// Enter the character if there isn't another symbol before it
		if (nMaskPos >= 0 && strMaskPortion[nMaskPos] == symbol && _ShouldEnter(c))
		{
			m_pEdit->SetSel(nStart, nStart + nMaskPos);
			m_pEdit->ReplaceSel(strMaskPortion.Left(nMaskPos), TRUE);

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

// Handles the WM_KEYDOWN message, which is called when the user enters a special character such as Delete or the arrow keys.
void CAMSEdit::MaskedBehavior::_OnKeyDown(UINT uChar, UINT nRepCnt, UINT nFlags)
{
	switch (uChar)
	{
		case VK_DELETE:
		{
			// If deleting make sure it's the last character or that
			// the selection goes all the way to the end of the text

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

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

			if (nEnd != nLen)
			{
				if (!(nEnd == nStart && nEnd == nLen - 1))
					return;
			}
			break;
		}
	}

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

// Returns a reference to the array of symbols that may be found on the mask.
// This allows adding, editing, or deleting symbols for the mask.
CAMSEdit::MaskedBehavior::SymbolArray& CAMSEdit::MaskedBehavior::GetSymbolArray()
{
	return m_arraySymbols;
}


/////////////////////////////////////////////////////////////////////////////
// CAMSEdit::MaskedBehavior::Symbol

// Constructs the object -- needed for CArray
CAMSEdit::MaskedBehavior::Symbol::Symbol() :
	m_cSymbol(0),
	m_fnValidation(NULL),
	m_fnConversion(NULL)
{
}

// Constructs the object with the given character and set of functions
CAMSEdit::MaskedBehavior::Symbol::Symbol(TCHAR cSymbol, ValidationFunction fnValidation, ConversionFunction fnConversion /*= NULL*/) :
	m_cSymbol(cSymbol),
	m_fnValidation(fnValidation),
	m_fnConversion(fnConversion)
{
}

// Destroys the object (virtual).
CAMSEdit::MaskedBehavior::Symbol::~Symbol()
{
}

// Returns true if the given character (usually just entered by the user) is a match for self's symbol.
// This is tested by passing it to the validation function passed in the constructor (if valid).
bool CAMSEdit::MaskedBehavior::Symbol::Validate(TCHAR c) const
{
	if (m_fnValidation)
		return (m_fnValidation(c) != 0);
	return true;
}

// Returns the given character converted as a result of calling the conversion function was passed in the constructor.
// If no conversion function was passed, the character is returned intact.
TCHAR CAMSEdit::MaskedBehavior::Symbol::Convert(TCHAR c) const
{
	if (m_fnConversion)
		return (TCHAR)m_fnConversion(c);
	return c;
}

// Sets the character for the symbol to be used in the mask.
void CAMSEdit::MaskedBehavior::Symbol::Set(TCHAR cSymbol)
{
	m_cSymbol = cSymbol;
}

// Returns the character for the symbol to be used in the mask.
TCHAR CAMSEdit::MaskedBehavior::Symbol::Get() const
{
	return m_cSymbol;
}

// Returns the character for the symbol to be used in the mask.
CAMSEdit::MaskedBehavior::Symbol::operator TCHAR() const
{
	return m_cSymbol;
}

#endif	// (AMSEDIT_COMPILED_CLASSES & AMSEDIT_MASKED_CLASS)


#if	(AMSEDIT_COMPILED_CLASSES & AMSEDIT_NUMERIC_CLASS)

/////////////////////////////////////////////////////////////////////////////
// CAMSEdit::NumericBehavior

// Constructs the object using the given nMaxWholeDigits and nMaxDecimalPlaces.
CAMSEdit::NumericBehavior::NumericBehavior(CAMSEdit* pEdit, int nMaxWholeDigits /*= 9*/, int nMaxDecimalPlaces /*= 4*/) :
	Behavior(pEdit),
	m_nMaxWholeDigits(nMaxWholeDigits >= 0 ? nMaxWholeDigits : -nMaxWholeDigits),
	m_nMaxDecimalPlaces(nMaxDecimalPlaces),
	m_cNegativeSign('-'),
	m_cDecimalPoint('.'),
	m_cGroupSeparator(','),
	m_nDigitsInGroup(0),
	m_dMin(AMS_MIN_NUMBER),
	m_dMax(AMS_MAX_NUMBER),
	m_bAdjustingSeparators(false)
{
	ASSERT(m_nMaxWholeDigits > 0);		// must have at least 1 digit to the left of the decimal
	ASSERT(m_nMaxDecimalPlaces >= 0);	// decimal places must be positive

	if (nMaxWholeDigits < 0)
		m_uFlags |= CannotBeNegative;

	// Get the system's negative sign
	if (::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN, NULL, 0))
		::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN, &m_cNegativeSign, sizeof(m_cNegativeSign));

	// Get the system's decimal point
	if (::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, NULL, 0))
		::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, &m_cDecimalPoint, sizeof(m_cDecimalPoint));

	// Get the system's group separator
	if (::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, NULL, 0))
		::GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, &m_cGroupSeparator, sizeof(m_cGroupSeparator));

	// Ensure the separators are not the same
	if (m_cDecimalPoint == m_cGroupSeparator)
		m_cGroupSeparator = (m_cDecimalPoint == ',' ? '.' : ',');
}

// Sets the maximum number of digits before the decimal point.
// If nMaxWholeDigits is negative, then negative numbers will NOT be allowed.
void CAMSEdit::NumericBehavior::SetMaxWholeDigits(int nMaxWholeDigits)
{
	ASSERT(nMaxWholeDigits);

	// If nMaxWholeDigits is negative, don't allow negatives
	bool bAllowNegative = (nMaxWholeDigits >= 0);
	if (nMaxWholeDigits < 0)
		nMaxWholeDigits = -nMaxWholeDigits;

	if (m_nMaxWholeDigits == nMaxWholeDigits && IsNegativeAllowed() == bAllowNegative)
		return;

	m_nMaxWholeDigits = nMaxWholeDigits;
	if (!ModifyFlags(bAllowNegative ? 0 : CannotBeNegative, bAllowNegative ? CannotBeNegative : 0))
		_Redraw();
}

// Returns the maximum number of digits before the decimal point.
int CAMSEdit::NumericBehavior::GetMaxWholeDigits() const
{
	return m_nMaxWholeDigits;
}

// Sets the maximum number of digits after the decimal point.
void CAMSEdit::NumericBehavior::SetMaxDecimalPlaces(int nMaxDecimalPlaces)
{
	ASSERT(nMaxDecimalPlaces >= 0);
	if (m_nMaxDecimalPlaces == nMaxDecimalPlaces)
		return;

	m_nMaxDecimalPlaces = nMaxDecimalPlaces;
	_Redraw();
}

// Returns the maximum number of digits after the decimal point.
int CAMSEdit::NumericBehavior::GetMaxDecimalPlaces() const
{
	return m_nMaxDecimalPlaces;
}

// Sets whether the negative sign is allowed in the number or not.
void CAMSEdit::NumericBehavior::AllowNegative(bool bAllowNegative /*= true*/)
{
	ModifyFlags(bAllowNegative ? 0 : CannotBeNegative, bAllowNegative ? CannotBeNegative : 0);
}

// Returns true if the negative sign is allowed in the number.
bool CAMSEdit::NumericBehavior::IsNegativeAllowed() const
{
	return !(m_uFlags & CannotBeNegative);
}

// Sets the number of digits to be grouped together (if any).
void CAMSEdit::NumericBehavior::SetDigitsInGroup(int nDigitsInGroup)
{
	ASSERT(nDigitsInGroup >= 0);
	if (m_nDigitsInGroup == nDigitsInGroup)
		return;

	m_nDigitsInGroup = nDigitsInGroup;
	_Redraw();
}

// Returns the number of digits to be grouped together (if any).
int CAMSEdit::NumericBehavior::GetDigitsInGroup() const
{
	return m_nDigitsInGroup;
}

// Sets the character to use for the decimal point and the group separator (thousands)
void CAMSEdit::NumericBehavior::SetSeparators(TCHAR cDecimal, TCHAR cGroup)
{
	ASSERT(cDecimal);
	ASSERT(cGroup);

	// If nothing's changing, leave
	if (m_cDecimalPoint == cDecimal && m_cGroupSeparator == cGroup)
		return;

	// Set them
	m_cDecimalPoint = cDecimal;
	m_cGroupSeparator = cGroup;

	// Ensure they're not the same
	if (m_cDecimalPoint == m_cGroupSeparator)
		m_cGroupSeparator = (m_cDecimalPoint == ',' ? '.' : ',');

	_Redraw();
}

// Retrieves the character being used for the decimal point and group separator (thousands).
void CAMSEdit::NumericBehavior::GetSeparators(TCHAR* pcDecimal, TCHAR* pcGroup) const
{
	if (pcDecimal)

⌨️ 快捷键说明

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