Click here to Skip to main content
15,885,278 members
Articles / Desktop Programming / ATL

Win32 Dialog Helpers

Rate me:
Please Sign up or sign in to vote.
4.94/5 (38 votes)
18 Apr 200311 min read 274K   3.1K   79  
Easy support for dialog resizing and ActiveX controls
This article provides a few samples to enable features in WIN32 dialogs such as support for dialog resizing and ActiveX controls. VC++6 / VC++7.x projects are provided.
#pragma once

/////////////////////////////////////////////////////////////////////////////////////
//
// collection templates
//
// taken from the Windows MFC
// templated
//
//
//


template <class T>
class CTemplateArray
{

public:

// Construction
	CTemplateArray();
	~CTemplateArray();

// Attributes
	int		GetSize() const;
	int		GetUpperBound() const;
	void	SetSize(int nNewSize, int nGrowBy = -1);

// Operations
	// Clean up
	void	FreeExtra();
	void	RemoveAll();

	// Accessing elements
	T		GetAt(int nIndex) const;
	void	SetAt(int nIndex, T newElement);
	T&		ElementAt(int nIndex);

	// Direct Access to the element data (may return NULL)
	const T* GetData() const;
	T*		 GetData();

	// Potentially growing the array
	void	SetAtGrow(int nIndex, T newElement);
	int		Add(T newElement);
	int		Append(const CTemplateArray& src);
	void	Copy(const CTemplateArray& src);

	// overloaded operator helpers
	T		operator[](int nIndex) const;
	T&		operator[](int nIndex);

	// Operations that move elements around
	void	InsertAt(int nIndex, T newElement, int nCount = 1);
	void	RemoveAt(int nIndex, int nCount = 1);
	void	InsertAt(int nStartIndex, CTemplateArray* pNewArray);
	void	Remove(T oldElement);

// Implementation
protected:
	T*  m_pData;   // the actual array of data
	int m_nSize;     // # of elements (upperBound - 1)
	int m_nMaxSize;  // max allocated
	int m_nGrowBy;   // grow amount

protected:
	// local typedefs for class templates
	typedef void* BASE_TYPE;
	typedef void* BASE_ARG_TYPE;
};



template <class T> CTemplateArray<T>::CTemplateArray()
{
	m_pData = NULL;
	m_nSize = m_nMaxSize = m_nGrowBy = 0;
}

template <class T> CTemplateArray<T>::~CTemplateArray()
{
	delete[] (BYTE*)m_pData;
}

template <class T> int CTemplateArray<T>::GetSize() const
{ 
	return m_nSize; 
}

template <class T> int CTemplateArray<T>::GetUpperBound() const
{ 
	return m_nSize-1; 
}

template <class T> void CTemplateArray<T>::SetSize(int nNewSize, int nGrowBy)
{
	if (nNewSize < 0)
		return;

	if (nGrowBy != -1)
		m_nGrowBy = nGrowBy;  // set new size

	if (nNewSize == 0)
	{
		// shrink to nothing
		delete[] (BYTE*)m_pData;
		m_pData = NULL;
		m_nSize = m_nMaxSize = 0;
	}
	else if (m_pData == NULL)
	{
		// create one with exact size
		m_pData = (T*) new BYTE[nNewSize * sizeof(T)];

		memset(m_pData, 0, nNewSize * sizeof(T));  // zero fill

		m_nSize = m_nMaxSize = nNewSize;
	}
	else if (nNewSize <= m_nMaxSize)
	{
		// it fits
		if (nNewSize > m_nSize)
		{
			// initialize the new elements

			memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(T));

		}

		m_nSize = nNewSize;
	}
	else
	{
		// otherwise, grow array
		int nGrowBy = m_nGrowBy;
		if (nGrowBy == 0)
		{
			// heuristically determine growth when nGrowBy == 0
			//  (this avoids heap fragmentation in many situations)
			nGrowBy = (m_nSize/8 > 4)? m_nSize/8 : 4;
		}
		int nNewMax;
		if (nNewSize < m_nMaxSize + nGrowBy)
			nNewMax = m_nMaxSize + nGrowBy;  // granularity
		else
			nNewMax = nNewSize;  // no slush

		T* pNewData = (T*) new BYTE[nNewMax * sizeof(T)];

		// copy new data from old
		memcpy(pNewData, m_pData, m_nSize * sizeof(T));

		memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(T));


		// get rid of old stuff (note: no destructors called)
		delete[] (BYTE*)m_pData;
		m_pData = pNewData;
		m_nSize = nNewSize;
		m_nMaxSize = nNewMax;
	}
}

