MFC中如何重绘CListCtrl的表头

MFC中的CListCtrl实际上是由两个控件组成,一个是表头控件,一个是列表控件。有些时候,我们需要重绘表头,使其满足特定的场景要求。
本文介绍了CListCtrl表头的重绘方法,自定义表头效果如下。
在这里插入图片描述

一、从CHeaderCtrl派生出自定义表头类CCustomHeader

MFC中表示表头控件的类是CHeaderCtrl,我们从它派生一个新类CCustomHeader 。
头文件为:

class CCustomHeader : public CHeaderCtrl
{
	DECLARE_DYNAMIC(CCustomHeader)

public:
	CCustomHeader();
	virtual ~CCustomHeader();
	//设置表头单元格的对齐方式,参见DrawText函数中文字对齐格式
	void SetTextAlign(UINT uFormat = DT_CENTER | DT_SINGLELINE | DT_VCENTER);

protected:
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
	DECLARE_MESSAGE_MAP()

private:
	UINT m_nTextAlignFormat;	//表头文字对齐方式
};

实现文件

// CCustomHeader.cpp: 实现文件
//

#include "pch.h"
#include "TestCustomHeader.h"
#include "CCustomHeader.h"


// CCustomHeader

IMPLEMENT_DYNAMIC(CCustomHeader, CHeaderCtrl)

CCustomHeader::CCustomHeader()
	:m_nTextAlignFormat(DT_CENTER | DT_SINGLELINE | DT_VCENTER)
{}

CCustomHeader::~CCustomHeader()
{}

void CCustomHeader::SetTextAlign(UINT uFormat)
{
	m_nTextAlignFormat = uFormat;
}

BEGIN_MESSAGE_MAP(CCustomHeader, CHeaderCtrl)
END_MESSAGE_MAP()

void CCustomHeader::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	ASSERT(lpDrawItemStruct->CtlType == ODT_HEADER);
	HDITEM hdi;
	TCHAR  lpBuffer[256];

	hdi.mask = HDI_TEXT;
	hdi.pszText = lpBuffer;
	hdi.cchTextMax = 256;
	GetItem(lpDrawItemStruct->itemID, &hdi);

	CDC* pDC;
	pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
	HGDIOBJ hOldFont = pDC->SelectObject(GetStockObject(DEFAULT_GUI_FONT));
	
	// 绘制按钮边框
	::DrawFrameControl(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH);

	//绘制文本
	::DrawText(lpDrawItemStruct->hDC, lpBuffer, _tcslen(lpBuffer),
		&lpDrawItemStruct->rcItem, m_nTextAlignFormat);

	pDC->SelectObject(hOldFont);
}

请注意,在实现文件中,我们重写了DrawItem虚函数;因此当表头控件是自绘样式时,每次绘制都会调用DrawItem函数,在该函数中我们获取表头控件的DC,然后即可进行绘制。
另请注意在DrawItem中使用的如下函数:

BOOL GetItem( int nPos, HDITEM* pHeaderItem ) const;
说明:该函数可以获取表头控件每一项的信息(Retrieves information about a header control item.)

利用该函数,我们获取了表头中每一项的标题内容。

二、使用自定义表头类CCustomHeader

新建一个基于对话框的程序,在对话框类的头文件中增加:

	CListCtrl m_wndLstMain;		//表示列表控件本身
	CCustomHeader m_wndHeader;	//表示列表控件的表头控件

在OnInitDialog函数中增加:

BOOL CTestDlg::OnInitDialog()
{
	//.... 省略
	
	// TODO: 在此添加额外的初始化代码
	CRect rect;
	m_wndLstMain.GetClientRect(rect);
	m_wndLstMain.InsertColumn(0, _T("姓名"), LVCFMT_LEFT, rect.Width() / 3);
	m_wndLstMain.InsertColumn(1, _T("班级"), LVCFMT_LEFT, rect.Width() / 3);
	m_wndLstMain.InsertColumn(2, _T("学号"), LVCFMT_LEFT, rect.Width() / 3);

	m_wndLstMain.InsertItem(0, _T("张三"));
	m_wndLstMain.SetItemText(0, 1, _T("一班"));
	m_wndLstMain.SetItemText(0, 2, _T("001"));

	m_wndLstMain.InsertItem(1, _T("李四"));
	m_wndLstMain.SetItemText(1, 1, _T("一班"));
	m_wndLstMain.SetItemText(1, 2, _T("002"));

	m_wndLstMain.InsertItem(2, _T("王五"));
	m_wndLstMain.SetItemText(2, 1, _T("一班"));
	m_wndLstMain.SetItemText(2, 2, _T("003"));

	m_wndLstMain.SetExtendedStyle(LVS_EX_GRIDLINES);
	
	//子类化列表控件的表头
	CHeaderCtrl* pHeader = m_wndLstMain.GetHeaderCtrl();
	if(pHeader)
		m_wndHeader.SubclassWindow(pHeader->GetSafeHwnd());
	HDITEM hdItem;
	hdItem.mask = HDI_FORMAT;
	for (int i = 0; i < m_wndHeader.GetItemCount(); i++)
	{
		m_wndHeader.GetItem(i, &hdItem);
		hdItem.fmt |= HDF_OWNERDRAW;	//增加自绘样式
		m_wndHeader.SetItem(i, &hdItem);
	}
	
	//.... 省略
}

注意在上述函数中,我们首先初始化了CListCtrl对象,创建了多个列及多个子项,然后利用GetHeaderCtrl()函数找到了CListCtrl对象的表头控件,最后调用SubclassWindow子类化表头控件并将其绑定到m_wndHeader(这是我们重写的表头控件类对象)。
但是,仅仅如此还并未结束,我们需要将表头的每一项都改为自绘样式,这样,表头重绘时才会调用DrawItem函数,具体代码为:

	HDITEM hdItem;
	hdItem.mask = HDI_FORMAT;
	for (int i = 0; i < m_wndHeader.GetItemCount(); i++)
	{
		m_wndHeader.GetItem(i, &hdItem);
		hdItem.fmt |= HDF_OWNERDRAW;	//增加自绘样式
		m_wndHeader.SetItem(i, &hdItem);
	}
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MFC CListCtrl控件的重绘可以通过以下几种方法来实现。 首先,可以通过重写CListCtrl的OnPaint函数来进行重绘。在OnPaint函数,可以使用CDC类提供的绘图函数,如DrawText、DrawImage等,来绘制列表控件的内容。同时,可以使用CListCtrl的GetItemRect函数来获取每个项的位置和大小,以便准确地绘制每个项。 其次,可以使用CListCtrl的Invalidate函数来标记控件为无效状态,然后在主窗口的OnPaint函数进行重绘。使用Invalidate函数可以通知Windows系统,在下一次重绘窗口时调用CListCtrl的OnPaint函数,从而实现重绘。这种方法适用于需要在每个窗口的重绘都进行重绘的情况。 另外,可以使用CListCtrl的SetRedraw函数来关闭重绘功能,然后手动进行重绘。通过调用SetRedraw(TRUE)函数来重新启用重绘功能。这种方法适用于批量修改列表控件的项的情况,可以加快重绘的速度。 最后,可以通过CListCtrl的SetItemData和GetItemData函数来定制列表项的显示。通过重写CListCtrl的DrawItem函数,可以对每个项进行自定义绘制。通过SetItemData函数设置项的数据,然后在DrawItem函数使用GetItemData函数获取数据,根据数据来绘制每个项的外观。 总结来说,MFC CListCtrl控件的重绘可以通过重写OnPaint函数、使用Invalidate函数、设置SetRedraw函数或者自定义DrawItem函数来实现。具体的方法选择需要根据实际需求和应用场景来决定。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Santiago

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值