MFC 自绘ComboBox

来源:互联网 发布:电脑桌面软件太多 编辑:程序博客网 时间:2024/06/08 00:08

效果图:


.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:// 关联的CImageListCImageList *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 文件

/********************************************************** ComboBoxXI.cpp : implementation file Written by WangYao (wangyao1052@163.com) Version: V1.0 2014-06-07**********************************************************/#include "stdafx.h"#include "ComboBoxXI.h"#defineCBXI_CX_BORDER   2#defineCBXI_CY_BORDER   2// CComboBoxXIIMPLEMENT_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());}// 绘制ICONCRect 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);}}// 绘制Textif (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;// 检测是否是DropListif (-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

0 0
原创粉丝点击