VC++组合框操作辅助类使组合框显示字符串与任意数据类型配对

使用步骤:

1.关联控件

    调用InitCtrl函数CComboBox控件进行关联

2.预定义字符串与配对数值

    使用AddItem函数初始化下拉列表显示字符串配对实际数值

3.显示数据到组合框

    调用FillWithStr/FillWithStr_T/FillSiblingComboBox将已添加好的数据显示到组合框或非关联ComboBox控件

4.获取用户选择值

    需要获取组合框实际选择值调用GetSelectedPair/GetSelectedTValue/GetSelectedStrValue可以直接获取用户选择的字符数值对或对应的数值(注意下拉列表样式选择Drop List)。


#pragma once

#include <vector>

//author:葛红军

namespace nsTStrPair
{
#ifndef _tcscpy_s
#define _tcscpy_s(strDestination, numberOfElements, strSource)\
	_tcscpy(strDestination, strSource)
#endif
template<typename T>
struct TStrPair
{
	PTCHAR	szValue;
	T		tValue;
};

//////////////////////////////////////////////////////////////////////////
//CTStrPair
template<typename T>
class CTStrPair
{
public:
	typedef typename std::vector<TStrPair<T>*>::iterator		TStrPairIterator;	
	typedef typename std::allocator<TStrPair<T>*>::reference	reference;

	CTStrPair()
	{

	}

	virtual ~CTStrPair()
	{
		RemoveAll();
	}

	LPCTSTR TToStr(T tValue);
	T StrToT(LPCTSTR szValue, BOOL bCaseSensitive=TRUE);
	INT_PTR GetTIndex(T tValue);//获取T值的序号
	INT_PTR GetStrIndex(LPCTSTR szValue, BOOL bCaseSensitive=TRUE);//获取Str值的序号
	BOOL AddItem(LPCTSTR szValue, T tValue, BOOL bUniqueStr=TRUE, BOOL bCaseSensitive=TRUE);
	BOOL RemoveItem(LPCTSTR szValue, BOOL bCaseSensitive=TRUE);
	BOOL RemoveItem(T tValue);
	void RemoveAll();

	CString FormatStr(LPTSTR pszFrm, ...)
	{
		CString		sVal;
		va_list		argptr;

		va_start(argptr, pszFrm);	
		sVal.FormatV(pszFrm, argptr);
		va_end(argptr);

		return sVal;
	}

	reference operator[](size_t _P)
	{
		return _Items[_P];
	}

	virtual TStrPair<T>** GetData() 
	{
		if (_Items.empty()) return NULL;
		return &_Items[0];
	}

