CLsitCtrl 控件使用
CListCtrl控件在数据库编程中是用得比较多的控件之一,也是Window控件中较难掌握的一个控件。他可以有四显示方式,Report、List、Icon、SmallIcon,可以在"properties"的Styles选项卡中在View项可以选择显示方式。
Report报告式列表视图方式在数据库开发中是最常用的一种方式。Report方式中列表控件的显示方式是有行(item)和列(column)的,只能操作每一行的第零列,即表头列。
向MFC 对话框中添加CCtrlList 控件,关联变量m_list ,选择report显示方式。 下面看下其相关结构体及常用操作函数:
1、相关结构体
1)LV_COLUMN结构
该结构仅用于报告式列表视图,用来描述表项的某一列。向表项中插入新的一列,需要用到该结构。
LV_COLUMN结构定义如下:
typedef struct_LV_COLUMN{
UINT mask; //屏蔽位的组合,表明该结构体中哪些成员是有效的
int fmt; //该列的对齐方式(LVCF_FMT)
int cx; //列的宽度(像素)(LVCF_FMT)
LPTSTR pszText; //列标题(LVCF_TEXT)
int cchTextMax; //列标题缓冲区的长度(LVCF_TEXT)
int iSubItem; //与列关联的子项索引值 从0开始(LVCF_SUBITEM)
}LVCOLUMN;
mask是用来设置LVCOLUMN结构体中哪些成员有效,其值可以为0。mask可设置的值如下:
LVCF_FMT 表示fmt成员有效
LVCF_IMAGE 表示 iImage成员有效
LVCF_ORDER //以下略
LVCF_SUBITEM
LVCF_TEXT
LVCF_WIDTH
2)LV_ITEM结构
该结构用来描述一个表项或一个子项(行或行中的元素),它包含了项的各种属性,定义为:
typedef struct_LV_ITEM{
UINT mask; //屏蔽位的组合,表明哪些成员是有效的
int iItem; //从0开始编号的表项索引(行索引)
int iSubItem; //从1开始编号的子项索引(列索引),因为编号0的列使用InsertItem时已经写入数据
UINT state; //项的状态(LVIF_STATE)
UINT stateMask; //项的状态屏蔽
LPTSTR pszText; //指向存放项的正文的索引区(LVIF_TEXT)
int cchTextMax; //标题正文缓冲区的长度(LVCF_TEXT)
int iImage; //图标的索引(LVIF_IMAGE)
LPARAM lParam; //32位的附加数据(LV_PARAM)
}LV_ITEM;
以上两个结构体具体取值 ,参见msdn
2、常用操作函数
1)初始化列表
① 初始化表头 ,插入各个列
int InsertColumn(int nCol,const LV_COLUMN*pColumn);
其中参数nCol是新列的索引,参数pColumn指向一个LV_COLUMN结构,函数根据该结构来创建新的列。若 插入成功,函数返回新的索引;否则返回-1。
② 要删除某列,应调用DeleteColumn()函数,其声明为:
BOOL DeleteColumn(int nCol); 其中nCol为该列的索引号;
例 :
char *szColUmn[] = {"姓名", "性别"}; int nColWidth[] = {100, 100}; LVCOLUMN lvc; lvc.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH | LVCF_ORDER; lvc.fmt = LVCFMT_LEFT; //左对齐 for (int i = 0; i < 2; i++) { lvc.pszText = szColUmn[i]; lvc.iSubItem = i; lvc.iOrder = i; lvc.cx = nColWidth[i]; m_list.InsertColumn(i, &lvc); } //m_list.DeleteColumn(0);
当然也有简便方法初始化表头,不需要定义LVCOLUMN 结构体 。直接调用如下函数
int InsertColumn(
int nCol,
LPCTSTR lpszColumnHeading,
int nFormat = LVCFMT_LEFT,
int nWidth = -1,
int nSubItem = -1
);
用该方法替换上面的代码如下 :
char *szColUmn[] = {"姓名", "性别"}; for (int i = 0; i < 2; i++) { m_list.InsertColumn(i,szColUmn[i],LVCFMT_LEFT,100); }
④ 添加行 (同样有两种方法,一种是构造结构体在添加,另外一种是直接添加)
如果要显示图标,则应该创建一个CImageList对象并使该对象包含用作显示图标的位图序列,然后调用
SetImageList为列表视图设置位图序列。函数的声明为:int InsertItem(const LV_ITEM *pItem);
或者 int InsertItem( int nItem, LPCTSTR lpszItem);
int InsertItem( int nItem, LPCTSTR lpszItem, int nImage ); //
还不会的待研究③ 设置列表风格使用的时候多用第二种和第三种。因此省去了定义并初始化LV_ITEM数据类型这一步。
按行索引添加行示例如下:(此时显示情况会按顺序显示(从上往下升序))
m_list.InsertItem(0,"张三 "); m_list.SetItemText(0,1,"男"); m_list.InsertItem(1,"小红"); m_list.SetItemText(1,1,"女");
如果每次行索引都是0 ,也会顺序显示所有的行 但从上往下为降序
m_List.SetExtendedStyle(m_List.GetExtendedStyle()|LVS_EX_FULLROWSELECT);
2)操作列表
①函数GetItemText()和函数SetItemText()用于查询、修改和设置表项以及子项显示的正文。
(此操作在数据库编程时使用较多)
SetItemText()函数的一个重要用途就是对子项进行初始化。
int GetItemText(int nItem,int nSubItem,LTPSTR lpszText,int nLen) const;
CString GetItemText(int nItem,int nSubItem) const;
BOOL SetItemText(int nItem,int nSubItem,LPTSTR lpszText);
其中,参数nItem是表项的索引(行索引),nSubItem是子项的索引(列索引),若nSubItem为0说明函数是针对表项的。参数lpszText指向正文缓冲区,参数nLen说明缓冲区的大小。
② 对CListCtrl 控件的事件响应
双击某一行响应函数:
void CCListCtrlDlg::OnDblclkList2(NMHDR* pNMHDR, LRESULT* pResult) { //获取选中的行 得到其各个元素 。 int nIndex = m_list.GetNextItem( -1, LVNI_SELECTED ); MessageBox(m_list.GetItemText(nIndex,1)); *pResult = 0; }
单击标头列的响应函数 :
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; int n=pNMListView->iSubItem; CString str; str.Format("%d",n); AfxMessageBox(str); //输出得到的列号
③ 单击表头实现自动排序
表头可以当作按钮来使用,当鼠标点击表头时,会向父窗口发送一个LNV_COLUMNCLICK消息,在重绘的CMyListCtrl类或者IDC_LIST控件中响应对应LNV_COLUMNCLICK消息,由第三方开发的专用排序函数来实现的,排序函数只是实现表项的具体比较操作。正常的排序过程是升序方式,通过调换排序函数中的参数值,就可实现降序排列,即将PARAM1与PARAM2调换位置。
④ 删除行
m_list.DeletItem(int nIndex);
m_list.DeleteAllIIems();
⑤实现类似表格的操作 ,直接修改行里的元素 。