CListCtrl::SetExtendedStyle
CListCtrl的成員函數聲明
DWORD SetExtendedStyle(
DWORD dwNewStyle );
函數功能設置CListCtrl的擴展樣式
dwNewStyle指定的擴展樣式
LVS_EX_GRIDLINES //繪制表格,網格線。
LVS_EX_SUBITEMIMAGES//子項目圖標列表
LVS_EX_CHECKBOXES //帶復選框
LVS_EX_TRACKSELECT //自動換行
LVS_EX_HEADERDRAGDROP//報表頭可以拖拽
LVS_EX_FULLROWSELECT //選擇整行,允許選擇整行。
LVS_EX_ONECLICKACTIVATE//單擊激活單擊選中項目。
LVS_EX_TWOCLICKACTIVATE//雙擊激活
LVS_EX_FLATSB//扁平滾動條
LVS_EX_REGIONAL
LVS_EX_INFOTIP
LVS_EX_UNDERLINEHOT
LVS_EX_UNDERLINECOLD
LVS_EX_MULTIWORKAREAS//多工作區
----------------------------------
例子:m_TextList.SetExtendedStyle(...);
LVS_ALIGNLEFT 用來確定表項的大小圖標以左對齊方式顯示;
LVS_ALIGNTOP 用來確定表項的大小圖標以頂對齊方式顯示;
LVS_AUTOARRANGE 用來確定表項的大小圖標以自動排列方式顯示;
LVS_EDITLABELS 設置表項文本可以編輯,父窗口必須設有LVN_ENDLABELEDIT風格;
LVS_ICON 用來確定大圖標的顯示方式;
LVS_LIST 用來確定列表方式顯示;
LVS_NOCOLUMNHEADER 用來確定在詳細資料方式時不顯示列表頭;
LVS_NOLABELWRAP 用來確定以單行方式顯示圖標的文本項;
LVS_NOSCROLL 用來屏蔽滾動條;
LVS_NOSORTHEADER 用來確定列表頭不能用作按鈕功能;
LVS_OWNERDRAWFIXED 在詳細列表方式時允許自繪窗口;
LVS_REPORT 用來確定以詳細資料即報告方式顯示;
LVS_SHAREIMAGELISTS用來確定共享圖像列表方式;
LVS_SHOWSELALWAYS 用來確定一直顯示被選中表項方式;
LVS_SINGLESEL 用來確定在某一時刻只能有一項被選中;
LVS_SMALLICON 用來確定小圖標顯示方式;
LVS_SORTASCENDING 用來確定表項排序時是基於表項文本的升序方式;
LVS_SORTDESCENDING 用來確定表項排序時是基於表項文本的降序方式;
typedef struct _LV_ITEM {
UINT mask; //結構成員屏蔽位
int iItem; //表項索引號
int iSubItem; //子表項索引號
UINT state; //表項狀態
UINT stateMask; //狀態有效性屏蔽位
LPTSTR pszText; //表項名文本
int cchTextMax; //表項名最大長度
int iImage; // 表項圖標的索引號
LPARAM lParam; // 與表項相關的32位數
} LV_ITEM;
typedef struct _LV_COLUMN {
UINT mask; //結構成員有效性屏蔽位
int fmt; //表列對齊方式
int cx; //表列的象素寬度
LPTSTR pszText; //表列的表頭名
int cchTextMax; //表列名的文本長度
int iSubItem; //與表列關聯的子表項索引號
} LV_COLUMN;
其中fmt可以取如下值:
LVCFMT_CENTER 表列居中對齊
LVCFMT_LEFT 表列左對齊
CListCtrl 使用完全指南
構造函數
ClistCtrl構造一個CListCtrl對象。
Create創建列表控件並將其附加給CListCtrl對象。
GetBkColor獲取列表視圖控件的背景色。
SetBkColor設置列表視圖控件的背景色。
GetImageList獲取用於繪制列表視圖項的圖象列表的句柄。
SetImageList指定一個圖象列表到列表視圖控件。
GetItemCount獲取列表視圖控件中的項的數量。
GetItem獲取列表視圖項的屬性。
GetCallbackMask獲取列表視圖控件的回調掩碼。
SetCallbackMask設置列表視圖控件的回調掩碼。
GetNextItem查找指定特性和指定指定項關系的列表視圖項。
GetFirstSeletedItemPosition在列表視圖控件中獲取第一個選擇的列表視圖項的位置。
GetNextSeletedItem為重復而獲取下一個選擇的列表視圖。
GetItemRect獲取項的有界矩形。
SetItemPosition在列表視圖控件中移動一項到指定位置。
GetItemPosition獲取列表視圖項的位置。
GetStringWidth指定需要顯示所有指定字符串的最小列寬。
GetEditControl獲取用於編輯一個項文本的編輯控件的句柄。
GetColumn獲取控件的列的屬性。
SetColumn設置列表視圖列的屬性。
GetColumnWidth獲取報表視圖或列表視圖中的列的寬度。
SetColumnWidth改變報表視圖或列表視圖中的列的寬度。
GetCheck獲取與某項相關的狀態圖象的當前顯示狀態。
SetCheck設置與某項相關的狀態圖象的當前顯示狀態。
GetViewRect獲取列表視圖控件中所有項的有界矩形。
GetTextColor獲取列表視圖控件的文本顏色。
SetTextColor設置列表視圖控件的文本顏色。
GetTextBkColor獲取列表視圖控件的文本背景色。
SetTextBkColor設置列表視圖控件的文本背景色。
GetTopIndex獲取最高級項的索引。
GetCountPerPage計算可正好垂直放入列表視圖控件中的項的數目。
GetOrigin獲取列表視圖控件的最初的當前視圖。
SetItemState改變列表視圖控件的項的狀態。
GetItemState獲取列表視圖控件的項的狀態。
GetItemText獲取列表視圖項或子項的文本。
SetItemText設置列表視圖項或子項的文本。
SetItemCount准備一個列表視圖控件以添加大量的項。
GetItemData獲取與某項相關的應用所指定的值。
SetItemData設置項的應用指定的值。
GetSelectedCount獲取列表視圖控件中選擇項的數量。
SetColumnOrderArray設置列表視圖控件的列序(左或右)。
GetColumnOrderArray獲取列表視圖控件的列序(左或右)。
SetIconSpacing設置列表視圖控件中的圖標的距離。
GetHeaderCtrl獲取列表視圖控件的標題控件。
GetHotCursor獲取在熱調試對列表視圖控件有效時使用的游標。
SetHotCursor設置在熱調試對列表視圖控件有效時使用的游標。
GetSubItemRect獲取列表視圖控件中某項的有界矩形。
GetHotItem獲取當前在游標下的列表視圖項。
SetHotItem設置列表視圖控件的當前熱項。
GetSelectionMark獲取列表視圖控件的選擇屏蔽。
SetSelectionMark設置列表視圖控件的選擇屏蔽。
GetExtendedStyle獲取列表視圖控件的當前擴展風格。
SetExtendedStyle設置列表視圖控件的當前擴展風格。
SubItemHitTest指定哪個列表視圖項在指定位置。
GetWorkAreas獲取列表視圖控件的當前工作區。
GetNumberOfWorkAreas獲取列表視圖控件的當前工作區數量。
SetItemCountEx設置虛列表視圖控件的項的數量。
SetWorkAreas設置列表視圖控件中圖標可以顯示的區域。
ApproximateViewRect指定顯示列表視圖控件項所需的寬度和高度。
GetBkImage獲取列表視圖控件的當前背景圖象。
SetBkImage設置列表視圖控件的當前背景圖象。
GetHoverTime獲取列表視圖控件的當前逗留時間。
SetHoverTime設置列表視圖控件的當前逗留時間。
InsertItem在列表視圖控件中插入一個新項。
DeleteItem從控件中刪除一項。
DeleteAllItems從控件中刪除所有項。
FindItem查找具有指定的字符的列表視圖項。
SortItems使用應用定義的比較函數排序列表視圖項。
HitTest指定哪個列表視圖在指定的位置上。
EnsureVisible保證項是可見的。
Scroll滾動列表視圖控件的內容。
ReDrawItems強迫列表視圖控件刷新一些項。
Update強迫控件刷新一個指定的項。
Arrange調整一欄里的項。
EditLabel開始項文本該處編輯。
InsertColumn插入列表視圖控件中的新列。
DeleteColumn從列表視圖控件中刪除一列。
CreateDragImage為指定的項構造一個拖動圖象列表。
DrawItem當自繪制控件的可視部分改變時被調用。
創建圖形列表並和CListCtrl關聯:
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);
為報表添加4列:
char *szColumn[]={"昵稱","IP地址","登陸時間","狀態"};
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);
}
為報表添加兩項,以附加方式添加:
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++;
設置報表的樣式
選中一整行:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_FULLROWSELECT);
繪制表格:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_GRIDLINES);
帶復選框:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_CHECKBOXES);
自動切換:
m_list_ctrl.SetExtendedStyle(m_list_ctrl.GetExtendedStyle()|LVS_EX_TRACKSELECT);
選定一行:
設置CListCtrl的Show selectionalways選項
SetItemState (iIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED)
選中一個或多個項目時,會發送LVN_ITEMCHANGED消息,可以使用
GetSelectedCount()方法得到被選定的項的數目。
點擊列頭的消息響應:
ON_NOTIFY(HDN_ITEMCLICKW, 0, ResponseFunc)
消息,需要自己添加
或者:
ON_NOTIFY(LVN_COLUMNCLICK, ID_yourCtrl, ResponseFunc)//向導添加
前者后響應,后者先響應
響應函數:
ResponseFunc(NMHDR *pNMHDR, LRESULT *pResult)
雙擊CListCtrl中的ITEM的消息是及消息函數:
ON_NOTIFY(NM_DBLCLK, ID_yourCtrl, ResponseFunc)
單擊ITEM的消息響應:
ON_NOTIFY(NM_CLICK, ID_yourCtrl, ResponseFunc)
ResponseFunc(NMHDR *pNMHDR, LRESULT *pResult)
HDN_ITEMCLICK 就是Header controlNotify message for mouse left click on the Header control!
而HDN_ITEMCLICK是當List View中存在一個Header Contrl時,Header Ctrl通知父窗口List View的!
CListCtrl中的Item被選中觸發LBN_SELCHANGE(通過WM_COMMAND)消息!
刪除CListCtrl中選定的項:
POSITION pos;
int nIndex;
for(; pos= GetFirstSelectedItemPosition();)
{
nIndex = GetNextSelectedItem(pos);
DeleteItem(nIndex);
}
POSITION GetFirstSelectedItemPosition() const
如果函數執行成功,則返回條目的POSITION值,如果返回值為KULL,則表示當前列表視圖控件中沒有條目選中。
Int GetNextSelectedItem(POSITION& pos) const
如果函數執行成功,則返回列表視圖控件中下一個被選中的條目索引。其中參數pos為將接收條目POSITION值的變量。
注意:使用這兩個函數的時候 ListCtrl最好是有LVS_FULLROWSELECT的擴展風格。
在ListCtrl中進行排序
列表控件(CListCtrl)的頂部有一排按鈕,用戶可以通過選擇不同的列來對記錄進行排序。但是 CListCtrl並沒有自動排序的功能,我們需要自己添加一個用於排序的回調函數來比較兩個數據的大小,此外還需要響應排序按鈕被點擊的消息。下面講述一下具體的做法。
CListCtrl提供了用於排序的函數,函數原型為:BOOLCListCtrl::SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData )。其中第一個參數為全局排序函數的地址,第二個參數為用戶數據,你可以根據你的需要傳遞一個數據或是指針。該函數返回-1代表第一項排應在第二項前面,返回1代表第一項排應在第二項后面,返回0代表兩項相等。
用於排序的函數原形為:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAMlParamSort),其中第三個參數為調用者傳遞的數據(即調用SortItems時的第二個參數dwData)。第一和第二個參數為用於比較的兩項的ItemData,你可以通過DWORD CListCtrl::GetItemData( int nItem )/BOOLCListCtrl::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 acontrol
}
//處理消息
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;
}
排序最快:
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 byclicking on the header, you can use the style LVS_NOSORTHEADER. However, if youdo 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_ITEMCLICKnotification from the header control and process it appropriately. In the codebelow, we have used the sorting function SortTextItems() developed in a previoussection. 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 whichcolumn has been sorted on, if any. The second variable to track if the sort is ascendingor 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. Ifthe 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. Donot use the class wizard to add the entry. For one, you need to add two entrieswhereas the class wizard will allow you only one. Secondly, the class wizarduses the wrong macro in the entry. It uses ON_NOTIFY_REFLECT() instead ofON_NOTIFY(). Since the HDN_ITEMCLICK is a notification from the header controlto 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. Whatnotification it receives will depend on the OS. The list view control onWindows 95 will send the ANSI version and the control on NT will send theUNICODE version.
Also, note that the second argument is zero. This value filters for the id ofthe 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 userclicks on a column header. The expected behaviour is to sort the list based onthe values of the items in that column. In this function we have used theSortTextItems() function developed in a previous section. If any of the columnsdisplays numeric or date values, then you would have to provide custom sortingfor 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也具有編輯功能:
要重載一個文本框,然后在LVN_BEGINLABELEDIT時改變文本框位置。
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中設置
CEdit::OnWindowPosChanging(lpwndpos);
// TODO: Add your message handler code here
}