	virtual size_t GetCount()
	{
		return _Items.size();
	}

private:
	std::vector<TStrPair<T>*> _Items;
};

template<typename T>
INT_PTR CTStrPair<T>::GetStrIndex( LPCTSTR szValue, BOOL bCaseSensitive/*=TRUE*/ )
{
	INT_PTR nIndex = 0;

	if (_Items.empty()) return -1;

	for (TStrPairIterator it=_Items.begin(); it!=_Items.end(); ++it, ++nIndex)
	{
		TStrPair<T> *item	= *it;
		if (bCaseSensitive) {
			if (!_tcscmp(item->szValue, szValue)) {
				return nIndex;
			}
		} else if (!_tcsicmp(item->szValue, szValue)) {
			return nIndex;
		}
	}

	return -1;
}

template<typename T>
INT_PTR CTStrPair<T>::GetTIndex( T tValue )
{
	INT_PTR nIndex = 0;

	if (_Items.empty()) return -1;

	for (TStrPairIterator it=_Items.begin(); it!=_Items.end(); ++it, ++nIndex)
	{
		TStrPair<T> *item	= *it;
		if (item->tValue == tValue) {
			return nIndex;
		}
	}

	return -1;
}

template<typename T>
void CTStrPair<T>::RemoveAll()
{
	if (_Items.empty()) return;

	for (TStrPairIterator it=_Items.begin(); it!=_Items.end(); ++it)
	{
		TStrPair<T> *item	= *it;
		delete []item->szValue;
		item->szValue		= NULL;
		delete item;
		item				= NULL;
	}
	_Items.clear();	
}

template<typename T>
BOOL CTStrPair<T>::RemoveItem( T tValue )
{
	if (_Items.empty()) return FALSE;

	BOOL bItemErased = FALSE;
	//注意删除操作顺序
	for (TStrPairIterator it=_Items.begin(); it!=_Items.end();)
	{
		TStrPair<T> *item = *it;
		if (item->tValue == tValue) {
			delete []item->szValue;
			item->szValue = NULL;
			delete item;
			item = NULL;
			it = _Items.erase(it);
			bItemErased = TRUE;
		} else {
			++it;
		}
	}

	return bItemErased;
}

template<typename T>
BOOL CTStrPair<T>::RemoveItem( LPCTSTR szValue, BOOL bCaseSensitive/*=TRUE*/ )
{
	BOOL bItemErased = FALSE;

	if (_Items.empty()) return TRUE;

	//注意删除操作顺序
	for (TStrPairIterator it=_Items.begin(); it!=_Items.end();)
	{
		TStrPair<T> *item = NULL;
		if (bCaseSensitive) {
			if (!_tcscmp((*it)->szValue, szValue)) {
				item = *it;
			}
		} else if (!_tcsicmp((*it)->szValue, szValue)) {
			item = *it;
		}

		if (item) {
			bItemErased = TRUE;
			delete []item->szValue;
			item->szValue = NULL;
			delete item;
			item = NULL;
			it = _Items.erase(it);
		} else {
			++it;
		}
	}

	return bItemErased;
}

template<typename T>
BOOL CTStrPair<T>::AddItem( LPCTSTR szValue, T tValue, BOOL bUniqueStr/*=TRUE*/, BOOL bCaseSensitive/*=FALSE*/ )
{
	if (bUniqueStr && !_Items.empty()) {
		for (TStrPairIterator it=_Items.begin(); it!=_Items.end(); ++it)
		{
			TStrPair<T> *item = *it;
			if (bCaseSensitive) {
				if (!_tcscmp(item->szValue, szValue)) {
					return FALSE;
				}
			} else if (!_tcsicmp(item->szValue, szValue)) {
				return FALSE;
			}	
		}
	}

	TStrPair<T> *newItem = new TStrPair<T>;
	if (!newItem) return FALSE;

	memset(newItem, 0, sizeof(TStrPair<T>));

	size_t nStrLen		= _tcslen(szValue);
	newItem->szValue	= new TCHAR[nStrLen+1];
	if (!newItem->szValue) {
		delete newItem;
		newItem = NULL;
		return FALSE;
	}
	
	_tcscpy_s(newItem->szValue, nStrLen+1, szValue);
	newItem->tValue = tValue;
	_Items.push_back(newItem);

	return TRUE;
}

template<typename T>
LPCTSTR CTStrPair<T>::TToStr( T tValue )
{
	if (_Items.empty()) return NULL;

	for (TStrPairIterator it=_Items.begin(); it!=_Items.end(); ++it)
	{
		TStrPair<T> *item = *it;
		if (item->tValue == tValue) {
			return item->szValue;
		}
	}

	return NULL;
}

template<typename T>
T CTStrPair<T>::StrToT( LPCTSTR szValue, BOOL bCaseSensitive/*=TRUE*/ )
{
	T tValue;

	if (_Items.empty()) return tValue;

	for (TStrPairIterator it=_Items.begin(); it!=_Items.end(); ++it)
	{
		TStrPair<T> *item = *it;
		if (bCaseSensitive) {
			if (!_tcscmp(item->szValue, szValue)) {
				return item->tValue;
			}
		} else if (!_tcsicmp(item->szValue, szValue)) {
			return item->tValue;			
		}
	}

	return tValue;
}

#define DECLARE_CTSTRPAIRCLASS(class_name, T_type)	\
private:											\
	virtual void _Init();							\
public:												\
	class_name() { _Init(); }

#define BEGIN_CTSTRPAIRCLASS(class_name)\
	void class_name::_Init() {

#define ADDPAIRITEM(szValue, tValue)	\
	AddItem(szValue, tValue);

#define END_CTSTRPAIRCLASS()			\
}

//////////////////////////////////////////////////////////////////////////
//CCBTStrPair
template<typename T>
class CCBTStrPair : public CTStrPair<T>
{
public:
	CCBTStrPair() : m_pWndParent(NULL), m_nCBID(0) {}
	CCBTStrPair(CWnd *parent, UINT nID);

