Click here to Skip to main content
15,896,557 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 75K   3.6K   36  
Masked numeric edit ActiveX control.
/////////////////////////////////////////////////////////////////////////////////////////
//	Project:		SP Numeric Edit Control 1.0
//
//	File:			SpNumericEdit.cpp		
//
//	Developer(s):	Sergei Pavlovsky
//					sergei_vp@hotmail.com
//					Copyright (c) 2004
//
//	Description:	Implementation of DLL Exports.
//
//	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.
/////////////////////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "SpNumericEditModule.h"
#include <vector>
#include "DsgnErrorReportDlg.h"

/////////////////////////////////////////////////////////////////////////////////////////
// CSpNumericEditModule class implementation
/////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////
// Constants

const UINT_PTR CSpNumericEditModule::ms_cchMaxResString = 128;

/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Error handling

BOOL CSpNumericEditModule::LoadTypeLib(ITypeLib** ppiTypeLib)
{
	ATLASSERT( ppiTypeLib );

	const DWORD cchInitialBuffer = _MAX_PATH;

	DWORD cchFileName;
	DWORD cchBuffer = 0;

	LPWSTR lpFileName = NULL;

	do
	{
		cchBuffer += cchInitialBuffer;

		void* lpBuffer = realloc(lpFileName, (cchBuffer + 1) * sizeof(WCHAR));
		ATLASSERT( lpBuffer );
		if ( !lpBuffer )
		{
			SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_CRT, 0, 
							 IDS_ELR_OUTOFMEMORY);
			free(lpFileName);
			return FALSE;
		}

		lpFileName = reinterpret_cast<LPWSTR>(lpBuffer);

		cchFileName = ::GetModuleFileNameW(_AtlBaseModule.GetResourceInstance(), lpFileName, cchBuffer);
	}
	while ( cchBuffer <= cchFileName );

	HRESULT hr = ::LoadTypeLib(lpFileName, ppiTypeLib);
	ATLASSERT( SUCCEEDED(hr) );
	free(lpFileName);
	if FAILED(hr)
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0, 
						 IDS_ERCM_LOADTYPELIBRARY);
		return FALSE;
	}

	return TRUE;
}

BOOL CSpNumericEditModule::GetValueTypesTypeInfo(ITypeLib* piTypeLib, 
												 ITypeInfo** ppiTypeInfo)
{
	ATLASSERT( piTypeLib );
	ATLASSERT( !::IsBadWritePtr(ppiTypeInfo, sizeof(ITypeInfo*)) );

	LPCWSTR lpcszTypeID = L"{EC31DA3A-C3C2-47fc-95C4-DA1EF188DCA9}";

	// Get ITypeInfo for the ValueTypeConstants enum
	GUID guid;
	HRESULT hr = IIDFromString((LPOLESTR)lpcszTypeID, &guid);
	ATLASSERT( SUCCEEDED(hr) );
	if ( FAILED(hr) )
	{		
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0, 
						 IDS_ERCM_IIDFROMSTRING);

		return FALSE;
	}

	hr = piTypeLib->GetTypeInfoOfGuid(guid, ppiTypeInfo);
	ATLASSERT( SUCCEEDED(hr) );
	if ( FAILED(hr) )
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0, 
						 IDS_ERCM_GETTYPEINFOBYID);		
		return FALSE;
	}

	return TRUE;
}

BOOL CSpNumericEditModule::GetFormatTypesTypeInfo(ITypeLib* piTypeLib, 
												  ITypeInfo** ppiTypeInfo)
{
	ATLASSERT( piTypeLib );
	ATLASSERT( !::IsBadWritePtr(ppiTypeInfo, sizeof(ITypeInfo*)) );

	LPCWSTR lpcszTypeID = L"{6F72E8CE-CA24-4178-A188-28023968B96D}";

	// Get ITypeInfo for the FormatTypeConstants enum
	GUID guid;
	HRESULT hr = IIDFromString((LPOLESTR)lpcszTypeID, &guid);
	ATLASSERT( SUCCEEDED(hr) );
	if ( FAILED(hr) )
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0, 
						 IDS_ERCM_IIDFROMSTRING);
		return FALSE;
	}

	hr = piTypeLib->GetTypeInfoOfGuid(guid, ppiTypeInfo);
	ATLASSERT( SUCCEEDED(hr) );
	if ( FAILED(hr) )
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0, 
						 IDS_ERCM_GETTYPEINFOBYID);		
		return FALSE;
	}

	return TRUE;
}

