VS2019 MFC ComBOX控件自绘的方法和实例【一】

35 篇文章 6 订阅
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 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值