	void			FillWithStr(int nDefaultSelectIndex=0, BOOL bReverseOrder=FALSE/*倒序填充*/);
	BOOL			FillWithStr_T(T tDefaultSelectValue);
	void			FillSiblingComboBox(UINT nID, int nDefaultSelect=0);
	TStrPair<T>*	GetSelectedPair();
	size_t          SetSelectTValue(T tSelectValue);
	T				GetSelectedTValue(T tDefaultValue);
	int             SetSelectStrValue(LPCTSTR szSelectValue, BOOL bCaseSensitive);
	LPCTSTR			GetSelectedStrValue(LPCTSTR szDefaultValue=NULL);	
	BOOL			isItemSelected();
	void			SetSelectNone();
	void			InitCtrl(CWnd *parent, UINT nID);

private:
	CWnd *m_pWndParent;
	UINT m_nCBID;
};

template<typename T>
void CCBTStrPair<T>::InitCtrl( CWnd *parent, UINT nID )
{
	m_pWndParent = parent;
	m_nCBID		 = nID;
}

template<typename T>
int CCBTStrPair<T>::SetSelectStrValue( LPCTSTR szSelectValue, BOOL bCaseSensitive )
{
	ASSERT(m_pWndParent);
	ASSERT(m_nCBID);
	CComboBox *pCB = (CComboBox*)m_pWndParent->GetDlgItem(m_nCBID);
	if (pCB==NULL) return CB_ERR;

	TStrPair<T> **items	= GetData();
	int			nCnt	= GetCount();
	ASSERT(items && (nCnt>=0));

	if (GetProp(pCB->GetSafeHwnd(), PropFlag) != hProp) 
		return CB_ERR;
	
	for (int i=0; i!=pCB->GetCount(); ++i)
	{
		int nTag = pCB->GetItemData(i);
		if (bCaseSensitive) {
			if (_tcscmp(szSelectValue, items[nTag]->szValue)==0) {
				pCB->SetCurSel(i);
				return i;
			}
		} else {
			if (_tcsnicmp(szSelectValue, items[nTag]->szValue)==0) {
				pCB->SetCurSel(i);
				return i;
			}
		}
	}

	return CB_ERR;
}

template<typename T>
size_t CCBTStrPair<T>::SetSelectTValue( T tSelectValue )
{
	ASSERT(m_pWndParent);
	ASSERT(m_nCBID);
	CComboBox *pCB = (CComboBox*)m_pWndParent->GetDlgItem(m_nCBID);
	if (pCB==NULL) return CB_ERR;

	TStrPair<T> **items	= GetData();
	size_t		nCnt	= GetCount();
	ASSERT(items && (nCnt>=0));

	for (size_t i=0; i<(size_t)pCB->GetCount(); ++i)
	{
		size_t nTag = pCB->GetItemData((int)i);
		if (items[nTag]->tValue == tSelectValue) {
			pCB->SetCurSel((int)i);
			return i;
		}
	}

	return CB_ERR;
}

template<typename T>
BOOL CCBTStrPair<T>::isItemSelected()
{
	ASSERT(m_pWndParent);
	ASSERT(m_nCBID);
	CComboBox *pCB = (CComboBox*)m_pWndParent->GetDlgItem(m_nCBID);
	if (pCB==NULL) return FALSE;

	return (pCB->GetCurSel() != CB_ERR);
}

template<typename T>
void CCBTStrPair<T>::SetSelectNone()
{
	ASSERT(m_pWndParent);
	ASSERT(m_nCBID);
	CComboBox *pCB = (CComboBox*)m_pWndParent->GetDlgItem(m_nCBID);
	if (pCB==NULL) return;

	pCB->SetCurSel(CB_ERR);
}

template<typename T>
CCBTStrPair<T>::CCBTStrPair( CWnd *parent, UINT nID ) :
m_pWndParent(parent), m_nCBID(nID)
{
	
}

template<typename T>
void CCBTStrPair<T>::FillWithStr(int nDefaultSelectIndex/*=0*/, BOOL bReverseOrder/*=FALSE*/ )
{
	ASSERT(m_pWndParent);
	ASSERT(m_nCBID);
	CComboBox *pCB = (CComboBox*)m_pWndParent->GetDlgItem(m_nCBID);
	if (pCB==NULL) return;

	ASSERT(nDefaultSelectIndex>=0);
	TStrPair<T> **items	= GetData();
	size_t		nCnt	= GetCount();
	ASSERT(items && (nCnt>=0));

	pCB->ResetContent();
	if (bReverseOrder) {
		for (size_t i=nCnt-1; i!=-1; --i)
		{
			int nIndex = pCB->AddString(items[i]->szValue);
			pCB->SetItemData(nIndex, i);
		}
	} else {
		for (size_t i=0; i!=nCnt; ++i)
		{
			int nIndex = pCB->AddString(items[i]->szValue);
			pCB->SetItemData(nIndex, i);
		}
	}	
	pCB->SetCurSel(nDefaultSelectIndex);
}

template<typename T>
BOOL CCBTStrPair<T>::FillWithStr_T( T tDefaultSelectValue )
{
	ASSERT(m_pWndParent);
	ASSERT(m_nCBID);
	CComboBox *pCB = (CComboBox*)m_pWndParent->GetDlgItem(m_nCBID);
	if (pCB==NULL) return CB_ERR;

	TStrPair<T> **items	= GetData();
	size_t		nCnt	= GetCount();
	size_t		nSel	= CB_ERR;
	ASSERT(items && (nCnt>=0));

	for (size_t i=0; i<nCnt; ++i)
	{
		int nIndex = pCB->AddString(items[i]->szValue);
		pCB->SetItemData(nIndex, i);
		if (items[i]->tValue == tDefaultSelectValue) {
			nSel = nIndex;
		}
	}

	pCB->SetCurSel((int)nSel);

	return (nSel != CB_ERR);
}

template<typename T>
void CCBTStrPair<T>::FillSiblingComboBox(UINT nID, int nDefaultSelect/* =0 */)
{
	ASSERT(m_pWndParent);
	ASSERT(m_nCBID);
	ASSERT(nID);
	CComboBox *pCB = (CComboBox*)m_pWndParent->GetDlgItem(nID);
	if (pCB==NULL) return;
	ASSERT(nDefaultSelect>=CB_ERR);
	TStrPair<T> **items	= GetData();
	int			nCnt	= GetCount();
	ASSERT(items && (nCnt>=0));

	pCB->ResetContent();
	for (int i=0; i!=nCnt; ++i)
	{
		int nIndex = pCB->AddString(items[i]->szValue);
		pCB->SetItemData(nIndex, i);
	}
	pCB->SetCurSel(nDefaultSelect);
}

template<typename T>
TStrPair<T>* CCBTStrPair<T>::GetSelectedPair()
{
	ASSERT(m_pWndParent);
	ASSERT(m_nCBID);
	if (!m_pWndParent->GetSafeHwnd()) return NULL;
	CComboBox *pCB = (CComboBox*)m_pWndParent->GetDlgItem(m_nCBID);
	if (pCB==NULL) return NULL;

	TStrPair<T> **items	= GetData();
	size_t		nCnt	= GetCount();
	if (!nCnt) return NULL;
	int			nSel	= pCB->GetCurSel();
	if (nSel == CB_ERR) return NULL;

	size_t		nTag	= pCB->GetItemData(nSel);
	if (nTag < nCnt) return (items[nTag]);

	return NULL;
}

template<typename T>
T CCBTStrPair<T>::GetSelectedTValue(T tDefaultValue)
{
	T		tRet = tDefaultValue;
	TStrPair<T> *item = GetSelectedPair();
	if (item) tRet = item->tValue;

	return tRet;
}

template<typename T>
LPCTSTR CCBTStrPair<T>::GetSelectedStrValue(LPCTSTR szDefaultValue/*=NULL*/)
{
	TStrPair<T> *item = GetSelectedPair();
	if (item) return item->szValue;
	return szDefaultValue;
}

#define DECLARE_CCOMBOBOXTSTRPAIRCLASS(class_name, T_type)	\
private:													\
	void _Init();											\
public:														\
	class_name(CWnd *parent=NULL, UINT nID=(UINT)-1) :		\
	CCBTStrPair<T_type>(parent, nID) { _Init(); }


#define BEGIN_CCOMBOBOXTSTRPAIRCLASS(class_name)			\
	BEGIN_CTSTRPAIRCLASS(class_name)

#define END_CCOMBOBOXTSTRPAIRCLASS()						\
	END_CTSTRPAIRCLASS()

}//end namespace




你可能感兴趣的:(组合框,控件,CComboBox,配对)