BOOL CSpNumericEditModule::GetFormatPropertiesTypeInfo(ITypeLib* piTypeLib, 
													   ITypeInfo** ppiTypeInfo)
{
	ATLASSERT( piTypeLib );
	ATLASSERT( !::IsBadWritePtr(ppiTypeInfo, sizeof(ITypeInfo*)) );

	LPCWSTR lpcszTypeID = L"{603D0A62-22C4-4ec5-ACD6-2AA4E254840E}";

	// Get ITypeInfo for the FormatPropertyConstants enum
	GUID guid;
	HRESULT hr = IIDFromString((LPOLESTR)lpcszTypeID, &guid);
	ATLASSERT( SUCCEEDED(hr) );
	if ( FAILED(hr) )
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0, 
						 IDS_ERCM_IIDFROMSTRING);
		return FALSE;
	}

	hr = piTypeLib->GetTypeInfoOfGuid(guid, ppiTypeInfo);
	ATLASSERT( SUCCEEDED(hr) );
	if ( FAILED(hr) )
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0, 
						 IDS_ERCM_GETTYPEINFOBYID);		
		return FALSE;
	}

	return TRUE;
}

BOOL CSpNumericEditModule::ConvertEnumValueName(ITypeInfo* piTypeInfo, 
												LPCOLESTR lpszName, 
												LONG* plValue)
{
	ATLASSERT( piTypeInfo );
	ATLASSERT( !::IsBadWritePtr(plValue, sizeof(LONG)) );

	*plValue = 0;

	// Define number of constants in the enum
	TYPEATTR* pta;
	HRESULT hr = piTypeInfo->GetTypeAttr(&pta);
	ATLASSERT( SUCCEEDED(hr) );
	if ( FAILED(hr) )
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0, 
						 IDS_ERCM_GETTYPEINFORMATIONATTRIBUTE);		
		return FALSE;
	}

	WORD cVars = pta->cVars;

	piTypeInfo->ReleaseTypeAttr(pta);

	// Add constants names and values to the combobox
	for ( WORD i = 0; i < cVars; i++ )
	{
		VARDESC* pvd = NULL;
		hr = piTypeInfo->GetVarDesc(i, &pvd);
		ATLASSERT( SUCCEEDED(hr) );
		if ( FAILED(hr) )
		{
			SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0, 
							 IDS_ERCM_GETTYPEINFORMATIONVAR);
			return FALSE;
		}

		LONG lCurrValue = pvd->lpvarValue->lVal;
		MEMBERID memid = pvd->memid;

		piTypeInfo->ReleaseVarDesc(pvd);

		CComBSTR cbsCurrName;
		hr = piTypeInfo->GetDocumentation(memid, &cbsCurrName, NULL, NULL, NULL);
		ATLASSERT( SUCCEEDED(hr) );		
		if ( FAILED(hr) )
		{
			SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0, 
							 IDS_ERCM_GETTYPEINFORMATIONDOC);
			return FALSE;
		}

		if ( cbsCurrName == lpszName )
		{
			*plValue = lCurrValue;
			break;
		}
	}

	if ( i == cVars )
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0, 
						 IDS_ERCM_FINDTYPEINFORMATIONVALUE);
		return FALSE;
	}

	return TRUE;
}

BOOL CSpNumericEditModule::ConvertEnumValueName(ITypeInfo* piTypeInfo, LONG lValue,
												BSTR* pbsName)
{
	ATLASSERT( piTypeInfo );
	ATLASSERT( !::IsBadWritePtr(pbsName, sizeof(BSTR)) );

	*pbsName = NULL;

	// Define number of constants in the enum
	TYPEATTR* pta;
	HRESULT hr = piTypeInfo->GetTypeAttr(&pta);
	ATLASSERT( SUCCEEDED(hr) );
	if ( FAILED(hr) )
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0, 
						 IDS_ERCM_GETTYPEINFORMATIONATTRIBUTE);		
		return FALSE;
	}

	WORD cVars = pta->cVars;

	piTypeInfo->ReleaseTypeAttr(pta);

	// Add constants names and values to the combobox
	for ( WORD i = 0; i < cVars; i++ )
	{
		VARDESC* pvd = NULL;
		hr = piTypeInfo->GetVarDesc(i, &pvd);
		ATLASSERT( SUCCEEDED(hr) );
		if ( FAILED(hr) )
		{
			SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0, 
							 IDS_ERCM_GETTYPEINFORMATIONVAR);
			return FALSE;
		}

		MEMBERID memid = pvd->memid;
		LONG lCurrValue = pvd->lpvarValue->lVal;

		piTypeInfo->ReleaseVarDesc(pvd);

		if ( lValue == lCurrValue )
		{
			hr = piTypeInfo->GetDocumentation(memid, pbsName, NULL, NULL, NULL);
			ATLASSERT( SUCCEEDED(hr) );		
			if ( FAILED(hr) )
			{
				SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0, 
								 IDS_ERCM_GETTYPEINFORMATIONDOC);
				return FALSE;
			}
			break;
		}
	}

	if ( i == cVars )
	{
		SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0, 
						 IDS_ERCM_FINDTYPEINFORMATIONVALUE);
		return FALSE;
	}

	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Resources

UINT_PTR CSpNumericEditModule::LoadString(UINT unID, LPTSTR lpszBuffer, 
										  UINT_PTR cchBuffer)
{
	ATLASSERT( !::IsBadWritePtr(lpszBuffer, sizeof(TCHAR) * cchBuffer) );

	if ( lpszBuffer )
	{
		return ::LoadString(_AtlBaseModule.GetResourceInstance(), unID, 
							lpszBuffer, (int)cchBuffer);
	}
	else
	{
		UINT_PTR cchString;
		UINT_PTR cchBuffer = 0;

		__try
		{
			do
			{
				cchBuffer += ms_cchMaxResString;

				void* lpBuf = realloc(lpszBuffer, (cchBuffer + 1) * sizeof(TCHAR));
				ATLASSERT( lpBuf );
				if ( !lpBuf )
				{
					SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_CRT, 0, 
									 IDS_ELR_OUTOFMEMORY);
					return 0;
				}

				lpszBuffer = reinterpret_cast<LPTSTR>(lpBuf);

				cchString = ::LoadString(_AtlBaseModule.GetResourceInstance(), unID,
										 lpszBuffer, int(cchBuffer + 1));
			}
			while ( cchBuffer <= cchString );
		}
		__finally
		{
			free(lpszBuffer);
		}

		return cchString;
	}
}

LPCTSTR CSpNumericEditModule::LoadString(UINT unID, CTCharVector& vecBuffer)
{
	if ( !unID )
		return NULL;

	UINT_PTR cchText = LoadString(unID, NULL, 0);

	vecBuffer.resize(cchText + 1);
	ATLASSERT( vecBuffer.size() == cchText + 1 );
	if ( vecBuffer.size() < cchText + 1 )
		return NULL;

	LPTSTR lpszText = &vecBuffer.front();

	LoadString(unID, lpszText, cchText + 1);

	vecBuffer[cchText] = _T('\x0');

	return lpszText;
}

/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Error history

void CSpNumericEditModule::LogErrorInfo(LPCTSTR lpcszSource, DWORD dwCode, 
										LPCTSTR lpcszReason, LPCTSTR lpcszDetails,
										DWORD dwHelpContext, 
										LPCTSTR lpcszHelpFile)
{
//	DWORD dwHelpContext = 0, 
//	LPCTSTR lpcszHelpFile = NULL

	m_ejLast.LogEntry(lpcszSource, dwCode, lpcszReason, lpcszDetails,
					  dwHelpContext, lpcszHelpFile);
}

void CSpNumericEditModule::SetLastErrorInfo(LPCTSTR lpcszSource, DWORD dwCode, 
											LPCTSTR lpcszReason, LPCTSTR lpcszDetails,
											DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
	// Set Source
	if ( lpcszSource )
		m_eiLast.SetSource(lpcszSource, _tcslen(lpcszSource));
	else
		m_eiLast.SetSource(_T(""), 0);

	// Set Code
	m_eiLast.SetCode(dwCode);

	// Set Reason
	if ( lpcszReason )
		m_eiLast.SetReason(lpcszReason, _tcslen(lpcszReason));		
	else
		m_eiLast.SetReason(_T(""), 0);
		
	// Set Details
	if ( lpcszDetails )		
		m_eiLast.SetDetails(lpcszDetails, _tcslen(lpcszDetails));
	else
		m_eiLast.SetDetails(_T(""), 0);
		
	// Set HelpContext
	m_eiLast.SetHelpContext(dwHelpContext);

	// Set HelpFile
	if ( lpcszHelpFile )
		m_eiLast.SetHelpFile(lpcszHelpFile, _tcslen(lpcszHelpFile));		
	else
		m_eiLast.SetHelpFile(_T(""), 0);
}

void CSpNumericEditModule::AddReasonToLastError(LPCTSTR lpcszReason)
{
	if ( lpcszReason )
		m_eiLast.AddReason(lpcszReason, _tcslen(lpcszReason));
}

void CSpNumericEditModule::AttachReportedLog()
{
	ATLASSERT( m_ejLast.IsEmpty() );

	m_ejLast.Swap(m_ejReported);
}

HRESULT CSpNumericEditModule::ExportReportedLog(IErrorLog* piLog)
{
	ATLASSERT( piLog );

	UINT_PTR i = m_ejReported.GetEntriesCount();

	while ( i-- )
	{
		const SP::CSMErrorInfo& eiSrc = m_ejReported.GetEntryAt(i);

		CComExcepInfo eiDst;
		eiDst.wCode = static_cast<WORD>(eiSrc.GetCode());
		eiDst.wReserved = 0;
		eiDst.bstrSource = ::SysAllocString(CT2OLE(eiSrc.GetSource()));
		eiDst.bstrDescription = ::SysAllocString(CT2OLE(eiSrc.GetReason()));
		eiDst.bstrHelpFile = ::SysAllocString(CT2OLE(eiSrc.GetHelpFile()));
		eiDst.dwHelpContext = eiSrc.GetHelpContext();
		eiDst.pvReserved = NULL;

		HRESULT hr = piLog->AddError(L"Formatter", &eiDst);
		ATLASSERT( SUCCEEDED(hr) );
		if FAILED(hr)
			return E_FAIL;
	}

	return S_OK;
}

/////////////////////////////////////////////////////////////////////////////////////////
// Helpers: Error report

UINT_PTR CSpNumericEditModule::BuildErrorInfoReport(const SP::CSMErrorInfo& entry, 
													LPTSTR lpszBuffer, UINT_PTR cchBuffer)
{
	ATLASSERT( !::IsBadWritePtr(lpszBuffer, cchBuffer * sizeof(TCHAR)) );

	const TCHAR szLF[] = _T("\r\n");
	const UINT_PTR cchLF = sizeof(szLF)/sizeof(TCHAR) - 1;

	UINT_PTR cchResult = 0;	

	// Source
	LPCTSTR lpcszSource = entry.GetSource();

	if ( lpcszSource && *lpcszSource )
	{
		TCHAR szTitle[128];
		_AtlModule.LoadString(IDS_ERRORINFOSOURCE, szTitle, 128);

		LPCTSTR lpcszTitle = szTitle;

		UINT_PTR cchSource = _tcslen(lpcszSource);

		if ( lpszBuffer && *lpcszTitle )
		{
			while ( cchBuffer && *lpcszTitle )
			{
				*lpszBuffer++ = *lpcszTitle++;

				cchBuffer--;
				cchResult++;
			}

			while ( cchBuffer && *lpcszSource )
			{
				*lpszBuffer++ = *lpcszSource++;

				cchBuffer--;
				cchResult++;
			}

			for ( UINT_PTR i = 0; i < cchLF && cchBuffer; i++ )
			{
				*lpszBuffer++ = szLF[i];

				cchBuffer--;
				cchResult++;
			}			
		}
		else
		{
			cchResult += _tcslen(lpcszTitle) + cchSource + cchLF;			
		}
	}

	// Reason
	LPCTSTR lpcszReason = entry.GetReason();

	if ( lpcszReason && *lpcszReason )
	{
		TCHAR szTitle[128];
		_AtlModule.LoadString(IDS_ERRORINFOREASON, szTitle, 128);

		LPCTSTR lpcszTitle = szTitle;

		UINT_PTR cchReason = _tcslen(lpcszReason);

		if ( lpszBuffer && *lpcszTitle )
		{
			while ( cchBuffer && *lpcszTitle )
			{
				*lpszBuffer++ = *lpcszTitle++;

				cchBuffer--;
				cchResult++;
			}

			while ( cchBuffer && *lpcszReason )
			{
				*lpszBuffer++ = *lpcszReason++;

				cchBuffer--;
				cchResult++;
			}

			for ( UINT_PTR i = 0; i < cchLF && cchBuffer; i++ )
			{
				*lpszBuffer++ = szLF[i];

				cchBuffer--;
				cchResult++;
			}			

		}
		else
		{
			cchResult += _tcslen(lpcszTitle) + cchReason + cchLF;			
		}
	}

	// Details
	LPCTSTR lpcszDetails = entry.GetDetails();

	if ( lpcszDetails && *lpcszDetails )
	{
		TCHAR szTitle[128];
		_AtlModule.LoadString(IDS_ERRORINFODETAILS, szTitle, 128);

		LPCTSTR lpcszTitle = szTitle;

		UINT_PTR cchDetails = _tcslen(lpcszDetails);

		if ( lpszBuffer && *lpcszTitle )
		{
			while ( cchBuffer )
			{
				*lpszBuffer++ = *lpcszTitle++;

				cchBuffer--;
				cchResult++;
			}

			while ( cchBuffer && *lpcszDetails )
			{
				*lpszBuffer++ = *lpcszDetails++;

				cchBuffer--;
				cchResult++;
			}

			for ( UINT_PTR i = 0; i < cchLF && cchBuffer; i++ )
			{
				*lpszBuffer++ = szLF[i];

				cchBuffer--;
				cchResult++;
			}			
		}
		else
		{
			cchResult += _tcslen(lpcszTitle) + cchDetails + cchLF;			
		}
	}

	return cchResult;
}

UINT_PTR CSpNumericEditModule::BuildErrorLogReport(const SP::CSMErrorJournal ej, 
												   LPTSTR lpszBuffer, 
												   UINT_PTR cchBuffer)
{
	ATLASSERT( !::IsBadWritePtr(lpszBuffer, cchBuffer * sizeof(TCHAR)) );

	const TCHAR szLF[] = _T("\r\n");
	const UINT_PTR cchLF = sizeof(szLF)/sizeof(TCHAR) - 1;

	UINT_PTR cchResult = 0;

	for ( UINT_PTR i = 0; i < ej.GetCount(); i++ )
	{
		const SP::CSMErrorInfo& entry = ej.GetEntryAt(i);

		UINT_PTR cchWritten = BuildErrorInfoReport(entry, lpszBuffer, cchBuffer);

		if (  cchWritten )
		{
			if ( lpszBuffer )
			{
				lpszBuffer += cchWritten;

				for ( UINT_PTR i = 0; i < cchLF && cchBuffer; i++ )
				{
					*lpszBuffer++ = szLF[i];

					cchBuffer--;
					cchResult++;
				}			
			}
			else
			{
				cchResult += cchWritten + cchLF;
			}
		}
	}

	return cchResult;
}

void CSpNumericEditModule::ReportComError(const CLSID& clsid, LPCSTR lpszDesc, 
										  const IID& iid, HRESULT hRes)
{
	AtlReportError(clsid, lpszDesc, iid, hRes);
}

void CSpNumericEditModule::ReportComError(const CLSID& clsid, LPCSTR lpszDesc, 
										  DWORD dwHelpID, LPCSTR lpszHelpFile, 
										  const IID& iid, HRESULT hRes)
{
	AtlReportError(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes);
}

void CSpNumericEditModule::ReportComError(const CLSID& clsid, LPCOLESTR lpszDesc, 
										  const IID& iid, HRESULT hRes)
{
	AtlReportError(clsid, lpszDesc, iid, hRes);
}

void CSpNumericEditModule::ReportComError(const CLSID& clsid, LPCOLESTR lpszDesc, 
										  DWORD dwHelpID, LPCOLESTR lpszHelpFile, 
										  const IID& iid, HRESULT hRes)
{
	AtlReportError(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes);
}

void CSpNumericEditModule::ReportComError(const CLSID& clsid, UINT nID, const IID& iid,
										  HRESULT hRes)
{
	AtlReportError(clsid, nID, iid, hRes, _AtlBaseModule.GetResourceInstance());
}

void CSpNumericEditModule::ReportComError(const CLSID& clsid, UINT nID, DWORD dwHelpID,
										  LPCOLESTR lpszHelpFile, const IID& iid, 
										  HRESULT hRes)
{
	AtlReportError(clsid, nID, dwHelpID, lpszHelpFile, iid, hRes, 
				   _AtlBaseModule.GetResourceInstance());
}

/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Error report

void CSpNumericEditModule::ReportLastErrorWithCom(const CLSID& clsid, const IID& iid, 
												  HRESULT hRes)
{
	// Put current error journal entries to the report journal
	m_ejReported.Clear();
	m_ejLast.Swap(m_ejReported);

	ReportComError(clsid, CT2OLE(m_eiLast.GetReason()), iid, hRes);

	m_eiLast.Clear();
}

void CSpNumericEditModule::ReportLastErrorWithDlg(HWND hWnd)
{
	// Put current error journal entries to the report journal
	m_ejReported.Clear();
	m_ejLast.Swap(m_ejReported);

	// Get Log report
	UINT_PTR cchLog = BuildErrorLogReport(m_ejReported, NULL, 0);
	CTCharVector vecLog(cchLog + 1);
	LPTSTR lpszLog = &vecLog.front();

	BuildErrorLogReport(m_ejReported, lpszLog, cchLog);
	lpszLog[cchLog] = _T('\x0');

	// Get Caption
	UINT_PTR cchCaption = LoadString(IDS_ERROR, NULL, 0);
	CTCharVector vecCaption(cchLog + 1);
	LPTSTR lpszCaption = &vecCaption.front();
	LoadString(IDS_ERROR, lpszCaption, cchCaption + 1);
	lpszCaption[cchCaption] = _T('\x0');

	CDsgnErrorReportDlg	dlg;

	dlg.DoModal(lpszCaption, m_eiLast.GetReason(), lpszLog);

	m_eiLast.Clear();
}

INT_PTR CSpNumericEditModule::ReportLastErrorWithDlgEx(HWND hWnd, UINT fDlgParams,
													   LPCTSTR lpcszCaption, 
													   LPCTSTR lpcszAddMsg)
{
	const TCHAR szLF[] = _T("\r\n");
	const UINT_PTR cchLF = sizeof(szLF)/sizeof(TCHAR) - 1;

	// Put current error journal entries to the report journal
	m_ejReported.Clear();
	m_ejLast.Swap(m_ejReported);

	// Form message
	CTCharVector vecMsg;
	LPCTSTR lpcszMsg;

	if ( lpcszAddMsg )
	{
		LPCTSTR lpcszReason = m_eiLast.GetReason();

		if ( lpcszReason && *lpcszReason )
		{
			const UINT_PTR cchRsn = m_eiLast.GetReason(NULL, 0);
			const UINT_PTR cchAddRsn = _tcslen(lpcszAddMsg);
			const UINT_PTR cchMsg = cchRsn + cchAddRsn +  cchLF + 1;

			vecMsg.resize(cchMsg);

			LPTSTR lpszMsg = &vecMsg.front();

			m_eiLast.GetReason(lpszMsg, cchRsn);
			lpszMsg[cchRsn] = _T('\x0');

			_tcscpy(lpszMsg + cchRsn, szLF);
			_tcscpy(lpszMsg + cchRsn + cchLF, lpcszAddMsg);

			lpcszMsg = lpszMsg;
		}
		else
		{
			lpcszMsg = lpcszAddMsg;
		}
	}
	else
	{
		lpcszMsg = m_eiLast.GetReason();
	}
	
	// Form Log report
	UINT_PTR cchLog = BuildErrorLogReport(m_ejReported, NULL, 0);
	CTCharVector vecLog(cchLog + 1);
	LPTSTR lpszLog = &vecLog.front();

	BuildErrorLogReport(m_ejReported, lpszLog, cchLog);
	lpszLog[cchLog] = _T('\x0');

	CDsgnErrorReportDlg	dlg;

	INT_PTR nResult = dlg.DoModal(lpcszCaption, lpcszMsg, lpszLog, fDlgParams);

	m_eiLast.Clear();

	return nResult;
}

