您的位置:首页 > 其它

[MFC]CListView列表视图

2015-12-11 11:07 176 查看
1. 列表视图简介:

1) 最常见的列表视图案例就是Windows的资源管理器的右侧视图,就是使用列表视图来展示当前路径下的文件集合的;

2) 列表视图有两大元素,一是文本,而是图形,和树形视图一样,但是这两种元素的展示形式会根据列表视图的样式发生改变;

3) Windows支持的4中列表视图的样式:

i. 小图标:



ii. 大图标:



iii. 列表:



iv. 报表(详细):



4) 在小图标、大图标和列表三种样式中,每个图标文字组合都是一个项目,而在报表模式中除了顶上的标题栏之外,其它每一行都是一个项目,其中最左列是主项目,右侧的列是主项目的子项目,像这里Lecture1.ppt就是主项目,Size的4372480和Last Modified的9/18/15(8:04a)这两项是Lecture1.ppt的子项目,这回在编程中具体体现出来;

5) 列表视图类是CListView,它继承自列表控件CListCtrl,并派生出了大部分功能,在列表视图中要使用列表的有关功能就必须调用CListView的GetListCtrl获得视图内部的列表空间的引用:CListCtrl& CListView::GetListCtrl() const;

2. 列表视图的初始样式:

1) 初始化列表视图时必须要覆盖CListView::PreCreateWindow函数,并设置cs.style来给出列表视图的默认样式;

2) 下表给出里列表视图的通用样式,其它没给出的一些样式是应用在Explorer浏览器中,这里就先不做说明:

i. 所有样式的前缀都是LVS_,即List View Style的缩写,即列表视图样式;

ii. 首先是四种显示模式:

LVS_ICON:大图标模式

LVS_SMLLICON:小图标模式

LVS_LIST:列表样式

LVS_REPORT:报表样式

iii. 项目对其方式:下列3中样式都只在大图标和小图标模式下有效

LVS_ALIGNLEFT:项目沿左边框对齐

LVS_ALIGNTOP:沿顶边框对齐

LVS_ALIGNARRANGE:自动按行和列排列项目

iv. 项目排序:

LVS_SORTASCENDING:按照项目文本字符升序排列

LVS_SORTDESCENDING:降序

v. 和标头有关:只在报表模式下有效,因为只有报表模式会有标头

LVS_NOCOLUMNHEADER:删除标头控件

LVS_NOSORTHEADER:通常用鼠标点击标头的某一项(就会发送LVN_COLUMNCLICK通知),那么该项所表示的列就会按照自定义的规则进行排序,现在该样式将禁止LVN_COLUMNCLICK通知的发送

vi. 功能性样式:

LVS_NOSCROLL:滚动失效,默认下是开启滚动的

LVS_SINGLESEL:限制为单选,禁止多选,默认下是开启多选的

LVS_SHOWSELALWAYS:被选中项目始终加亮,默认下加亮效果在视图失去焦点时消失

LVS_SHAREIMAGELIST:指定图形列表和视图时共享的,而不是绑定的,如果为绑定,那么视图被删除是图形列表也会删除

LVS_EDITLABELS:是项目文本可以直接编辑

LVS_OWNERDRAWFIXED:响应WM_DRAWITEM,可以让控件所有者自行绘制项目文本,即自定义项目内容;

3. 列表视图创建的大致步骤:

1) 首先肯定是现在CListView::PreCreateWindow中设置列表视图的默认样式;

2) 接下来的步骤应该都放在CListView::OnInitialUpdate虚函数中;

3) 首先是使用CImageList::Create分别创建两个图形列表,一个用于大图标模式的大图标列表,另一个是用于小图标、列表、报表模式的小图标列表;

4) 接下来使用CListCtrl的SetImageList将图形列表和列表视图绑定起来:

i. 函数原型:CImageList* CListCtrl::SetImageList(CImageList* pImageList, int nImageListType);

ii. 返回值还是上一次绑定的图形列表;

iii. nImageListType表示该图形列表的图形,在CListCtrl中只有两种类型,一种LVSIL_NORMAL(即大图标列表),另一种是LVSIL_SMALL(即小图标列表),LVSIL_前缀为List View Set Image List的缩写;

!!当使用设置模式的函数将列表视图设置为大图标模式时,列表视图就会自动调用大图标列表里的图标,如果设置为小图标、列表和报表模式,那么就会自动调用小图标列表里的图标;

5) 接下来添加列(即标头),但不过不是只有报表模式有列(标头)的吗?但不过没关系,因为标头只有在报表模式下才会显示,在其它模式下不显示而已,并且后面各个项也可以添加子项,只不过只有在报表模式下才会显示子项而已:

i. 添加列使用CListCtrl的InsertColumn:

int CListCtrl::InsertColumn(
int nCol,  // 列的索引(从0开始,从左往右)
LPCTSTR lpszColumnHeading,  // 列标头的内容
int nFormat = LVCFMT_LEFT,  // 列标头的对齐方式
int nWidth = –1,  // 列的宽度,以像素为单位,-1表示这是一个空列
int nSubItem = –1 // 子项目的索引,-1表示没有子项
);
ii. nFormat:列的对齐方式,以LVCFMT_打头,即List View Control Format的缩写,有以下几种

