使用步骤:
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