/////////////////////////////////////////////////////////////////////////////////////////
// Global routines: Error information managing
/////////////////////////////////////////////////////////////////////////////////////////

UINT_PTR SP::LoadErrorString(UINT unID, LPTSTR lpszBuffer, UINT_PTR cchBuffer)

{
	return _AtlModule.LoadString(unID, lpszBuffer, cchBuffer);
}

void SP::AccountError(DWORD fOptions, LPCTSTR lpcszSource, DWORD dwCode, 
					  LPCTSTR lpcszReason, LPCTSTR lpcszDetails, 
					  DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
	if ( fOptions & SP::AE_LOG )
		_AtlModule.LogErrorInfo(lpcszSource, dwCode, lpcszReason, lpcszDetails, 
								dwHelpContext, lpcszHelpFile);

	if ( fOptions & SP::AE_SETLOG )
		_AtlModule.AttachReportedLog();

	switch ( fOptions & AEM_MSG )
	{
	case SP::AE_SETMSG:
		_AtlModule.SetLastErrorInfo(lpcszSource, dwCode, lpcszReason, lpcszDetails, 
									dwHelpContext, lpcszHelpFile);
		break;

	case SP::AE_ADDMSG:
		_AtlModule.AddReasonToLastError(lpcszReason);
		break;		
	}
}

void SP::AccountError(DWORD fOptions, UINT unSource, DWORD dwCode, 
					  UINT unReason, UINT unDetails, 
					  DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
	CTCharVector vecSource, vecReason, vecDetails;

	LPCTSTR lpcszSource = _AtlModule.LoadString(unSource, vecSource);
	LPCTSTR lpcszReason = _AtlModule.LoadString(unReason, vecReason);
	LPCTSTR lpcszDetails = _AtlModule.LoadString(unDetails, vecDetails);

	SP::AccountError(fOptions, lpcszSource, dwCode, lpcszReason, lpcszDetails, 
					 dwHelpContext, lpcszHelpFile);
}


void SP::AccountComError(DWORD fOptions, DWORD dwCode, HRESULT hRes, 
						 IUnknown* piSrc, REFIID riid)
{
	ATLASSERT( piSrc );

	CComPtr<ISupportErrorInfo> spiSEI;
	HRESULT hr = piSrc->QueryInterface(IID_ISupportErrorInfo, (void**)&spiSEI);
	if FAILED(hr)
		return;

	hr = spiSEI->InterfaceSupportsErrorInfo(riid);
	if ( hr != S_OK ) 
		return;

	CComPtr<IErrorInfo> spiEI;
	hr = ::GetErrorInfo(0, &spiEI);
	ATLASSERT( SUCCEEDED(hr) );
	if FAILED(hr)
		return;

	// Set Source
	CComBSTR cbsSource;
	hr = spiEI->GetSource(&cbsSource);
	ATLASSERT( SUCCEEDED(hr) );

	// Get Reason
	CComBSTR cbsReason;
	hr = spiEI->GetDescription(&cbsReason);
	ATLASSERT( SUCCEEDED(hr) );

	// Get HelpContext
	DWORD dwHelpContext;
	hr = spiEI->GetHelpContext(&dwHelpContext);
	ATLASSERT( SUCCEEDED(hr) );

	// Get HelpFile
	CComBSTR cbsHelpFile;
	hr = spiEI->GetHelpFile(&cbsHelpFile);
	ATLASSERT( SUCCEEDED(hr) );

	SP::AccountError(fOptions, COLE2T(cbsSource), dwCode, COLE2T(cbsReason), NULL, 
					 dwHelpContext, COLE2T(cbsHelpFile));
}


void SP::ReportErrorWithCom(DWORD fOptions, const CLSID& clsid, const IID& iid, 
							HRESULT hRes, LPCTSTR lpcszSource, DWORD dwCode, 
							LPCTSTR lpcszReason, LPCTSTR lpcszDetails, 
							DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
	SP::AccountError(fOptions, lpcszSource, dwCode, lpcszReason, lpcszDetails, 
					 dwHelpContext, lpcszHelpFile);

	_AtlModule.ReportLastErrorWithCom(clsid, iid, hRes);
}

void SP::ReportErrorWithCom(DWORD fOptions, const CLSID& clsid, const IID& iid, 
							HRESULT hRes, UINT unSource, DWORD dwCode, 
							UINT unReason, UINT unDetails, 
							DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
	SP::AccountError(fOptions, unSource, dwCode, unReason, unDetails, 
					 dwHelpContext, lpcszHelpFile);

	_AtlModule.ReportLastErrorWithCom(clsid, iid, hRes);
}


void SP::ReportErrorWithDlg(DWORD fOptions, HWND hwndParent, 
							LPCTSTR lpcszSource, DWORD dwCode, LPCTSTR lpcszReason, 
							LPCTSTR lpcszDetails, 
							DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
	SP::AccountError(fOptions, lpcszSource, dwCode, lpcszReason, lpcszDetails, 
					 dwHelpContext, lpcszHelpFile);

	_AtlModule.ReportLastErrorWithDlg(hwndParent);
}

void SP::ReportErrorWithDlg(DWORD fOptions, HWND hwndParent, 
							UINT unSource, DWORD dwCode, UINT unReason, UINT unDetails, 
							DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
	SP::AccountError(fOptions, unSource, dwCode, unReason, unDetails, 
					 dwHelpContext, lpcszHelpFile);

	_AtlModule.ReportLastErrorWithDlg(hwndParent);
}


INT_PTR SP::ReportErrorWithDlgEx(DWORD fOptions, HWND hwndParent, UINT fDlgParams,
								 LPCTSTR lpcszCaption, LPCTSTR lpcszAddMsg, 
								 LPCTSTR lpcszSource, DWORD dwCode, LPCTSTR lpcszReason, 
								 LPCTSTR lpcszDetails, 
								 DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
	SP::AccountError(fOptions, lpcszSource, dwCode, lpcszReason, lpcszDetails, 
					 dwHelpContext, lpcszHelpFile);

	return _AtlModule.ReportLastErrorWithDlgEx(hwndParent, fDlgParams, lpcszCaption, 
											   lpcszAddMsg);
}

INT_PTR SP::ReportErrorWithDlgEx(DWORD fOptions, HWND hwndParent, UINT fDlgParams,
								 UINT unCaption, UINT unAddMsg, 
								 UINT unSource, DWORD dwCode, 
								 UINT unReason, UINT unDetails, 
								 DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
	CTCharVector vecCaption, vecAddMsg, vecSource, vecReason, vecDetails;

	LPCTSTR lpcszCaption = _AtlModule.LoadString(unCaption, vecCaption);
	LPCTSTR lpcszAddMsg = _AtlModule.LoadString(unAddMsg, vecAddMsg);
	LPCTSTR lpcszSource = _AtlModule.LoadString(unSource, vecSource);
	LPCTSTR lpcszReason = _AtlModule.LoadString(unReason, vecReason);
	LPCTSTR lpcszDetails = _AtlModule.LoadString(unDetails, vecDetails);

	return SP::ReportErrorWithDlgEx(fOptions, hwndParent, fDlgParams,
									lpcszCaption, lpcszAddMsg, 
									lpcszSource, dwCode, lpcszReason, lpcszDetails, 
									dwHelpContext, lpcszHelpFile);
}


/////////////////////////////////////////////////////////////////////////////////////////
// Global format designer's utilities
/////////////////////////////////////////////////////////////////////////////////////////

HRESULT __stdcall SpDfGetErrors(IErrorLog* piLog)
{
	if ( !piLog )
		return E_INVALIDARG;

	return _AtlModule.ExportReportedLog(piLog);
}

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