Click here to Skip to main content
15,884,743 members
Articles / Desktop Programming / ATL

SP Numeric Edit Control

Rate me:
Please Sign up or sign in to vote.
4.78/5 (11 votes)
16 Nov 200511 min read 74.7K   3.6K   36  
Masked numeric edit ActiveX control.
/////////////////////////////////////////////////////////////////////////////////////////
//	Project:		SP Data Formatting Library 1.5
//
//	File:			BinarySignedIntegerFormatter.h
//
//	Developer(s):	Sergei Pavlovsky
//					sergei_vp@hotmail.com
//					Copyright (c) 2004-2005
//
//	Description:	Classes used for a handling of binary signed integer data.
//
//	Platforms:		Win32, ATL
//
//	This code may be used in compiled form in any way you desire. This file may be 
//	redistributed unmodified by any means PROVIDING it is not sold for profit without 
//	the authors written consent, and providing that this notice and the authors name 
//	is included. If the source code in this file is used in any commercial application 
//	then acknowledgement must be made to the author of this file (in whatever form 
//	you wish).
//
//	This file is provided "as is" with no expressed or implied warranty. The author 
//	accepts no liability for any damage/loss of business that this product may cause.
/////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include "IntegerFormatter.h"

namespace SP
{

/////////////////////////////////////////////////////////////////////////////////////////
// CSignedInt8Base class
/////////////////////////////////////////////////////////////////////////////////////////

class CSignedInt8Base
{
// Constants
public:
	enum
	{
		MAX_CONVBUFFER = 5
	};

// Types
public:
	typedef char TCore;

// Utilities: Formatting & scanning 
public:
	static SIZE_T _RawFormat(char value, LPTSTR lpszBuffer);
	static bool _RawScan(LPCTSTR lpcszNumber, char* pValue);
};

/////////////////////////////////////////////////////////////////////////////////////////
// CSignedInt16Base class
/////////////////////////////////////////////////////////////////////////////////////////

class CSignedInt16Base
{
// Constants
public:
	enum
	{
		MAX_CONVBUFFER = 7
	};

// Types
public:
	typedef short TCore;

// Utilities: Formatting & scanning 
public:
	static SIZE_T _RawFormat(short value, LPTSTR lpszBuffer);
	static bool _RawScan(LPCTSTR lpcszNumber, short* pValue);
};

/////////////////////////////////////////////////////////////////////////////////////////
// CSignedInt32Base class
/////////////////////////////////////////////////////////////////////////////////////////

class CSignedInt32Base
{
// Constants
public:
	enum
	{
		MAX_CONVBUFFER = 12
	};

// Types
public:
	typedef int TCore;

// Utilities: Formatting & scanning 
public:
	static SIZE_T _RawFormat(int value, LPTSTR lpszBuffer);
	static bool _RawScan(LPCTSTR lpcszNumber, int* pValue);
};

/////////////////////////////////////////////////////////////////////////////////////////
// CSignedInt64Base class
/////////////////////////////////////////////////////////////////////////////////////////

class CSignedInt64Base
{
// Constants
public:
	enum
	{
		MAX_CONVBUFFER = 21
	};

// Types
public:
	typedef __int64 TCore;

// Utilities: Formatting & scanning 
public:
	static SIZE_T _RawFormat(__int64 value, LPTSTR lpszBuffer);
	static bool _RawScan(LPCTSTR lpcszNumber, __int64* pValue);
};

/////////////////////////////////////////////////////////////////////////////////////////
// CIEEERealDigitalPattern class template
/////////////////////////////////////////////////////////////////////////////////////////

template < class TCoreBase, char t_nSign, bool t_bZero >
class CBinarySignedIntegerDigitalPattern : public CIntegerDigitalPattern,
										   protected TCoreBase
{
// Types
public:
	typedef typename TCoreBase::TCore TCore;

// Types
private:	
	typedef CCtxAutoSwitch<TCompCtx, CBinarySignedIntegerDigitalPattern> 
		CCompCtxAutoSwitch;

	typedef CCtxAutoSwitch<TGenrCtx, CBinarySignedIntegerDigitalPattern> 
		CGenrCtxAutoSwitch;

	typedef CCtxAutoSwitch<TTranCtx, CBinarySignedIntegerDigitalPattern> 
		CTranCtxAutoSwitch;

	typedef CCtxAutoSwitch<TDataCtx, CBinarySignedIntegerDigitalPattern> 
		CDataCtxAutoSwitch;

// Construction & destruction
public:
	CBinarySignedIntegerDigitalPattern()
	{
	}

	CBinarySignedIntegerDigitalPattern(const CBinarySignedIntegerDigitalPattern& src)
		: CIntegerDigitalPattern(src)
	{
	}

// Operators
public:
	CBinarySignedIntegerDigitalPattern& operator=(
							const CBinarySignedIntegerDigitalPattern& right)
	{
		CIntegerDigitalPattern::operator=(right);

		return *this;
	}

// Operations: Common
public:
	char GetSign() const
	{
		return t_nSign;
	}

	bool IsZero() const
	{
		return t_bZero;
	}

	UINT _GetGeneralOperationErrorReason(EnumGeneralOperations enOp) const
	{
		// Depending on the template parameters optimizer will leave 
		// the only one of the following "if" statements.

		if ( !t_bZero && t_nSign > 0 )
		{
			const UINT rgIDs[] = 
				{
					EDF_COMPOSEPOSVALUEPATTERN,
					EDF_GENERATEPOSVALUEPATTERN,
					EDF_PARSEPOSVALUEPATTERN,
					EDF_TRANSLATEPOSVALUEPATTERN,
					0,
					0,
					0,
					0
				};

			ATLASSERT( enOp < sizeof(rgIDs)/sizeof(UINT) );

			return rgIDs[enOp];
		}

		if ( !t_bZero && t_nSign < 0 )
		{
			const UINT rgIDs[] = 
				{
					EDF_COMPOSENEGVALUEPATTERN,
					EDF_GENERATENEGVALUEPATTERN,
					EDF_PARSENEGVALUEPATTERN,
					EDF_TRANSLATENEGVALUEPATTERN,
					0,
					0,
					0,
					0
				};

			ATLASSERT( enOp < sizeof(rgIDs)/sizeof(UINT) );

			return rgIDs[enOp];
		}
		
		if ( t_bZero )
		{
			const UINT rgIDs[] = 
				{
					EDF_COMPOSEZEROPATTERN,
					EDF_GENERATEZEROPATTERN,
					EDF_PARSEZEROPATTERN,
					EDF_TRANSLATEZEROPATTERN,
					0,
					0,
					0,
					0
				};

			ATLASSERT( enOp < sizeof(rgIDs)/sizeof(UINT) );

			return rgIDs[enOp];
		}

		return 0;
	}

// Helpers: Formatting & scanning
private:
	SIZE_T _Format(TDataCtx& ctx, const TCore value, LPTSTR lpBuffer, 
					 SIZE_T cchBuffer) const
	{
		ATLASSERT( !::IsBadWritePtr(lpBuffer, cchBuffer * sizeof(TCHAR)) );

		// Perform standard formatting of the value
		TCHAR szRaw[MAX_CONVBUFFER];

		const SIZE_T cchRaw = _RawFormat(value, szRaw);
		ATLASSERT( cchRaw < MAX_CONVBUFFER );

		// Format the value according to the pattern
		return CIntegerDigitalPattern::_Format(ctx, szRaw, cchRaw, lpBuffer, cchBuffer);
	}
	
	bool _Match(TDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText) const
	{
		ATLASSERT( !::IsBadReadPtr(lpcText, cchText * sizeof(TCHAR)) );
	
		return CIntegerDigitalPattern::_Scan(ctx, lpcText, cchText, NULL, 0) 
					!= STATUS_FALSE;
	}

	bool _Scan(TDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText, 
			   TCore* pValue, bool* pbNotNull) const
	{
		ATLASSERT( !::IsBadReadPtr(lpcText, cchText * sizeof(TCHAR)) );
		ATLASSERT( !::IsBadWritePtr(pValue, sizeof(TCore)) );
		ATLASSERT( !::IsBadWritePtr(pbNotNull, sizeof(bool)) );

		bool bResult;

		try
		{
			const SIZE_T cchRawBuf = cchText + 3;

			CTempBuffer<TCHAR> bufRaw(cchRawBuf);
			
			const SIZE_T cchRaw = CIntegerDigitalPattern::_Scan(ctx, lpcText, cchText, 
																bufRaw, cchRawBuf);
			if ( cchRaw == STATUS_FALSE )
				return false;

			ATLASSERT( cchRaw < cchRawBuf );
			bufRaw[cchRaw] = _T('\x0');

			*pbNotNull = true;

			bResult = _RawScan(bufRaw, pValue);
		}
		catch ( CAtlException& e )
		{
			throw EAtlLogError(e);
		}

		return bResult;
	}

// Operations: Formatting & scanning
public:
	SIZE_T Format(CDataCtx& ctx, const void* lpcValue, 
				  LPTSTR lpBuffer, SIZE_T cchBuffer) const
	{
		ATLASSERT( !::IsBadReadPtr(lpcValue, sizeof(TCore)) );
		ATLASSERT( !::IsBadWritePtr(lpBuffer, cchBuffer * sizeof(TCHAR)) );

		CDataCtxAutoSwitch ctxSwitch(ctx, this);

		const TCore* const pcValue = reinterpret_cast<const TCore*>(lpcValue);

		return _Format(ctxSwitch.GetCtx(), *pcValue, lpBuffer, cchBuffer);
	}

	bool Matches(CDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText) const
	{
		ATLASSERT( !::IsBadReadPtr(lpcText, cchText * sizeof(TCHAR)) );

		CDataCtxAutoSwitch ctxSwitch(ctx, this);

		return _Match(ctxSwitch.GetCtx(), lpcText, cchText);
	}

	bool Scan(CDataCtx& ctx, LPCTSTR lpcText, SIZE_T cchText, 
			  void* lpValue, bool* pbNotNull) const
	{
		ATLASSERT( !::IsBadReadPtr(lpcText, cchText * sizeof(TCHAR)) );
		ATLASSERT( !::IsBadWritePtr(lpValue, sizeof(TCore)) );
		ATLASSERT( !::IsBadWritePtr(pbNotNull, sizeof(bool)) );		

		CDataCtxAutoSwitch ctxSwitch(ctx, this);

		TCore* const pValue = reinterpret_cast<TCore*>(lpValue);

		return _Scan(ctxSwitch.GetCtx(), lpcText, cchText, pValue, pbNotNull);
	}
};

/////////////////////////////////////////////////////////////////////////////////////////
// CBinarySignedIntegerFormatterBase class
/////////////////////////////////////////////////////////////////////////////////////////

class CBinarySignedIntegerFormatterBase
{
// Constants
protected:
	enum EnumPatterns
	{				
		PTM_PATTERN			 = 0x00FF,