template <class T> void CTemplateArray<T>::FreeExtra()
{
	if (m_nSize != m_nMaxSize)
	{
		// shrink to desired size
		T* pNewData = NULL;
		if (m_nSize != 0)
		{
			pNewData = (T*) new BYTE[m_nSize * sizeof(T)];
			// copy new data from old
			memcpy(pNewData, m_pData, m_nSize * sizeof(T));
		}

		// get rid of old stuff (note: no destructors called)
		delete[] (BYTE*)m_pData;
		m_pData = pNewData;
		m_nMaxSize = m_nSize;
	}
}

template <class T> void CTemplateArray<T>::RemoveAll()
{ 
	SetSize(0); 
}

template <class T> T CTemplateArray<T>::GetAt(int nIndex) const
{ 
	if (nIndex<0 || nIndex>=m_nSize)
		return NULL;
	else
		return m_pData[nIndex]; 
}

template <class T> void CTemplateArray<T>::SetAt(int nIndex, T newElement)
{ 
	if (nIndex >= 0 && nIndex < m_nSize)
		m_pData[nIndex] = newElement; 
}

template <class T> T& CTemplateArray<T>::ElementAt(int nIndex)
{ 
	static T pVoid=NULL;

	if (nIndex<0 || nIndex>=m_nSize)
		return pVoid;
	else
		return m_pData[nIndex]; 
}

template <class T> const T* CTemplateArray<T>::GetData() const
{ 
	return (const T*)m_pData; 
}

template <class T> T* CTemplateArray<T>::GetData()
{ 
	return (T*)m_pData; 
}

template <class T> void CTemplateArray<T>::SetAtGrow(int nIndex, T newElement)
{
	if (nIndex < 0)
		return;

	if (nIndex >= m_nSize)
		SetSize(nIndex+1);
	m_pData[nIndex] = newElement;
}

template <class T> int CTemplateArray<T>::Add(T newElement)
{ 
	int nIndex = m_nSize;
	SetAtGrow(nIndex, newElement);
	return nIndex; 
}

template <class T> void CTemplateArray<T>::Remove(T oldElement)
{ 
	for( int i = 0; i < m_nSize; i++)
	{
		if( m_pData[i] == oldElement)
		{
			if( i < m_nSize - 1)
				m_pData[i] = m_pData[i+1];
			m_nSize--;
			return;
		}
	}
}

template <class T> int CTemplateArray<T>::Append(const CTemplateArray& src)
{
	int nOldSize = m_nSize;
	
	if (this != &src)
	{
		SetSize(m_nSize + src.m_nSize);

		memcpy(m_pData + nOldSize, src.m_pData, src.m_nSize * sizeof(T));
	}
	return nOldSize;
}

template <class T> void CTemplateArray<T>::Copy(const CTemplateArray& src)
{
	if (this == &src)
		return;

	SetSize(src.m_nSize);

	memcpy(m_pData, src.m_pData, src.m_nSize * sizeof(T));

}

template <class T> T CTemplateArray<T>::operator[](int nIndex) const
{ 
	return GetAt(nIndex); 
}

template <class T> T& CTemplateArray<T>::operator[](int nIndex)
{ 
	return ElementAt(nIndex); 
}


template <class T> void CTemplateArray<T>::InsertAt(int nIndex, T newElement, int nCount)
{
	if (nIndex<0 || nCount<=0)
		return;

	if (nIndex >= m_nSize)
	{
		// adding after the end of the array
		SetSize(nIndex + nCount);  // grow so nIndex is valid
	}
	else
	{
		// inserting in the middle of the array
		int nOldSize = m_nSize;
		SetSize(m_nSize + nCount);  // grow it to new size
		// shift old data up to fill gap
		memmove(&m_pData[nIndex+nCount], &m_pData[nIndex],
			(nOldSize-nIndex) * sizeof(T));

		// re-init slots we copied from

		memset(&m_pData[nIndex], 0, nCount * sizeof(T));

	}

	// insert new value in the gap
	while (nCount-- && (nIndex + nCount <= m_nSize))
		m_pData[nIndex++] = newElement;
}

template <class T> void CTemplateArray<T>::RemoveAt(int nIndex, int nCount)
{
	if (nIndex >= 0 || nCount >= 0 || (nIndex + nCount <= m_nSize) )
	{
		// just remove a range
		int nMoveCount = m_nSize - (nIndex + nCount);

		if (nMoveCount)
			memcpy(&m_pData[nIndex], &m_pData[nIndex + nCount],
				nMoveCount * sizeof(T));
		m_nSize -= nCount;
	}
}

template <class T> void CTemplateArray<T>::InsertAt(int nStartIndex, CTemplateArray* pNewArray)
{
	if (pNewArray && nStartIndex>=0 && pNewArray->GetSize() > 0)
	{
		InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
		for (int i = 0; i < pNewArray->GetSize(); i++)
			SetAt(nStartIndex + i, pNewArray->GetAt(i));
	}
}



/////////////////////////////////////////////////////////////////////////////


template <class T>
class CTemplateAutoArray : public CTemplateArray<T>
{
public:
	~CTemplateAutoArray();

	void reset();
};


template <class T> CTemplateAutoArray<T>::~CTemplateAutoArray()
{
	reset();
}

template <class T> void CTemplateAutoArray<T>::reset()
{
	for( int i = 0; i < m_nSize; i++) // call objects destructor
		delete m_pData[i];

	RemoveAll();
}




template <class T>
class CTemplateObjArray
{


public:

// Construction
	CTemplateObjArray();
	~CTemplateObjArray();

// Attributes
	int		GetSize() const;
	int		GetUpperBound() const;
	void	SetSize(int nNewSize, int nGrowBy = -1);

// Operations
	// Clean up
	void	FreeExtra();
	void	RemoveAll();

	// Accessing elements
	T		GetAt(int nIndex) const;
	void	SetAt(int nIndex, T newElement);
	T&		ElementAt(int nIndex);


	// Potentially growing the array
	void	SetAtGrow(int nIndex, T newElement);
	int		Add(T newElement);
	int		Append(const CTemplateObjArray& src);
	void	Copy(const CTemplateObjArray& src);

	// overloaded operator helpers
	T		operator[](int nIndex) const;
	T&		operator[](int nIndex);

	// Operations that move elements around
	void	InsertAt(int nIndex, T newElement, int nCount = 1);
	void	RemoveAt(int nIndex, int nCount = 1);
	void	InsertAt(int nStartIndex, CTemplateObjArray* pNewArray);
	void	Remove(T oldElement);

// Implementation
protected:
	T*  m_pData;   // the actual array of data
	int m_nSize;     // # of elements (upperBound - 1)
	int m_nMaxSize;  // max allocated
	int m_nGrowBy;   // grow amount

};


template <class T> CTemplateObjArray<T>::CTemplateObjArray()
{
	m_pData = NULL;
	m_nSize = m_nMaxSize = m_nGrowBy = 0;
}

template <class T> CTemplateObjArray<T>::~CTemplateObjArray()
{
	delete[] m_pData;
	m_pData = NULL;
}

template <class T> int CTemplateObjArray<T>::GetSize() const
{ 
	return m_nSize; 
}

template <class T> int CTemplateObjArray<T>::GetUpperBound() const
{ 
	return m_nSize-1; 
}

template <class T> void CTemplateObjArray<T>::SetSize(int nNewSize, int nGrowBy)
{
	if (nNewSize < 0)
		return;

	if (nGrowBy != -1)
		m_nGrowBy = nGrowBy;  // set new size

	if (nNewSize == 0)
	{
		// shrink to nothing
		delete[] m_pData;
		m_pData = NULL;
		m_nSize = m_nMaxSize = 0;
	}
	else if (m_pData == NULL)
	{
		// create one with exact size
		m_pData = new T[nNewSize];

		m_nSize = m_nMaxSize = nNewSize;
	}
	else if (nNewSize <= m_nMaxSize)
	{
		// it fits
		if (nNewSize > m_nSize)
		{
			T empty;
			for (int i=m_nSize; i<nNewSize; i++)
				m_pData[i] = empty;
		}

		m_nSize = nNewSize;
	}
	else
	{
		// otherwise, grow array
		int nGrowBy = m_nGrowBy;
		if (nGrowBy == 0)
		{
			// heuristically determine growth when nGrowBy == 0
			//  (this avoids heap fragmentation in many situations)
			nGrowBy = (m_nSize/8 > 4)? m_nSize/8 : 4;
		}
		int nNewMax;
		if (nNewSize < m_nMaxSize + nGrowBy)
			nNewMax = m_nMaxSize + nGrowBy;  // granularity
		else
			nNewMax = nNewSize;  // no slush

		T* pNewData = new T[nNewMax];
		
		for (int i=0; i<m_nSize; i++)
		{
			pNewData[i] = m_pData[i]; // = operator required on T class
		}

		// get rid of old stuff (note: no destructors called)
		delete[] m_pData;
		m_pData = pNewData;
		m_nSize = nNewSize;
		m_nMaxSize = nNewMax;
	}
}


template <class T> void CTemplateObjArray<T>::FreeExtra()
{
	if (m_nSize != m_nMaxSize)
	{
		// shrink to desired size
		T* pNewData = NULL;
		if (m_nSize != 0)
		{
			// copy new data from old
			pNewData =  new T[m_nSize];
			for (int i=0; i<m_nSize; i++)
				pNewData[i] = m_pData[i];
		}

		// get rid of old stuff (note: no destructors called)
		delete[] m_pData;
		m_pData = pNewData;
		m_nMaxSize = m_nSize;
	}
}

template <class T> void CTemplateObjArray<T>::RemoveAll()
{ 
	SetSize(0); 
}

template <class T> T CTemplateObjArray<T>::GetAt(int nIndex) const
{ 
	T empty;
	if (nIndex<0 || nIndex>=m_nSize)
		return empty;
	else
		return m_pData[nIndex]; 
}

template <class T> void CTemplateObjArray<T>::SetAt(int nIndex, T newElement)
{ 
	if (nIndex >= 0 && nIndex < m_nSize)
		m_pData[nIndex] = newElement; 
}

template <class T> T& CTemplateObjArray<T>::ElementAt(int nIndex)
{ 
	static T pVoid=NULL;

	if (nIndex<0 || nIndex>=m_nSize)
		return pVoid;
	else
		return m_pData[nIndex]; 
}


template <class T> void CTemplateObjArray<T>::SetAtGrow(int nIndex, T newElement)
{
	if (nIndex < 0)
		return;

	if (nIndex >= m_nSize)
		SetSize(nIndex+1);
	m_pData[nIndex] = newElement;
}

template <class T> int CTemplateObjArray<T>::Add(T newElement)
{ 
	int nIndex = m_nSize;
	SetAtGrow(nIndex, newElement);
	return nIndex; 
}

template <class T> void CTemplateObjArray<T>::Remove(T oldElement)
{ 
	for( int i = 0; i < m_nSize; i++)
	{
		if( m_pData[i] == oldElement)
		{
			if( i < m_nSize - 1)
				m_pData[i] = m_pData[i+1];
			m_nSize--;
			return;
		}
	}
}

template <class T> int CTemplateObjArray<T>::Append(const CTemplateObjArray& src)
{
	int nOldSize = m_nSize;
	
	if (this != &src)
	{
		SetSize(m_nSize + src.m_nSize);

		long nSize = src.m_nSize;
		for (int i=0; i<nSize; i++)
			m_pData[i+nOldSize] = src[i];
	}
	return nOldSize;
}

template <class T> void CTemplateObjArray<T>::Copy(const CTemplateObjArray& src)
{
	if (this == &src)
		return;

	SetSize(src.m_nSize);

	long nSize = src.m_nSize;
	for (int i=0; i<nSize; i++)
		m_pData[i] = src[i];
}

template <class T> T CTemplateObjArray<T>::operator[](int nIndex) const
{ 
	return GetAt(nIndex); 
}

template <class T> T& CTemplateObjArray<T>::operator[](int nIndex)
{ 
	return ElementAt(nIndex); 
}


template <class T> void CTemplateObjArray<T>::InsertAt(int nIndex, T newElement, int nCount)
{
	if (nIndex<0 || nCount<=0)
		return;

	if (nIndex >= m_nSize)
	{
		// adding after the end of the array
		SetSize(nIndex + nCount);  // grow so nIndex is valid
	}
	else
	{
		// inserting in the middle of the array
		int nOldSize = m_nSize;
		SetSize(m_nSize + nCount);  // grow it to new size

		int i;
		for (i=nOldSize-1; i>=nIndex; i--)
		{
			m_pData[i+nCount] = m_pData[i];
		}

		// re-init slots we copied from
	
		T empty;

		for (i=nIndex; i<nIndex+nCount; i++)
			m_pData[i] = empty;

	}

	// insert new value in the gap
	while (nCount-- && (nIndex + nCount <= m_nSize))
		m_pData[nIndex++] = newElement;
}

template <class T> void CTemplateObjArray<T>::RemoveAt(int nIndex, int nCount)
{
	if (nIndex >= 0 || nCount >= 0 || (nIndex + nCount <= m_nSize) )
	{
		// just remove a range
		int nMoveCount = m_nSize - (nIndex + nCount);

		if (nMoveCount)
		{

			int i;
			for (i=nIndex; i<nIndex+nMoveCount; i++)
			{
				m_pData[i] = m_pData[i+nCount];
			}

			T empty;
			for (i=m_nSize-nCount; i<m_nSize; i++)
				m_pData[i] = empty;

		}

		m_nSize -= nCount;
	}
}


template <class T> void CTemplateObjArray<T>::InsertAt(int nStartIndex, CTemplateObjArray* pNewArray)
{
	if (pNewArray && nStartIndex>=0 && pNewArray->GetSize() > 0)
	{
		InsertAt(nStartIndex, pNewArray->GetAt(0), pNewArray->GetSize());
		for (int i = 0; i < pNewArray->GetSize(); i++)
			SetAt(nStartIndex + i, pNewArray->GetAt(i));
	}
}


/////////////////////////////////////////////////////////////////////////////


typedef CTemplateArray<void*> ArrayLPVoid;
typedef CTemplateArray<long>  ArraySLong;
typedef CTemplateArray<long>  ArrayInt;
typedef CTemplateArray<char*>  ArrayString;
typedef CTemplateArray<void*> CPtrArray;

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.


Written By
France France
Addicted to reverse engineering. At work, I am developing business intelligence software in a team of smart people (independent software vendor).

Need a fast Excel generation component? Try xlsgen.

Comments and Discussions