MFC_ListView

1. 获取当前选择行
2. 添加图片列
3. 排序
4. 设置行高(待更好方法)
5. 固定列宽 (重载OnNotify函数)


1. 获取CListCtrl控件当前选择行的某一列数据
CListCtrl& rList = GetListCtrl();
POSITION pos = rList.GetFirstSelectedItemPosition();
//while(pos!=NULL)//选中多个
if(pos!=NULL))//只选1个
{
  int nItem = rList.GetNextSelectedItem(pos);
  CString st = rList.GetItemText(nItem, 0);
  AfxMessageBox(st);
}

2. 添加图片列

//设置

	CListCtrl& wndList = GetListCtrl();
	DWORD dwStyle = wndList.GetExtendedStyle();
	dwStyle = dwStyle|LVS_EX_FULLROWSELECT|LVS_NOSCROLL|LVS_EX_SUBITEMIMAGES;// LVS_EX_SUBITEMIMAGES
	wndList.SetExtendedStyle(dwStyle); //设置扩展风格

	wndList.SetImageList(&m_ImagesList, LVSIL_SMALL);//m_ImagesList 为CImageList* 
	wndList.InsertColumn(0, _T("From"), LVCFMT_LEFT, 100);
	wndList.InsertColumn(1, _T("Subject"), LVCFMT_LEFT, 200);

//添加
//当有 LVS_SORTASCENDING风格时, 插入某行时, insertItem返回值为插入到第j行
int j = wndList.InsertItem(1, _T("tom"), 0);
wndList.SetItem(j, 2, LVIF_TEXT|LVIF_IMAGE, NULL, 3,0, 0, 0);
//3表示图象索引,2表示要插入的列 

3. 排序
点击列的标题进行排序。
(上传MyListView.h中类CMyListView即实现了此功能, 但有所改变, 可调用 CallSort(int nSortCol, BOOL dftOrder = FALSE) 进行排序)
在添加该消息响应函数前,先要定义实现排序的回调函数。 有些应用中, 第一列是图像帧号, 按自然数排列,其他按字串排列,两个比较的回调函数。


步骤:
  a. 在MyListView.h中声明两个静态的回调函数:
	static int CALLBACK ListViewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);//按字串排序
	static int CALLBACK ListViewCompareIntFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);//按自然数排序
      在.cpp中实现:
	int CALLBACK ListViewCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
	{
		//得到排序方式
		int *pisorder = (int*)lParamSort;
		//得到两个列的排序信息
		TCHAR *sz1 = (TCHAR*)lParam1;
		TCHAR *sz2 = (TCHAR*)lParam2;//得到两个列的排序信息
		//比较, 若为降序, 则将结果 * -1
		if(*pisortorder == LVS_SORTASCENDING)
			return lstrcmp(sz1, sz2);
		else
			return lstrcmp(sz1, sz2) * (-1);
	}

	int CALLBACK CMyListView::ListViewCompareIntFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
	{
		int *pisortorder = (int*)lParamSort;//得到排序方式
		TCHAR *sz1 = (TCHAR*)lParam1;
		TCHAR *sz2 = (TCHAR*)lParam2;//得到两个列的排序信息
		int n1 = _ttoi(sz1);//? 不用单独提出int
		int n2 = _ttoi(sz2);	


		if(*pisortorder == LVS_SORTASCENDING)
		{
			if(n1 - n2 > 0) return 1;
			else if(n1 - n2 == 0) return 0;
			else return -1;
		}
		else
		{
			if(n1 - n2 > 0) return -1;
			else if(n1 - n2 == 0) return 0;
			else return 1;
		}
	}

  b. 通过向导(或手动)为事件LVN_COLUMNCLICK添加消息响应函数 OnColumnClick(). 点击表头。
1. .h中声明 afx_msg void OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult);
  .cpp中
	IMPLEMENT_DYNCREATE(CMyListView, CListView)
	BEGIN_MESSAGE_MAP(CMyListView, CListView)
		ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)
	END_MESSAGE_MAP()

  并实现:
void  CMyListView::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult)
	{
		static int ncurSortCol = -1;//保存当前的排序列

		NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;	

		CListCtrl* rList = &GetListCtrl();

		LONG ws = GetWindowLong(rList->m_hWnd, GWL_STYLE);
		int nSortOrder;//排序的方式, 升序降序

		//若点击列与当前排序列不同, 则改变排序列, 并将排序方式定为增序(降序也可)
		//若相同, 则更改排序方式。
		if(ncurSortCol == pNMListView->iSubItem)
		{


			if(ws & LVS_SORTASCENDING)
			{
				ws ^= LVS_SORTASCENDING;
				nSortOrder = LVS_SORTDESCENDING;
			}
			else
			{
				ws ^= LVS_SORTDESCENDING;
				nSortOrder = LVS_SORTASCENDING;
			}
		}
		else
		{
			if(ws & LVS_SORTASCENDING)
			{
				//ws ^= LVS_SORTASCENDING;//文中没有,但是否需要?
				nSortOrder = LVS_SORTDESCENDING;
				ncurSortCol = pNMListView->iSubItem;
			}
			else
			{
				//ws ^= LVS_SORTDESCENDING;
				nSortOrder = LVS_SORTASCENDING;
				ncurSortCol = pNMListView->iSubItem;
			}
		}
		//将当前的排序信息保存在窗口Style中,供以后使用。 
		ws |= nSortOrder;
		SetWindowLong(rList->m_hWnd, GWL_STYLE, ws);//将当前的排序信息保存在窗口Style中

		//将各item的lparam用新排序列的内容替换
		LVITEM li;
		li.mask = LVIF_PARAM | LVIF_TEXT;
		TCHAR szItemText[1024];
		for(int i=0; i<rList->GetItemCount(); i++)
		{
			li.iItem = i;
			li.iSubItem = ncurSortCol;
			li.cchTextMax = 1024;
			li.pszText = szItemText;


			rList->GetItem(&li);
			TCHAR* szlparam = (TCHAR*)li.lParam;


			//删除以前的信息, 释放空间
			//添加list item时应注意将lParam初始化NULL.
			if(szlparam != NULL)
				delete szlparam;
			//复制当前列的szitemtext到item的lparam中
			szlparam = new TCHAR[lstrlen(szItemText)+1];
			lstrcpy(szlparam, szItemText);
			rList->SetItemData(i, DWORD(szlparam));
		}
		//开始排序
		if(ncurSortCol == 0) //第一排按整数排序
		{
			rList->SortItems(ListViewCompareIntFunc, (LPARAM)(&nSortOrder));
		}
		else
		{
			rList->SortItems(ListViewCompareFunc, (LPARAM)(&nSortOrder));
		}

		*pResult = 0;
	}


4. 设置行高(待更好的方法)
这里行高变为20. 适应“图片”大小
m_ImagesList.Create(5, 20, ILC_COLOR32, 5, 5);
GetListCtrl().SetImageList(&m_ImagesList, LVSIL_SMALL);


5. 固定列宽
.h 类中添加重载函数和成员变量/函数如下:
	virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);

	std::vector<int> m_vFrozenCols;//用来记录固定列宽的列
	void FreezeColumn(int col);

.cpp中
void CMyListView::FreezeColumn(int col)
{
	m_vFrozenCols.push_back(col);
}

BOOL CMyListView::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	int len = m_vFrozenCols.size();
	if(len > 0)
	{
		HD_NOTIFY* pHDN = (HD_NOTIFY*)lParam;
		switch(((NMHDR*)lParam)->code)
		{
		case HDN_BEGINTRACKW:
		case HDN_BEGINTRACKA:
		case HDN_DIVIDERDBLCLICKA:
		case HDN_DIVIDERDBLCLICKW:
			for(int i=0; i<len; i++)
			{
				if(pHDN->iItem == m_vFrozenCols[i]) //如果拖动的列是设定固定列宽的列之一
				{
					*pResult = TRUE;
					return TRUE;
				}
			}
		}
	}
	return CListView::OnNotify(wParam, lParam, pResult);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值