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