效果图:
.h文件
#pragma once
#include"stdafx.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);
int AddString(LPCTSTR lpszString, int nImageIndex = -1);
int DeleteString(UINT nIndex);
int InsertString(int nIndex, LPCTSTR lpszString, int nImageIndex);
void ResetContent();
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);
};
/**********************************************************
ComboBoxXI.cpp : implementation file
Written by WangYao ([email protected])
Version: V1.0 2014-06-07
**********************************************************/
#include "stdafx.h"
#include "ComboBoxXI.h"
#define CBXI_CX_BORDER 2
#define CBXI_CY_BORDER 2
// CComboBoxXI
IMPLEMENT_DYNAMIC(CComboBoxXI, CComboBox)
CComboBoxXI::CComboBoxXI()
{
m_pImageList = NULL;
m_imageSize.cx = 0;
m_imageSize.cy = 0;
m_nEditHeight = 0;
m_iIsDropList = -1;
}
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();
}
//---------------------------------------------------------
// 函数: 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, ::GetSysColor(COLOR_HIGHLIGHT));
pDC->SetBkColor(oldColor);
}
else
{
pDC->FillSolidRect(&rcItem, pDC->GetBkColor());
}
// 绘制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(::GetSysColor(COLOR_HIGHLIGHTTEXT));
}
else
{
pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
}
CRect rcText(rcItem);
rcText.left = rcIcon.right;
rcText.top = rcIcon.top;
pDC->DrawText(cstrItemText, rcText, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_WORDBREAK);
}
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()
// CComboBoxXI message handlers
=============== 提供了如下接口 ===============================
void SetImageList(CImageList* pImageList);
CImageList* GetImageList() const;
int GetItemImage(int nIndex);
int SetItemImage(int nIndex, int nImageIndex, BOOL bRepaint = TRUE);
int AddString(LPCTSTR lpszString, int nImageIndex = -1);
int DeleteString(UINT nIndex);
int InsertString(int nIndex, LPCTSTR lpszString, int nImageIndex);
void ResetContent();
DWORD_PTR GetItemData(int nIndex) const;
int SetItemData(int nIndex, DWORD_PTR dwItemData);
void* GetItemDataPtr(int nIndex) const;
int SetItemDataPtr(int nIndex, void* pData);
================= 示例 =================================
OnInitialDialog()
{
...........
m_imglist1.Create(32,32, ILC_COLOR32 | ILC_MASK, 2, 1);
m_imglist1.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
m_imglist1.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
m_combo.SetImageList(&m_imglist1);
m_combo.AddString(_T("123"), 0);
m_combo.AddString(_T("456"), 1);
m_combo.SetCurSel(0);
}
注:ComboBox要设置两个属性
HasStrings: True
Owner Draw: Variable