在ListCtrl中進行排序 (轉)
在ListCtrl中進行排序 (轉)[@more@]//轉自MFC開發指南,/">
在ListCtrl中進行排序
聞怡洋 wyy_cq@21cn.
列表(CListCtrl)的頂部有一排按鈕,可以透過選擇不同的列來對記錄進行排序。但是 CListCtrl並沒有自動排序的功能,我們需要自己新增一個用於排序的回撥來比較兩個資料的大小,此外還需要響應排序按鈕被點選的訊息。下面講述一下具體的做法。
CListCtrl提供了用於排序的函式,函式原型為:BOOL CListCtrl::SortItems( PFNLVCOMPARE pfnCompare, D dwData )。其中第一個引數為全域性排序函式的地址,第二個引數為使用者資料,你可以根據你的需要傳遞一個資料或是指標。該函式返回-1代表第一項排應在第二項前面,返回1代表第一項排應在第二項後面,返回0代表兩項相等。
用於排序的函式原形為:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort),其中第三個引數為者傳遞的資料(即呼叫SortItems時的第二個引數dwData)。第一和第二個引數為用於比較的兩項的ItemData,你可以透過DWORD CListCtrl::GetItemData( int nItem )/BOOL CListCtrl::SetItemData( int nItem, DWORD dwData )來對每一項的ItemData進行存取。在新增項時選用特定的CListCtrl::InsertItem也可以設定該值。由於你在排序時只能透過該值來確定項的位置所以你應該比較明確的確定該值的含義。
最後一點,我們需要知道什麼時候需要排序,實現這點可以在父視窗中對LVN_COLUMNCLICK訊息進行處理來實現。
下面我們看一個例子,這個例子是一個派生類,並支援順序/倒序兩種方式排序。為了簡單我對全域性資料進行排序,而在實際應用中會有多組需要排序的資料,所以需要透過傳遞引數的方式來告訴派序函式需要對什麼資料進行排序。
//全域性資料
struct DEMO_DATA
{
char szName[20];
int iAge;
}strAllData[5]={{"王某",30},{"張某",40},{"武某",32},{"陳某",20},{"李某",36}};
//CListCtrl派生類定義
class CSortList : public CListCtrl
{
// Construction
public:
CSortList();
BOOL m_fAsc;//是否順序排序
int m_nSortedCol;//當前排序的列
protected:
//{{AFX_MSG(CSortList)
//}}AFX_MSG
...
};
//父視窗中包含該CListCtrl派生類
class CSort_in_list_ctrlDlg : public CDialog
{
// Construction
public:
CSort_in_list_ctrlDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CSort_in_list_ctrlDlg)
enum { IDD = IDD_SORT_IN_LIST_CTRL_DIALOG };
CSortList m_listTest;
//}}AFX_DATA
}
//在父視窗中定義LVN_COLUMNCLICK訊息對映
BEGIN_MESSAGE_MAP(CSort_in_list_ctrlDlg, CDialog)
//{{AFX_MSG_MAP(CSort_in_list_ctrlDlg)
ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST1, OnColumnclickList1)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//初始化資料
BOOL CSort_in_list_ctrlDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//初始化ListCtrl中資料列表
m_listTest.InsertColumn(0,"姓名");
m_listTest.InsertColumn(1,"年齡");
m_listTest.SetColumnWidth(0,80);
m_listTest.SetColumnWidth(1,80);
for(int i=0;i<5;i++)
{
m_listTest.InsertItem(i,strAllData[i].szName);
char szAge[10];
sprintf(szAge,"%d",strAllData[i].iAge);
m_listTest.SetItemText(i,1,szAge);
//設定每項的ItemData為陣列中資料的
//在排序函式中透過該ItemData來確定資料
m_listTest.SetItemData(i,i);
}
return TRUE; // return TRUE unless you set the focus to a control
}
//處理訊息
void CSort_in_list_ctrlDlg::OnColumnclickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
//設定排序方式
if( pNMListView->iSubItem == m_listTest.m_nSortedCol )
m_listTest.m_fAsc = !m_listTest.m_fAsc;
else
{
m_listTest.m_fAsc = TRUE;
m_listTest.m_nSortedCol = pNMListView->iSubItem;
}
//呼叫排序函式
m_listTest.SortItems( ListCompare, (DWORD)&m_listTest );
*pResult = 0;
}
//排序函式實現
int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
//透過傳遞的引數來得到CSortList物件指標,從而得到排序方式
CSortList* pV=(CSortList*)lParamSort;
//透過ItemData來確定資料
DEMO_DATA* pInfo1=strAllData+lParam1;
DEMO_DATA* pInfo2=strAllData+lParam2;
CString szComp1,szComp2;
int iCompRes;
switch(pV->m_nSortedCol)
{
case(0):
//以第一列為根據排序
szComp1=pInfo1->szName;
szComp2=pInfo2->szName;
iCompRes=szComp1.Compare(szComp2);
break;
case(1):
//以第二列為根據排序
if(pInfo1->iAge == pInfo2->iAge)
iCompRes = 0;
else
iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;
break;
default:
ASSERT(0);
break;
}
//根據當前的排序方式進行調整
if(pV->m_fAsc)
return iCompRes;
else
return iCompRes*-1;
}
本文示範程式碼
在ListCtrl中進行排序
聞怡洋 wyy_cq@21cn.
列表(CListCtrl)的頂部有一排按鈕,可以透過選擇不同的列來對記錄進行排序。但是 CListCtrl並沒有自動排序的功能,我們需要自己新增一個用於排序的回撥來比較兩個資料的大小,此外還需要響應排序按鈕被點選的訊息。下面講述一下具體的做法。
CListCtrl提供了用於排序的函式,函式原型為:BOOL CListCtrl::SortItems( PFNLVCOMPARE pfnCompare, D dwData )。其中第一個引數為全域性排序函式的地址,第二個引數為使用者資料,你可以根據你的需要傳遞一個資料或是指標。該函式返回-1代表第一項排應在第二項前面,返回1代表第一項排應在第二項後面,返回0代表兩項相等。
用於排序的函式原形為:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort),其中第三個引數為者傳遞的資料(即呼叫SortItems時的第二個引數dwData)。第一和第二個引數為用於比較的兩項的ItemData,你可以透過DWORD CListCtrl::GetItemData( int nItem )/BOOL CListCtrl::SetItemData( int nItem, DWORD dwData )來對每一項的ItemData進行存取。在新增項時選用特定的CListCtrl::InsertItem也可以設定該值。由於你在排序時只能透過該值來確定項的位置所以你應該比較明確的確定該值的含義。
最後一點,我們需要知道什麼時候需要排序,實現這點可以在父視窗中對LVN_COLUMNCLICK訊息進行處理來實現。
下面我們看一個例子,這個例子是一個派生類,並支援順序/倒序兩種方式排序。為了簡單我對全域性資料進行排序,而在實際應用中會有多組需要排序的資料,所以需要透過傳遞引數的方式來告訴派序函式需要對什麼資料進行排序。
//全域性資料
struct DEMO_DATA
{
char szName[20];
int iAge;
}strAllData[5]={{"王某",30},{"張某",40},{"武某",32},{"陳某",20},{"李某",36}};
//CListCtrl派生類定義
class CSortList : public CListCtrl
{
// Construction
public:
CSortList();
BOOL m_fAsc;//是否順序排序
int m_nSortedCol;//當前排序的列
protected:
//{{AFX_MSG(CSortList)
//}}AFX_MSG
...
};
//父視窗中包含該CListCtrl派生類
class CSort_in_list_ctrlDlg : public CDialog
{
// Construction
public:
CSort_in_list_ctrlDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CSort_in_list_ctrlDlg)
enum { IDD = IDD_SORT_IN_LIST_CTRL_DIALOG };
CSortList m_listTest;
//}}AFX_DATA
}
//在父視窗中定義LVN_COLUMNCLICK訊息對映
BEGIN_MESSAGE_MAP(CSort_in_list_ctrlDlg, CDialog)
//{{AFX_MSG_MAP(CSort_in_list_ctrlDlg)
ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST1, OnColumnclickList1)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//初始化資料
BOOL CSort_in_list_ctrlDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//初始化ListCtrl中資料列表
m_listTest.InsertColumn(0,"姓名");
m_listTest.InsertColumn(1,"年齡");
m_listTest.SetColumnWidth(0,80);
m_listTest.SetColumnWidth(1,80);
for(int i=0;i<5;i++)
{
m_listTest.InsertItem(i,strAllData[i].szName);
char szAge[10];
sprintf(szAge,"%d",strAllData[i].iAge);
m_listTest.SetItemText(i,1,szAge);
//設定每項的ItemData為陣列中資料的
//在排序函式中透過該ItemData來確定資料
m_listTest.SetItemData(i,i);
}
return TRUE; // return TRUE unless you set the focus to a control
}
//處理訊息
void CSort_in_list_ctrlDlg::OnColumnclickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
//設定排序方式
if( pNMListView->iSubItem == m_listTest.m_nSortedCol )
m_listTest.m_fAsc = !m_listTest.m_fAsc;
else
{
m_listTest.m_fAsc = TRUE;
m_listTest.m_nSortedCol = pNMListView->iSubItem;
}
//呼叫排序函式
m_listTest.SortItems( ListCompare, (DWORD)&m_listTest );
*pResult = 0;
}
//排序函式實現
int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
//透過傳遞的引數來得到CSortList物件指標,從而得到排序方式
CSortList* pV=(CSortList*)lParamSort;
//透過ItemData來確定資料
DEMO_DATA* pInfo1=strAllData+lParam1;
DEMO_DATA* pInfo2=strAllData+lParam2;
CString szComp1,szComp2;
int iCompRes;
switch(pV->m_nSortedCol)
{
case(0):
//以第一列為根據排序
szComp1=pInfo1->szName;
szComp2=pInfo2->szName;
iCompRes=szComp1.Compare(szComp2);
break;
case(1):
//以第二列為根據排序
if(pInfo1->iAge == pInfo2->iAge)
iCompRes = 0;
else
iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;
break;
default:
ASSERT(0);
break;
}
//根據當前的排序方式進行調整
if(pV->m_fAsc)
return iCompRes;
else
return iCompRes*-1;
}
本文示範程式碼
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990596/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 在Java中對集合當中的物件進行排序Java物件排序
- 對list集合中的物件進行排序(轉載)物件排序
- 在命令列用 sort 進行排序命令列排序
- 在JavaScript中對HTML進行反轉義JavaScriptHTML
- 使用XPathExpression類對XML進行排序 (轉)ExpressXML排序
- 在 Oracle JDeveloper 中進行 Ajax 程式設計(轉)OracleDeveloper程式設計
- 根據陣列中物件進行排序陣列物件排序
- 當單擊DBGrid中的標題欄時,進行排序 (轉)排序
- 在Linux Shell程式中進行身份驗證(轉)Linux
- iOS中對NSArray中自定義的物件進行排序iOS物件排序
- 在Linux命令列中進行大小寫字元轉換Linux命令列字元
- 對字典進行排序排序
- 如何在dhtmlxGantt網格中對任務進行排序和重新排序HTML排序
- 如何在Python中對dicts列表進行排序Python排序
- 4.10 如何在Java中進行排序開發Java排序
- 在開發專案中進行有效的專案管理(轉)專案管理
- 重疊IO操作在進行中
- 怎樣在squid中透過URL進行訪問控制(轉)UI
- 在Linux Shell程式中進行身份驗證[修訂版] (轉)Linux
- 使用go在mongodb中進行CRUD操作MongoDB
- 在 WebSphere Process Server 中進行版本管理WebServer
- 工作在矛盾糾結中進行著
- 在Linux行內直接進行大小寫轉換Linux
- Linux中ls對檔案進行按大小排序和按時間排序Linux排序
- Python對字典進行排序Python排序
- 陣列進行排序的方法陣列排序
- 對N個數進行排序排序
- 用c#進行快速排序C#排序
- java對中文(拼音)進行排序Java排序
- 如何使用Web3.js API 在頁面中進行轉賬WebJSAPI
- Rust 在 cargo 中進行條件編譯RustCargo編譯
- 在Javascript中進行面向切面程式設計JavaScript程式設計
- 在TypeScript專案中進行BDD測試TypeScript
- 在oracle中Logmnr進行日誌挖掘Oracle
- 在C#中進行單元測試C#
- 用“歸併”改進“快速排序” (轉)排序
- Map按照key和value進行排序排序
- 使用索引掃描來進行排序索引排序