原文出處:http://blog.csdn.net/bqw2008/article/details/2047489
 Windows ListCtrl使用技巧
1. ListCtrl 風(fēng)格
LVS_ICON: 為每個(gè)item顯示大圖標(biāo)
LVS_SMALLICON: 為每個(gè)item顯示小圖標(biāo)
LVS_LIST: 顯示一列帶有小圖標(biāo)的item
LVS_REPORT: 顯示item詳細(xì)資料

直觀的理解:windows資源管理器,“查看”標(biāo)簽下的“大圖標(biāo),小圖標(biāo),列表,詳細(xì)資料”
--------------------------------------------------------------------------------
2. 設(shè)置listctrl 風(fēng)格及擴(kuò)展風(fēng)格 LONG lStyle;
lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//獲取當(dāng)前窗口style
lStyle &= ~LVS_TYPEMASK; //清除顯示方式位
lStyle |= LVS_REPORT; //設(shè)置style
SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//設(shè)置style

DWORD dwStyle = m_list.GetExtendedStyle();
dwStyle |= LVS_EX_FULLROWSELECT;//選中某行使整行高亮(只適用與report風(fēng)格的listctrl)
dwStyle |= LVS_EX_GRIDLINES;//網(wǎng)格線(只適用與report風(fēng)格的listctrl)
dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件
m_list.SetExtendedStyle(dwStyle); //設(shè)置擴(kuò)展風(fēng)格

注:listview的style請(qǐng)查閱msdn
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceshellui5/html/wce50lrflistviewstyles.asp
--------------------------------------------------------------------------------
3. 插入數(shù)據(jù) m_list.InsertColumn( 0, "ID", LVCFMT_LEFT, 40 );//插入列
m_list.InsertColumn( 1, "NAME", LVCFMT_LEFT, 50 );
int nRow = m_list.InsertItem(0, “11”);//插入行
m_list.SetItemText(nRow, 1, “jacky”);//設(shè)置數(shù)據(jù)
--------------------------------------------------------------------------------
4. 一直選中item 選中style中的Show selection always,或者在上面第2點(diǎn)中設(shè)置LVS_SHOWSELALWAYS

--------------------------------------------------------------------------------
5. 選中和取消選中一行 int nIndex = 0;
//選中
m_list.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);
//取消選中
m_list.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);
--------------------------------------------------------------------------------
6. 得到listctrl中所有行的checkbox的狀態(tài) m_list.SetExtendedStyle(LVS_EX_CHECKBOXES);
CString str;
for(int i=0; i<m_list.GetItemCount(); i++)
{
if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_list.GetCheck(i))
{
str.Format(_T("第%d行的checkbox為選中狀態(tài)"), i);
AfxMessageBox(str);
}
}
--------------------------------------------------------------------------------
7. 得到listctrl中所有選中行的序號(hào)
方法一:
CString str;
for(int i=0; i<m_list.GetItemCount(); i++)
{
if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED )
{
str.Format(_T("選中了第%d行"), i);
AfxMessageBox(str);
}
}

方法二:
POSITION pos = m_list.GetFirstSelectedItemPosition();
if (pos == NULL)
TRACE0("No items were selected!/n");
else
{
while (pos)
{
int nItem = m_list.GetNextSelectedItem(pos);
TRACE1("Item %d was selected!/n", nItem);
// you could do your own processing on nItem here
}
}
--------------------------------------------------------------------------------
8. 得到item的信息 TCHAR szBuf[1024];
LVITEM lvi;
lvi.iItem = nItemIndex;
lvi.iSubItem = 0;
lvi.mask = LVIF_TEXT;
lvi.pszText = szBuf;
lvi.cchTextMax = 1024;
m_list.GetItem(&lvi);

關(guān)于得到設(shè)置item的狀態(tài),還可以參考msdn文章
Q173242: Use Masks to Set/Get Item States in CListCtrl
http://support.microsoft.com/kb/173242/en-us
--------------------------------------------------------------------------------
9. 得到listctrl的所有列的header字符串內(nèi)容 LVCOLUMN lvcol;
char str[256];
int nColNum;
CString strColumnName[4];//假如有4列

