CListCtrl中加入排序小图标,CHeaderCtrl::GetItem可能被误用。

因为项目需求,要在CListCtrl中加上排序小图标,Google到博文http://blog.csdn.net/liujiannanit125/article/details/6249039,感谢博主的奉献。不过实际使用中出现一个问题,加上这段代码后,经常出现写入内存错误,时有时无,很不好找原因。怀疑是pHdrCtrl->SetItem( i, &hdi );语句写入时出错,注释后故障以旧,多次调试后发现注释pHdrCtrl->GetItem(i, &hdi);语句后,故障消失。为什么读取信息出现写入内存错误呢,百思不得其解。

再次仔细阅读msdn的说明和例子后恍然大悟,GetItem的第二个参数即是输入参数又是输出参数,调用前必需在hdi.mask中指定获取哪些参数。获取标题文字的代码如下:

HDITEM hdi;
enum   { sizeOfBuffer = 256 };
TCHAR  lpBuffer[sizeOfBuffer];
hdi.mask = HDI_TEXT;
hdi.pszText = lpBuffer;
hdi.cchTextMax = sizeOfBuffer;

问题就出在这里,原文中没有初始化 hdi.mask 而直接调用 GetItem,hdi.mask 的内容是随机的,碰巧包含HDI_TEXT,就会对 hdi.pszText 写入标题文字,hdi.pszText 也是随机的,可能是非法地址,于是出现有时能用,有时报错的情况。下面有意写一段错误代码,果然每次都出错。

hdi.mask = HDI_TEXT;
hdi.pszText = (LPTSTR)1;
hdi.cchTextMax = 100;
m_myHeaderCtrl.GetItem(i, &hdi);

问题找到了,新写代码与下,经测试没有发现问题。

	const CString sorts[] = { NULL, NULL, L"number", L"CONVERT(name USING GBK)", L"sex", L"birthday",
		L"age", L"regday", L"scanday", L"importday", L"scancount", L"note" };	// 第一列是ID列, 第二列是序号列,不排序。

	LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);


// 自定义图标排序箭头样式
	CHeaderCtrl* pHdrCtrl = GetHeaderCtrl();
	int n = pHdrCtrl->GetItemCount();
	ASSERT( n == sizeof(sorts)/sizeof(CString) );	// 列数与数组一致
	
	m_strOrderby = sorts[ phdr->iItem ];
	if( m_strOrderby.IsEmpty() )	// 没有排序
		return;

	HDITEM hdi;
	for( int i = 0; i < n; i++ )
	{
		hdi.mask = HDI_IMAGE | HDI_FORMAT;	// 读取排序箭头图标状态,必需指定
		pHdrCtrl->GetItem(i, &hdi);
		if( i == phdr->iItem )
		{
			if( hdi.fmt & HDF_IMAGE )	// 已经排序,改变升降序。
			{
				hdi.iImage = 1 - hdi.iImage;
			}
			else
			{
				hdi.iImage = 0;
				hdi.fmt |= HDF_IMAGE | HDF_BITMAP_ON_RIGHT;
			}
			if( hdi.iImage )
				m_strOrderby += " DESC";
		}
		else
		{
			hdi.mask = HDI_FORMAT;
			hdi.fmt &= ~HDF_IMAGE & ~HDF_BITMAP_ON_RIGHT;
		}

		pHdrCtrl->SetItem( i, &hdi );
	}


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值