ComBox自绘效果图:
继承类H头文件
class CComboBoxXI : public CComboBox { DECLARE_DYNAMIC(CComboBoxXI) public: CComboBoxXI(); virtual ~CComboBoxXI(); void SetImageList(CImageList* pImageList); CImageList* GetImageList() const; int GetItemImage(int nIndex); int SetItemImage(int nIndex, int nImageIndex, BOOL bRepaint = TRUE); COLORREF NorBkCrl; COLORREF SelectedBkCrl; COLORREF NorTextCrl; COLORREF SelectedTextCrl; LPCTSTR lpFaceName; int nHeight; int AddString(LPCTSTR lpszString, int nImageIndex = -1); int DeleteString(UINT nIndex); int InsertString(int nIndex, LPCTSTR lpszString, int nImageIndex); void ResetContent(); void SetBkAndTextCrl(COLORREF nBkCrl,COLORREF sBkCrl,COLORREF nTextCrl,COLORREF sTextCrl); void SetComBoxFont(int nFontHeight,LPCTSTR lpFontFaceName); DWORD_PTR GetItemData(int nIndex) const; int SetItemData(int nIndex, DWORD_PTR dwItemData); void* GetItemDataPtr(int nIndex) const; int SetItemDataPtr(int nIndex, void* pData); protected: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); DECLARE_MESSAGE_MAP() private: // 关联的CImageList CImageList* m_pImageList; CSize m_imageSize; // EditCtrl的高度 unsigned int m_nEditHeight; // 是否是DropList: // -1(待定,未检测), 1(Yes), 0(No) // 只对DropList设置EditCtrl的高度,对DropDown和Simple则采用默认高度 int m_iIsDropList; struct CBDataXI { // 图像序号,如果为-1,则表示无图像 int iImageIndex; // 关联数据的指针 LPVOID pData; CBDataXI() { iImageIndex = -1; pData = NULL; } }; void DeleteItemData(int nIndex); };
继承类CPP
#define CBXI_CX_BORDER 10 #define CBXI_CY_BORDER 10 // CComboBoxXI IMPLEMENT_DYNAMIC(CComboBoxXI, CComboBox) CComboBoxXI::CComboBoxXI() { m_pImageList = NULL; m_imageSize.cx = 0; m_imageSize.cy = 0; m_nEditHeight = 0; m_iIsDropList = 1; NorBkCrl = RGB(0,0,255); SelectedBkCrl = RGB(150,130,50); NorTextCrl = RGB(150,130,50); SelectedTextCrl = RGB(0,0,255); nHeight = 18; lpFaceName = _T("Adobe 宋体 Std L"); } CComboBoxXI::~CComboBoxXI() { } //--------------------------------------------------------- // 函数: SetImageList // 功能: 设置关联的ImageList // 参数: // pImageList --- ImageList的指针 // 返回: 无 //--------------------------------------------------------- void CComboBoxXI::SetImageList(CImageList* pImageList) { m_pImageList = pImageList; if (m_pImageList) { int cx; int cy; ImageList_GetIconSize(*m_pImageList, &cx, &cy); m_imageSize.cx = cx; m_imageSize.cy = cy; } else { m_imageSize.cx = 0; m_imageSize.cy = 0; } Invalidate(); } //--------------------------------------------------------- // 函数: GetImageList // 功能: 获取关联ImageList的指针 // 参数: 无 // 返回: 关联ImageList的指针,若没有关联ImageList返回NULL //--------------------------------------------------------- CImageList* CComboBoxXI::GetImageList() const { return m_pImageList; } //--------------------------------------------------------- // 函数: GetItemImage // 功能: 获取项的图片索引 // 参数: // nIndex --- 项索引(以0为起点) // 返回: // 以0为起始的图片序号 // 若存在错误,如nIndex超出范围,返回-1 // 若组合框项没有关联图片则返回-1 //--------------------------------------------------------- int CComboBoxXI::GetItemImage(int nIndex) { CBDataXI* pCBData = (CBDataXI*)CComboBox::GetItemData(nIndex); if (pCBData == (CBDataXI*)CB_ERR || pCBData == NULL) { return -1; } return pCBData->iImageIndex; } //--------------------------------------------------------- // 函数: SetItemImage // 功能: 设置项的图片索引 // 参数: // nIndex --- 项索引(以0为起点) // nImageIndex --- 图片索引(以0为起点) // bRepaint --- 是否重绘 // 返回: // 成功返回0,失败返回-1 //--------------------------------------------------------- int CComboBoxXI::SetItemImage(int nIndex, int nImageIndex, BOOL bRepaint) { CBDataXI* pCBData = (CBDataXI*)CComboBox::GetItemData(nIndex); if (pCBData == (CBDataXI*)CB_ERR || pCBData == NULL) { return -1; } pCBData->iImageIndex = nImageIndex; if (bRepaint) { Invalidate(); } return 0; } //--------------------------------------------------------- // 函数: AddString // 功能: 添加项 // 参数: lpszString --- 字符串指针 // nImageIndex --- 图片索引(以0为起点) // 返回: 新增项的索引值 // 失败则返回CB_ERR或CB_ERRSPACE //--------------------------------------------------------- int CComboBoxXI::AddString(LPCTSTR lpszString, int nImageIndex) { int nIndex = CComboBox::AddString(lpszString); if (nIndex != CB_ERR && nIndex != CB_ERRSPACE) { CBDataXI* pData = new CBDataXI(); pData->iImageIndex = nImageIndex; pData->pData = NULL; CComboBox::SetItemData(nIndex, (DWORD_PTR)pData); } return nIndex; } //--------------------------------------------------------- // 函数: InsertString // 功能: 在指定位置插入项 // 参数: // nIndex --- 指定位置 // lpszString --- 字符串指针 // nImageIndex --- 图片索引(以0为起点) // 返回: // 插入项索引值 // 失败则返回CB_ERR或CB_ERRSPACE //--------------------------------------------------------- int CComboBoxXI::InsertString(int nIndex, LPCTSTR lpszString, int nImageIndex) { int nRet = CComboBox::InsertString(nIndex, lpszString); if (nRet != CB_ERR && nRet != CB_ERRSPACE) { CBDataXI* pData = new CBDataXI(); pData->iImageIndex = nImageIndex; pData->pData = NULL; CComboBox::SetItemData(nIndex, (DWORD_PTR)pData); } return nRet; } //--------------------------------------------------------- // 函数: DeleteString // 功能: 删除项 // 参数: // nIndex --- 索引 // 返回: // 成功则返回当前还剩的项数 // 失败则返回CB_ERR //--------------------------------------------------------- int CComboBoxXI::DeleteString(UINT nIndex) { DeleteItemData(nIndex); return CComboBox::DeleteString(nIndex); } //--------------------------------------------------------- // 函数: ResetContent // 功能: 清空内容 //--------------------------------------------------------- void CComboBoxXI::ResetContent() { int nCnt = CComboBox::GetCount(); for (int i = 0; i < nCnt; ++i) { DeleteItemData(i); } CComboBox::ResetContent(); } //--------------------------------------------------------- // 函数: SetBkAndTextCrl // 功能: 设置背景颜色,字体颜色 //--------------------------------------------------------- void CComboBoxXI::SetBkAndTextCrl(COLORREF nBkCrl, COLORREF sBkCrl, COLORREF nTextCrl, COLORREF sTextCrl) { NorBkCrl = nBkCrl; SelectedBkCrl = sBkCrl; NorTextCrl = nTextCrl; SelectedTextCrl = sTextCrl; } //--------------------------------------------------------- // 函数: SetComBoxFont // 功能: 设置字体大小,字体类型 //---- void CComboBoxXI::SetComBoxFont(int nFontHeight, LPCTSTR lpFontFaceName) { nHeight= nFontHeight; lpFaceName = lpFontFaceName; } //--------------------------------------------------------- // 函数: GetItemData // 功能: 获取项关联的数据 // 参数: // nIndex --- 索引 // 返回: // 关联的数据,失败则返回CB_ERR //--------------------------------------------------------- DWORD_PTR CComboBoxXI::GetItemData(int nIndex) const { CBDataXI* pCBData = (CBDataXI*)CComboBox::GetItemData(nIndex); if (pCBData == (CBDataXI*)CB_ERR || pCBData == NULL) { return CB_ERR; } return (DWORD_PTR)pCBData->pData; } //--------------------------------------------------------- // 函数: SetItemData // 功能: 设置项关联的数据 // 参数: // nIndex --- 索引 // dwItemData --- 关联的数据 // 返回: // 成功返回CB_OKAY, 失败返回CB_ERR //--------------------------------------------------------- int CComboBoxXI::SetItemData(int nIndex, DWORD_PTR dwItemData) { CBDataXI* pCBData = (CBDataXI*)CComboBox::GetItemData(nIndex); if (pCBData == (CBDataXI*)CB_ERR || pCBData == NULL) { return CB_ERR; } pCBData->pData = (LPVOID)dwItemData; return CB_OKAY; } //--------------------------------------------------------- // 函数: GetItemDataPtr // 功能: 获取项关联的数据 // 参数: // nIndex --- 索引 // 返回: // 关联的数据,失败则返回CB_ERR //--------------------------------------------------------- void* CComboBoxXI::GetItemDataPtr(int nIndex) const { CBDataXI* pCBData = (CBDataXI*)CComboBox::GetItemDataPtr(nIndex); if (pCBData == (CBDataXI*)CB_ERR || pCBData == NULL) { return (void*)CB_ERR; } return pCBData->pData; } //--------------------------------------------------------- // 函数: SetItemDataPtr // 功能: 设置项关联的数据 // 参数: // nIndex --- 索引 // pData --- 关联的数据 // 返回: // 成功返回CB_OKAY, 失败则返回CB_ERR //--------------------------------------------------------- int CComboBoxXI::SetItemDataPtr(int nIndex, void* pData) { CBDataXI* pCBData = (CBDataXI*)CComboBox::GetItemDataPtr(nIndex); if (pCBData == (CBDataXI*)CB_ERR || pCBData == NULL) { return CB_ERR; } pCBData->pData = pData; return CB_OKAY; } void CComboBoxXI::DeleteItemData(int nIndex) { CBDataXI* pCBData = (CBDataXI*)CComboBox::GetItemData(nIndex); if (pCBData != (CBDataXI*)CB_ERR) { delete pCBData; CComboBox::SetItemData(nIndex, (DWORD_PTR)NULL); } } void CComboBoxXI::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { if (lpDrawItemStruct->itemID == -1) { return; } CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); pDC->SetBkMode(TRANSPARENT); RECT& rcItem = lpDrawItemStruct->rcItem; CString cstrItemText; CComboBox::GetLBText(lpDrawItemStruct->itemID, cstrItemText); CBDataXI* pData = (CBDataXI*)CComboBox::GetItemDataPtr(lpDrawItemStruct->itemID); if (NULL == pData) { return; } // 是否处于选中状态 BOOL bIsSelected = (lpDrawItemStruct->itemAction | ODA_SELECT) && (lpDrawItemStruct->itemState & ODS_SELECTED); // 是否处于焦点状态 BOOL bIsFocused = (lpDrawItemStruct->itemAction | ODA_FOCUS) && (lpDrawItemStruct->itemState & ODS_FOCUS); // 绘制背景 if (bIsSelected) { COLORREF oldColor = pDC->GetBkColor(); pDC->FillSolidRect(&rcItem, SelectedBkCrl); pDC->SetBkColor(oldColor); } else { pDC->FillSolidRect(&rcItem, NorBkCrl); } // 绘制ICON CRect rcIcon(rcItem.left, rcItem.top, rcItem.left, rcItem.top); if (m_pImageList) { HICON hIcon = m_pImageList->ExtractIcon(pData->iImageIndex); if (hIcon) { rcIcon.right = rcItem.left + m_imageSize.cx + 2 * CBXI_CX_BORDER; rcIcon.bottom = rcItem.top + m_imageSize.cy + 2 * CBXI_CY_BORDER; CPoint pos(rcIcon.left + CBXI_CX_BORDER, rcIcon.top + CBXI_CY_BORDER); pDC->DrawState(pos, m_imageSize, hIcon, DSS_NORMAL, (CBrush*)NULL); ::DestroyIcon(hIcon); } } // 绘制Text if (bIsSelected) { pDC->SetTextColor(SelectedTextCrl); } else { pDC->SetTextColor(NorTextCrl); } CFont m_ComCF; CFont* m_OldComCF; m_ComCF.CreateFontW(nHeight, 0, 0, 0, FW_EXTRALIGHT, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, lpFaceName); m_OldComCF = (CFont*)pDC->SelectObject(&m_ComCF); CRect rcText(rcItem); rcText.left = rcIcon.right; rcText.top = rcIcon.top; pDC->DrawText(cstrItemText, rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_WORDBREAK); pDC->SelectObject(m_OldComCF); } void CComboBoxXI::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) { CDC* pDC = GetDC(); LPCTSTR lpszText = (LPCTSTR)lpMeasureItemStruct->itemData; CSize szText = pDC->GetTextExtent(lpszText); ReleaseDC(pDC); lpMeasureItemStruct->itemHeight = szText.cy > m_imageSize.cy + 2 * CBXI_CY_BORDER ? szText.cy : m_imageSize.cy + 2 * CBXI_CY_BORDER; // 检测是否是DropList if (-1 == m_iIsDropList) { DWORD dwStyle = GetStyle(); if (DWORD(CBS_DROPDOWNLIST & dwStyle) == (DWORD)CBS_DROPDOWNLIST) { m_iIsDropList = 1; } else { m_iIsDropList = 0; } } // 设置EditCtrl的高度 if (m_iIsDropList == 1 && lpMeasureItemStruct->itemHeight > m_nEditHeight) { m_nEditHeight = lpMeasureItemStruct->itemHeight; SetItemHeight(-1, m_nEditHeight); } } BEGIN_MESSAGE_MAP(CComboBoxXI, CComboBox) END_MESSAGE_MAP()
实现文件
参考例程:
https://blog.csdn.net/HLW0522/article/details/52348263?spm=1001.2014.3001.5506