LVCFMT_LEFT:左对齐

LVCFMT_RIGHT:右对齐

LVCFMT_CENTER:居中

!!最左侧的那一列必须使用LVCFMT_LEFT!!

!!其实可以不必按照0、1、2...的顺序来插入列,比如0、2、3也行,那么只要将1的那列的nWidth设为-1即可,这样其它参数都无效;

!!因此按照这个规则,不一定就是0的那列必须为LVCFMT_LEFT,如果0置为空列,那么后面的第一个非空列就是最左列,只要最左列必须为LVCFMT_LEFT即可;

4. 列表视图的操作:

1) 之前介绍的列表视图的创建,接下来的操作可以根据需要在任何地方(函数中)进行;

2) 插入项目:InsertItem

i. 原型:int CListCtrl::InsetItem(int nItem, LPCTSTR lpszItem, int nImage);

ii. nItem:表示该项目插入到第几号索引,原来位置的项目将会往后挪一位;

iii. lpszItem:插入项目的文本;

iv. nImage:该项目所对应的图标,这里是图形列表中图标的索引号;

v. 返回的是插入后项目的索引,如果失败则返回-1;

!!另一个版本:int CListCtrl::InsertItem(const LVITEM* pItem);

i. LVITEM是一个结构体,即List View Item的缩写,看一下定义:

typedef struct _LVITEM {
UINT mask; // 项目标志
int iItem; // 项目索引
int iSubItem; // 子项目索引
UINT state;
UINT stateMask;
LPTSTR pszText; // 项目-子项目所确定的位置的文本
int cchTextMax;
int iImage; // 项目图标在图形列表中的索引
LPARAM lParam; // 额外数据区的指针
int iIndent;
} LVITEM;
!!这里我们只注释了我们需要用到的数据域,其它数据域暂时用不到,不用理会;

3) 设置项目文本:SetItemText

i. 原型:BOOL CListCtrl::SetItemText(int nItem, int nSubItem, LPCTSTR lpszText);

ii. nItem-nSubItem:表示第几个项目的第几个子项目,nSubItem如果为0就表示该项目本身标签,只要在报表模式中nSubItem才可以大于0,表示该项目的子项目;

iii. lpszText是设置的文本,返回值表示调用是否成功;

4) 设置列表项目宽度的重要手段:GetStringWidth

i. 在通常情况下需要根据项目中文本的宽度来决定列表的宽度,如果列表过窄则部分文本显示不出来,过宽则空白太多也不美观;

ii. 可以通过文本来测量列表最最合适的宽度,原型:int CListCtrl::GetStringWidth(LPCTSTR lpsz) const;

iii. 该方法使CListCtrl独有的方法,它可以根据指定的字符串lpsz来计算出一个刚好合适的列表宽度并返回,注意!返回的是以像素为单位的;

5) 删除所有的项目:BOOL CListCtrl::DeleteAllItems(); // 返回值表示成功与否

5. 修改列表的样式:

1) 虽然在PreCreateWindow中已经设定好了默认的样式,但是有时候也有在程序中根据用户的响应来临时改变样式的需求,比如从菜单中选择列表的样式等;

2) 首先可以通过GetStyle来获取当前的样式:

i. 原型:DWORD CWnd::GetStyle() const;

ii. 该函数继承自CWnd,但是返回的是所有样式位,总共有32位,在被CListCtrl继承后,返回的不仅包含4大样式的信息,也包含其它各种杂七杂八的样式(比如左对齐、右对齐等等);

iii. 因此要获取真正的属于4大样式的哪一种必须借助于位掩码LVS_TYPEMASK,该标志和样式&后可以获得4大样式的标志位,因此判断当前是哪种4大样式的一种必须要这样写:列表只可能处在4大样式的其中一种状态,不可能同时处于两种样式的状态

DWORD dwStyle = GetStyle() & LVS_TYPEMASK;
switch (dwStyle)
{
case LVS_ICON:
...
case LVS_SMALLICON:
...
...
}
3) 临时修改列表样式:ModifyStyle

i. 原型:BOOL CWnd::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0);

ii. 该函数继承自CWnd,该函数会触发窗口的重绘,即按照给定的新样式重绘;

iii. 该函数底层为了提高效率,采取消除和添加的方式指定新样式,dwRemove表示要删除的样式,而dwAdd表示要添加的样式;

iv. nFlags是要传给SetWindowPos的标志,如果传0表示不调用SetWindowPos,如果不为0则会回调SetWindowPos并将nFlags传给它,这里我们不需要用到这个功能,因此保持该参数的默认值即可;

v. 通常用该函数在4大样式之间进行转换,第一个参数必然填LVS_TYPEMASK,把4大样式先删去,第二个参数填指定的4大样式的一种,例如:ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON); // 将样式转换为小图标模式

6. 列表的命中测试:

1)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: