CListCtrl自動排序及添加排序箭頭

應客戶要求,在點擊CListCtrl列表每列標題時進行排序,類似於WINDOWS資源管理器的效果。

首先在資源中添加LVN_COLUMNCLICK消息,生成OnLvnColumnclickListInfo函數,在函數裏進行處理即可。

1.最最笨的方法是點擊標題時,依次獲取每行的內容,自己比較排序,這裏不多說,略過。


2.用控制自帶的排序功能。

1)爲了能顯示箭頭,在列表初始化時增加圖標,如下

	CHeaderCtrl *pHeaderCtrl=m_ListCtrl.GetHeaderCtrl();

	m_ImageList.Create(16,16,ILC_COLOR16 | ILC_MASK,0,4);
	m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1));//IDI_ICON1和IDI_ICON2是自己資源中的箭頭ID,類型爲ICON
	m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
	pHeaderCtrl->SetImageList(&m_ImageList);//m_ImageList是頭文件中申明的CImageList m_ImageList

	

2.進行排序並顯示箭頭

int sort_column=-1; // 記錄點擊的列
bool method = false; // 記錄比較方法
// 比較函數
static int CALLBACK MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
	// 從參數中提取所需比較lc的兩行數據	
	int row1 = (int)lParam1;//這裏的參數實際是SetItemData函數設置的值,比較的第一列
	int row2 =(int)lParam2;//這裏的參數實際是SetItemData函數設置的值,比較的第二列
	CListCtrl* lc= (CListCtrl*)lParamSort;
	CString lp1 = lc->GetItemText(row1,sort_column);
	CString lp2 = lc->GetItemText(row2,sort_column); 
	LPCTSTR s1=(LPCTSTR)lp1; 
	LPCTSTR s2=(LPCTSTR)lp2;
	 // 比較,對不同的列,不同比較,注意記錄前一次排序方向,下一次要相反排序		 
	if (method)
	{
		return  strcmp(s2,s1);
	}
	else
	{
		return  strcmp(s1,s2);
	}
}
void CDlgWorklistInfo::OnLvnColumnclickListInfo(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV =reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	
	sort_column = pNMLV->iSubItem;//點擊的列

	int count = m_ListCtrl.GetItemCount();

	for (int i = 0; i< count ; i++)
	{
		 
		m_ListCtrl.SetItemData(i,i);//在排序前一定用這個函數設置每行值,類似於自定義索引
		
	}
	// 自定義圖標排序箭頭樣式  
	CHeaderCtrl* pHdrCtrl = m_ListCtrl.GetHeaderCtrl();  
	if(pHdrCtrl && pHdrCtrl->GetSafeHwnd())    
	{  
		int n = pHdrCtrl->GetItemCount();  

		HDITEM hdi={0};  
		TCHAR szBuf[129] = {0};       
		hdi.mask = HDI_TEXT; //取字符掩碼     
		hdi.pszText = szBuf; //字符緩衝區     
		hdi.cchTextMax = 128; //緩衝區大小    
		for( int i = 0; i < n; i++ )  
		{  
			hdi.mask = HDI_IMAGE | HDI_FORMAT;  // 讀取排序箭頭圖標狀態,必需指定  
			pHdrCtrl->GetItem(i, &hdi);  
			if( i == sort_column )  
			{  
				if( hdi.fmt & HDF_IMAGE )   //前後2次點擊同一列時, 已經排序,改變升降序,並切換箭頭圖標。  
				{  
					hdi.iImage = 1 - hdi.iImage;  
					method = !method;
				}  
				else  //前後點擊不同列時圖標顯示在新點擊列頭
				{  
					hdi.iImage = 0;  
					hdi.fmt |= HDF_IMAGE | HDF_BITMAP_ON_RIGHT;  
					if (method)//爲了保證新點擊的列與上次顯示一致
					{
						hdi.iImage = 1 - hdi.iImage;
					}
				}  
			}  
			else  
			{  
				hdi.mask = HDI_FORMAT;  
				hdi.fmt &= ~HDF_IMAGE & ~HDF_BITMAP_ON_RIGHT;  
			}  

			pHdrCtrl->SetItem( i, &hdi );  
		}  
	}
	m_ListCtrl.SortItems(MyCompareProc,(DWORD)&m_ListCtrl);//排序第二個參數是比較函數的第三個參數

	*pResult =0;
}


總結:另外網上有說用CMFCListCtrl類(VS2008以上)比較好用,有興趣可以自己試試。還有調試過程中用的是第三方類繼承CListCtrl導致
LPARAM lParam1, LPARAM lParam2
始終傳過來是很大的隨機值,後面直接換回微軟自帶的CListCtrl解決。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章