nColNum = 0;
lvcol.mask = LVCF_TEXT;
lvcol.pszText = str;
lvcol.cchTextMax = 256;
while(m_list.GetColumn(nColNum, &lvcol))
{
strColumnName[nColNum] = lvcol.pszText;
nColNum++;
}
--------------------------------------------------------------------------------
10. 使listctrl中一項(xiàng)可見,即滾動(dòng)滾動(dòng)條 m_list.EnsureVisible(i, FALSE);
--------------------------------------------------------------------------------
11. 得到listctrl列數(shù) int nHeadNum = m_list.GetHeaderCtrl()->GetItemCount();
--------------------------------------------------------------------------------
12. 刪除所有列 方法一:
while ( m_list.DeleteColumn (0))
因?yàn)槟銊h除了第一列后,后面的列會(huì)依次向上移動(dòng)。

方法二:
int nColumns = 4;
for (int i=nColumns-1; i>=0; i--)
m_list.DeleteColumn (i);
--------------------------------------------------------------------------------
13. 得到單擊的listctrl的行列號(hào) 添加listctrl控件的NM_CLICK消息相應(yīng)函數(shù)
void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
// 方法一:
/*
DWORD dwPos = GetMessagePos();
CPoint point( LOWORD(dwPos), HIWORD(dwPos) );

m_list.ScreenToClient(&point);

LVHITTESTINFO lvinfo;
lvinfo.pt = point;
lvinfo.flags = LVHT_ABOVE;

int nItem = m_list.SubItemHitTest(&lvinfo);
if(nItem != -1)
{
CString strtemp;
strtemp.Format("單擊的是第%d行第%d列", lvinfo.iItem, lvinfo.iSubItem);
AfxMessageBox(strtemp);
}
*/

// 方法二:
/*
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if(pNMListView->iItem != -1)
{
CString strtemp;
strtemp.Format("單擊的是第%d行第%d列",
pNMListView->iItem, pNMListView->iSubItem);
AfxMessageBox(strtemp);
}
*/
*pResult = 0;
}
--------------------------------------------------------------------------------
14. 判斷是否點(diǎn)擊在listctrl的checkbox上 添加listctrl控件的NM_CLICK消息相應(yīng)函數(shù)
void CTest6Dlg::OnClickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
DWORD dwPos = GetMessagePos();
CPoint point( LOWORD(dwPos), HIWORD(dwPos) );

m_list.ScreenToClient(&point);

LVHITTESTINFO lvinfo;
lvinfo.pt = point;
lvinfo.flags = LVHT_ABOVE;

UINT nFlag;
int nItem = m_list.HitTest(point, &nFlag);
//判斷是否點(diǎn)在checkbox上
if(nFlag == LVHT_ONITEMSTATEICON)
{
AfxMessageBox("點(diǎn)在listctrl的checkbox上");
}
*pResult = 0;
}
--------------------------------------------------------------------------------
15. 右鍵點(diǎn)擊listctrl的item彈出菜單 添加listctrl控件的NM_RCLICK消息相應(yīng)函數(shù)
void CTest6Dlg::OnRclickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if(pNMListView->iItem != -1)
{
DWORD dwPos = GetMessagePos();
CPoint point( LOWORD(dwPos), HIWORD(dwPos) );

CMenu menu;
VERIFY( menu.LoadMenu( IDR_MENU1 ) );
CMenu* popup = menu.GetSubMenu(0);
ASSERT( popup != NULL );
popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this );
}
*pResult = 0;
}
--------------------------------------------------------------------------------
16. item切換焦點(diǎn)時(shí)(包括用鍵盤和鼠標(biāo)切換item時(shí)),狀態(tài)的一些變化順序 添加listctrl控件的LVN_ITEMCHANGED消息相應(yīng)函數(shù)
void CTest6Dlg::OnItemchangedList1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// TODO: Add your control notification handler code here

CString sTemp;

if((pNMListView->uOldState & LVIS_FOCUSED) == LVIS_FOCUSED &&
(pNMListView->uNewState & LVIS_FOCUSED) == 0)
{
sTemp.Format("%d losted focus",pNMListView->iItem);
}
else if((pNMListView->uOldState & LVIS_FOCUSED) == 0 &&
(pNMListView->uNewState & LVIS_FOCUSED) == LVIS_FOCUSED)
{
sTemp.Format("%d got focus",pNMListView->iItem);
}

if((pNMListView->uOldState & LVIS_SELECTED) == LVIS_SELECTED &&
(pNMListView->uNewState & LVIS_SELECTED) == 0)
{
sTemp.Format("%d losted selected",pNMListView->iItem);
}
else if((pNMListView->uOldState & LVIS_SELECTED) == 0 &&
(pNMListView->uNewState & LVIS_SELECTED) == LVIS_SELECTED)
{
sTemp.Format("%d got selected",pNMListView->iItem);
}

*pResult = 0;
}
--------------------------------------------------------------------------------
20. listctrl的subitem添加圖標(biāo) m_list.SetExtendedStyle(LVS_EX_SUBITEMIMAGES);
m_userlist.SetItem(..); //具體參數(shù)請(qǐng)參考msdn
--------------------------------------------------------------------------------
21. 在CListCtrl顯示文件,并根據(jù)文件類型來(lái)顯示圖標(biāo) 網(wǎng)上找到的代碼,share
BOOL CTest6Dlg::OnInitDialog()
{
CDialog::OnInitDialog();

HIMAGELIST himlSmall;
HIMAGELIST himlLarge;
SHFILEINFO sfi;
char cSysDir[MAX_PATH];
CString strBuf;

memset(cSysDir, 0, MAX_PATH);

GetWindowsDirectory(cSysDir, MAX_PATH);
strBuf = cSysDir;
sprintf(cSysDir, "%s", strBuf.Left(strBuf.Find("file:///));

himlSmall = (HIMAGELIST)SHGetFileInfo ((LPCSTR)cSysDir,
0,
&sfi,
sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_SMALLICON );

himlLarge = (HIMAGELIST)SHGetFileInfo((LPCSTR)cSysDir,
0,
&sfi,
sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_LARGEICON);

if (himlSmall && himlLarge)
{
::SendMessage(m_list.m_hWnd, LVM_SETIMAGELIST,
(WPARAM)LVSIL_SMALL, (LPARAM)himlSmall);
::SendMessage(m_list.m_hWnd, LVM_SETIMAGELIST,
(WPARAM)LVSIL_NORMAL, (LPARAM)himlLarge);
}
return TRUE; // return TRUE unless you set the focus to a control
}

void CTest6Dlg::AddFiles(LPCTSTR lpszFileName, BOOL bAddToDocument)
{
int nIcon = GetIconIndex(lpszFileName, FALSE, FALSE);
CString strSize;
CFileFind filefind;

// get file size
if (filefind.FindFile(lpszFileName))
{
filefind.FindNextFile();
strSize.Format("%d", filefind.GetLength());
}
else
strSize = "0";

// split path and filename
CString strFileName = lpszFileName;
CString strPath;

int nPos = strFileName.ReverseFind('//');
if (nPos != -1)
{
strPath = strFileName.Left(nPos);
strFileName = strFileName.Mid(nPos + 1);
}

// insert to list
int nItem = m_list.GetItemCount();
m_list.InsertItem(nItem, strFileName, nIcon);
m_list.SetItemText(nItem, 1, strSize);
m_list.SetItemText(nItem, 2, strFileName.Right(3));
m_list.SetItemText(nItem, 3, strPath);
}

int CTest6Dlg::GetIconIndex(LPCTSTR lpszPath, BOOL bIsDir, BOOL bSelected)
{
SHFILEINFO sfi;
memset(&sfi, 0, sizeof(sfi));

if (bIsDir)
{
SHGetFileInfo(lpszPath,
FILE_ATTRIBUTE_DIRECTORY,
&sfi,
sizeof(sfi),
SHGFI_SMALLICON | SHGFI_SYSICONINDEX |
SHGFI_USEFILEATTRIBUTES |(bSelected ? SHGFI_OPENICON : 0));
return sfi.iIcon;
}
else
{
SHGetFileInfo (lpszPath,
FILE_ATTRIBUTE_NORMAL,
&sfi,
sizeof(sfi),
SHGFI_SMALLICON | SHGFI_SYSICONINDEX |
SHGFI_USEFILEATTRIBUTES | (bSelected ? SHGFI_OPENICON : 0));
return sfi.iIcon;
}
return -1;
}

--------------------------------------------------------------------------------
22. listctrl內(nèi)容進(jìn)行大數(shù)據(jù)量更新時(shí),避免閃爍 m_list.SetRedraw(FALSE);
//更新內(nèi)容
m_list.SetRedraw(TRUE);
m_list.Invalidate();
m_list.UpdateWindow();

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

創(chuàng)建圖形列表并和CListCtrl關(guān)聯(lián):
m_image_list.Create(IDB_CALLER2, 16, 10, RGB(192,192, 192));
m_image_list.SetBkColor( GetSysColor( COLOR_WINDOW ) );
m_caller_list.SetImageList( &m_image_list, LVSIL_SMALL);
為報(bào)表添加4列:
char *szColumn[]={"昵稱","IP地址","登陸時(shí)間","狀態(tài)"};
int widths[]={100,98,70,55};
LV_COLUMN lvc;
lvc.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM;
lvc.fmt=LVCFMT_LEFT;
for(int i=0;i<4;i++) {//插入各列
lvc.pszText=szColumn[i];
lvc.cx=widths[i];
lvc.iSubItem=i;
m_caller_list.InsertColumn(i,&lvc);
}
為報(bào)表添加兩項(xiàng),以附加方式添加:
char* data[4];
data[0]="所有人";
data[1]="0.0.0.0";
data[3]="在線";
data[2]=new char;
CTime now=CTime::GetCurrentTime();
CString temp = now.Format("%H:%M:%S");
data[2]=temp.GetBuffer(1);
LV_ITEM lvi;
lvi.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
lvi.iSubItem=0;
lvi.pszText=(char *)data[0];
lvi.iImage = 0;
lvi.iItem=0;
m_caller_list.InsertItem(&lvi);
for (int j=0;j<4;j++) m_caller_list.SetItemText(count,j,data[j]);
count++;
lvi.iImage = 1;
lvi.iItem=count;
m_caller_list.InsertItem(&lvi);
data[0]="cherami";
data[1]="127.0.0.1";
for (int n=0;n<4;n++) m_caller_list.SetItemText(count,n,data[n]);
count++;
設(shè)置報(bào)表的樣式
選中一整行:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_FULLROWSELECT);
繪制表格:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_GRIDLINES);
帶復(fù)選框:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_CHECKBOXES);
自動(dòng)切換:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_TRACKSELECT);
選定一行:
設(shè)置CListCtrl的Show selection always選項(xiàng)
SetItemState (iIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED)
選中一個(gè)或多個(gè)項(xiàng)目時(shí),會(huì)發(fā)送LVN_ITEMCHANGED消息,可以使用
GetSelectedCount()方法得到被選定的項(xiàng)的數(shù)目。
點(diǎn)擊列頭的消息響應(yīng):
ON_NOTIFY(HDN_ITEMCLICKW, 0, ResponseFunc)
消息,需要自己添加
或者:
ON_NOTIFY(LVN_COLUMNCLICK, ID_yourCtrl, ResponseFunc)//向?qū)砑?br />前者后響應(yīng),后者先響應(yīng)
響應(yīng)函數(shù):
ResponseFunc(NMHDR *pNMHDR, LRESULT *pResult)
雙擊CListCtrl中的ITEM的消息是及消息函數(shù):
ON_NOTIFY(NM_DBLCLK, ID_yourCtrl, ResponseFunc)
單擊ITEM的消息響應(yīng):
ON_NOTIFY(NM_CLICK, ID_yourCtrl, ResponseFunc)
ResponseFunc(NMHDR *pNMHDR, LRESULT *pResult)

HDN_ITEMCLICK 就是Header control Notify message for mouse left click on the Header control!
而HDN_ITEMCLICK是當(dāng)List View中存在一個(gè)Header Contrl時(shí),Header Ctrl通知父窗口List View的!
CListCtrl中的Item被選中觸發(fā)LBN_SELCHANGE(通過WM_COMMAND)消息!
刪除CListCtrl中選定的項(xiàng):
POSITION pos;
int nIndex;
for(; pos= GetFirstSelectedItemPosition();)
{
nIndex = GetNextSelectedItem(pos);
DeleteItem(nIndex);
}
在ListCtrl中進(jìn)行排序
列表控件(CListCtrl)的頂部有一排按鈕,用戶可以通過選擇不同的列來(lái)對(duì)記錄進(jìn)行排序。但是 CListCtrl并沒有自動(dòng)排序的功能,我們需要自己添加一個(gè)用于排序的回調(diào)函數(shù)來(lái)比較兩個(gè)數(shù)據(jù)的大小,此外還需要響應(yīng)排序按鈕被點(diǎn)擊的消息。下面講述一下具體的做法。
CListCtrl提供了用于排序的函數(shù),函數(shù)原型為:BOOL CListCtrl::SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData )。其中第一個(gè)參數(shù)為全局排序函數(shù)的地址,第二個(gè)參數(shù)為用戶數(shù)據(jù),你可以根據(jù)你的需要傳遞一個(gè)數(shù)據(jù)或是指針。該函數(shù)返回-1代表第一項(xiàng)排應(yīng)在第二項(xiàng)前面,返回1代表第一項(xiàng)排應(yīng)在第二項(xiàng)后面,返回0代表兩項(xiàng)相等。
用于排序的函數(shù)原形為:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort),其中第三個(gè)參數(shù)為調(diào)用者傳遞的數(shù)據(jù)(即調(diào)用SortItems時(shí)的第二個(gè)參數(shù)dwData)。第一和第二個(gè)參數(shù)為用于比較的兩項(xiàng)的ItemData,你可以通過DWORD CListCtrl::GetItemData( int nItem )/BOOL CListCtrl::SetItemData( int nItem, DWORD dwData )來(lái)對(duì)每一項(xiàng)的ItemData進(jìn)行存取。在添加項(xiàng)時(shí)選用特定的CListCtrl::InsertItem也可以設(shè)置該值。由于你在排序時(shí)只能通過該值來(lái)確定項(xiàng)的位置所以你應(yīng)該比較明確的確定該值的含義。
最后一點(diǎn),我們需要知道什么時(shí)候需要排序,實(shí)現(xiàn)這點(diǎn)可以在父窗口中對(duì)LVN_COLUMNCLICK消息進(jìn)行處理來(lái)實(shí)現(xiàn)。
下面我們看一個(gè)例子,這個(gè)例子是一個(gè)派生類,并支持順序/倒序兩種方式排序。為了簡(jiǎn)單我對(duì)全局?jǐn)?shù)據(jù)進(jìn)行排序,而在實(shí)際應(yīng)用中會(huì)有多組需要排序的數(shù)據(jù),所以需要通過傳遞參數(shù)的方式來(lái)告訴派序函數(shù)需要對(duì)什么數(shù)據(jù)進(jìn)行排序。

//全局?jǐn)?shù)據(jù)
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;//當(dāng)前排序的列
protected:
//{{AFX_MSG(CSortList)
//}}AFX_MSG
...
};
//父窗口中包含該CListCtrl派生類對(duì)象
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()
//初始化數(shù)據(jù)
BOOL CSort_in_list_ctrlDlg::OnInitDialog()
{
CDialog::OnInitDialog();
//初始化ListCtrl中數(shù)據(jù)列表
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);
//設(shè)置每項(xiàng)的ItemData為數(shù)組中數(shù)據(jù)的索引
//在排序函數(shù)中通過該ItemData來(lái)確定數(shù)據(jù)
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;
//設(shè)置排序方式
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;
}
//調(diào)用排序函數(shù)
m_listTest.SortItems( ListCompare, (DWORD)&m_listTest );
*pResult = 0;
}
//排序函數(shù)實(shí)現(xiàn)
int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
//通過傳遞的參數(shù)來(lái)得到CSortList對(duì)象指針,從而得到排序方式
CSortList* pV=(CSortList*)lParamSort;
//通過ItemData來(lái)確定數(shù)據(jù)
DEMO_DATA* pInfo1=strAllData+lParam1;
DEMO_DATA* pInfo2=strAllData+lParam2;
CString szComp1,szComp2;
int iCompRes;
switch(pV->m_nSortedCol)
{
case(0):
//以第一列為根據(jù)排序
szComp1=pInfo1->szName;
szComp2=pInfo2->szName;
iCompRes=szComp1.Compare(szComp2);
break;
case(1):
//以第二列為根據(jù)排序
if(pInfo1->iAge == pInfo2->iAge)
iCompRes = 0;
else
iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;
break;
default:
ASSERT(0);
break;
}
//根據(jù)當(dāng)前的排序方式進(jìn)行調(diào)整
if(pV->m_fAsc)
return iCompRes;
else
return iCompRes*-1;
}
排序最快:
CListCtrl::SortItems
Example
// Sort the item in reverse alphabetical order.
static int CALLBACK
MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
// lParamSort contains a pointer to the list view control.
// The lParam of an item is just its index.
CListCtrl* pListCtrl = (CListCtrl*) lParamSort;
CString strItem1 = pListCtrl->GetItemText(lParam1, 0);
CString strItem2 = pListCtrl->GetItemText(lParam2, 0);
return strcmp(strItem2, strItem1);
}
void snip_CListCtrl_SortItems()
{
// The pointer to my list view control.
extern CListCtrl* pmyListCtrl;
// Sort the list view items using my callback procedure.
pmyListCtrl->SortItems(MyCompareProc, (LPARAM) pmyListCtrl);
}

If you don’t want to allow the users to sort the list by clicking on the header, you can use the style LVS_NOSORTHEADER. However, if you do want to allow sorting, you do not specify the LVS_NOSORTHEADER. The control, though, does not sort the items. You have to handle the HDN_ITEMCLICK notification from the header control and process it appropriately. In the code below, we have used the sorting function SortTextItems() developed in a previous section. You may choose to sort the items in a different manner.
Step 1: Add two member variables
Add two member variables to the CListCtrl. The first variable to track which column has been sorted on, if any. The second variable to track if the sort is ascending or descending.
int nSortedCol;
BOOL bSortAscending;

Step 2: Initialize them in the constructor.
Initialize nSortedCol to -1 to indicate that no column has been sorted on. If the list is initially sorted, then this variable should reflect that.

nSortedCol = -1;
bSortAscending = TRUE;

Step 3: Add entry in message map to handle HDN_ITEMCLICK
Actually you need to add two entries. For HDN_ITEMCLICKA and HDN_ITEMCLICKW. Do not use the class wizard to add the entry. For one, you need to add two entries whereas the class wizard will allow you only one. Secondly, the class wizard uses the wrong macro in the entry. It uses ON_NOTIFY_REFLECT() instead of ON_NOTIFY(). Since the HDN_ITEMCLICK is a notification from the header control to the list view control, it is a direct notification and not a reflected one.
ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked)
ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)
Note that we specify the same function for both the notification. Actually the program will receive one or the other and not both. What notification it receives will depend on the OS. The list view control on Windows 95 will send the ANSI version and the control on NT will send the UNICODE version.
Also, note that the second argument is zero. This value filters for the id of the control and we know that header control id is zero.
Step 4: Write the OnHeaderClicked() function
Here’s where you decide what to do when the user clicks on a column header. The expected behaviour is to sort the list based on the values of the items in that column. In this function we have used the SortTextItems() function developed in a previous section. If any of the columns displays numeric or date values, then you would have to provide custom sorting for them.

void CMyListCtrl::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
if( phdn->iButton == 0 )
{
// User clicked on header using left mouse button
if( phdn->iItem == nSortedCol )
bSortAscending = !bSortAscending;
else
bSortAscending = TRUE;
nSortedCol = phdn->iItem;
SortTextItems( nSortedCol, bSortAscending );
}
*pResult = 0;
}
讓CListCtrl的SubItem也具有編輯功能:
要重載一個(gè)文本框,然后在LVN_BEGINLABELEDIT時(shí)改變文本框位置。
CInEdit m_InEdit;
if( ( GetStyle() & LVS_TYPEMASK ) == LVS_REPORT && ( m_nEditSubItem != 0 ) )
{
HWND hwndEdit;
CRect rtBound;
CString strText;
hwndEdit = (HWND)SendMessage( LVM_GETEDITCONTROL );
GetSubItemRect( pDispInfo->item.iItem, m_nEditSubItem, LVIR_LABEL, rtBound );
m_InEdit.SubclassWindow( hwndEdit );
m_InEdit.m_left = rtBound.left;
strText = GetItemText( pDispInfo->item.iItem, m_nEditSubItem );
m_InEdit.SetWindowText( strText );
}
void CInEdit::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
CRect rtClient;
lpwndpos->x = m_left; // m_left在LVN_BEGINLABELEDIT中設(shè)置
CEdit::OnWindowPosChanging(lpwndpos);

// TODO: Add your message handler code here

}