		PT_POSITIVENUMBER	 = 0x0000,
		PT_NEGATIVENUMBER	 = 0x0001,
		PT_ZERO				 = 0x0002,
		PT_NULL				 = 0x0003,

		PTC_DIGITAL			 = 0x0003,
		PTC_TOTAL			 = 0x0004
	};
};

/////////////////////////////////////////////////////////////////////////////////////////
// CBinarySignedIntegerFormatter class template
/////////////////////////////////////////////////////////////////////////////////////////

template < class TCoreBase >
class CBinarySignedIntegerFormatter : public CIntegerFormatter,
									  protected TCoreBase,
									  protected CBinarySignedIntegerFormatterBase
{
// Types
protected:
	typedef typename TCoreBase::TCore TCore;

// Types
protected:
	typedef CBinarySignedIntegerDigitalPattern<TCoreBase, 1, false >
			CPositiveNumberPattern;

	typedef CBinarySignedIntegerDigitalPattern<TCoreBase, -1, false >
			CNegativeNumberPattern;

	typedef CBinarySignedIntegerDigitalPattern<TCoreBase, 0, true >
			CZeroPattern;

	typedef CIntegerNullPattern
			CNullPattern;

// Construction & destruction
protected:
	CBinarySignedIntegerFormatter(LCID lcid, WORD fTraits = TRAIT_NUMBER)
		: CIntegerFormatter(lcid, fTraits)
	{
	}	

	~CBinarySignedIntegerFormatter()
	{
	}

// Helpers: Common
protected:
	SIZE_T GetPatterns(const CNumericPattern** prgPatterns) const
	{
		ATLASSERT( !prgPatterns || 
				!::IsBadWritePtr(prgPatterns, PTC_TOTAL * sizeof(CNumericPattern*)) );

		if ( prgPatterns )
		{
			prgPatterns[0] = &m_patternPosNumber;
			prgPatterns[1] = &m_patternNegNumber;
			prgPatterns[2] = &m_patternZero;
			prgPatterns[3] = &m_patternNull;
		}

		return PTC_TOTAL;
	}

	SIZE_T GetPatterns(CNumericPattern** prgPatterns)
	{
		ATLASSERT( !prgPatterns || 
				!::IsBadWritePtr(prgPatterns, PTC_TOTAL * sizeof(CNumericPattern*)) );

		if ( prgPatterns )
		{
			prgPatterns[0] = &m_patternPosNumber;
			prgPatterns[1] = &m_patternNegNumber;
			prgPatterns[2] = &m_patternZero;
			prgPatterns[3] = &m_patternNull;
		}

		return PTC_TOTAL;
	}

// Helpers: Formatting and scanning
protected:
	const CNumericPattern& GetAppropriatePattern(const void* lpcValue) const
	{
		ATLASSERT( !lpcValue || !::IsBadReadPtr(lpcValue, sizeof(float)) );
		
		if ( lpcValue )
		{
			const TCore* pcVal = reinterpret_cast<const TCore*>(lpcValue);

			if ( *pcVal > 0 )
				return m_patternPosNumber;
			else if ( *pcVal < 0 )
				return m_patternNegNumber;
			else
				return m_patternZero;
		}
		else
		{
			return m_patternNull;
		}
	}

// Data members
protected:
	CPositiveNumberPattern	m_patternPosNumber;
	CNegativeNumberPattern	m_patternNegNumber;
	CZeroPattern			m_patternZero;
	CNullPattern			m_patternNull;
};

}; // namespace SP

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions