CListCtrl使用方法汇总

回顾:chrome

刚刚写完,由于是分期写的,因此最初想好好作一下的文章格式半途而废了~说的也许会有点啰嗦,可是全部的基础用到的技术细节应该都用到了。app

若是还有什么疑问,请回复留言,我会尽力解答。ide

若是有错误,请指正。函数

这里全部使用到的内容在VS2010中均能正常运行。网站

可运行程序的截图:this

CListCtrl控件的建立spa

若是一个CListCtrl控件对象和dialog上的控件已经绑定,那么能够跳过这个这一步,由于绑定了的对象已经完成了建立。翻译

可是若是要在dialog上凭空建立出来一个列表控件,那么就须要了解CListCtrl类的成员函数:Create指针

先看这个函数的原型:code

BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

第一个参数是用来声明这个列表的风格,具体风格以下 :

    • LVS_ALIGNLEFT Specifies that items are left-aligned in icon and small icon view.
      指定条款是小图标且左对齐
    • LVS_ALIGNTOP Specifies that items are aligned with the top of the control in icon and small icon view.
      指定条款是顶端对其且为小图标
    • LVS_AUTOARRANGE Specifies that icons are automatically kept arranged in icon view and small icon view.
      指定图标自动保存在图标视图中,且为小图标视图
    • LVS_EDITLABELS Allows item text to be edited in place. The parent window must process the LVN_ENDLABELEDIT notification message.
      容许条目适当的编辑,父窗口必须指定LVN_ENDLABELEDIT消息
    • LVS_ICON Specifies icon view.
      指定图标视图
    • LVS_LIST Specifies list view.
      指定列表视图
    • LVS_NOCOLUMNHEADER Specifies that a column header is not displayed in report view. By default, columns have headers in report view.
      指明列的头结点不在报告视图中显示,默认时,列的头结点会在报告中显示出来
    • LVS_NOLABELWRAP Displays item text on a single line in icon view. By default, item text can wrap in icon view.
      在图标视图中单独的显示出来。默认状况下,项文本能和图标同时显示
    • LVS_NOSCROLL Disables scrolling. All items must be within the client area.
      关闭滚动条,所有的条目必须在客户区内显示
    • LVS_NOSORTHEADER Specifies that column headers do not work like buttons. This style is useful if clicking a column header in report view does not carry out an action, such as sorting.
      代表列头不会像一个按钮那样。这个选项在report风格下若是不打算让其实现一些功能会颇有用,好比点击后排序
    • LVS_OWNERDRAWFIXED Enables the owner window to paint items in report view. The list view control sends a WM_DRAWITEM message to paint each item; it does not send separate messages for each subitem. The itemData member of theDRAWITEMSTRUCT structure contains the item data for the specified list view item.
      这个我貌似用不到……不翻译了
    • LVS_REPORT Specifies report view.
      指明报告窗口
    • LVS_SHAREIMAGELISTS Specifies that the control does not take ownership of the image lists assigned to it (that is, it does not destroy the image lists when it is destroyed). This style enables the same image lists to be used with multiple list view controls.
      指明这个控件并不获取图像列表的全部权。这就意味着,在这个对象析构的时候斌不会析构图像列表。这个风格容许一样的图像列表用于多个列表控件
    • LVS_SHOWSELALWAYS Always show the selection, if any, even if the control does not have the focus.
      老是显示被选中的选项,即使窗口未被锁定
    • LVS_SINGLESEL Allows only one item at a time to be selected. By default, multiple items can be selected.
      一次只能选择一个选项,默认的状况下,能同时选择多个条目
    • LVS_SMALLICON Specifies small icon view.
      指定小图标视图
    • LVS_SORTASCENDING Sorts items based on item text in ascending order.
      按照递增进行排序
    • LVS_SORTDESCENDING Sorts items based on item text in descending order. 
    • 按照递减排序

一下翻译这么多,有点累,看来个人英语仍是太差,否则怎么会以为累~

第二个参数:rect

这个参数就是你所建立的CListCtrl的位置,以及大小。再也不作过多介绍了

第三个参数:pParentWnd

这个参数用来指定父窗口,通常是一个CDialog对象指针,须要注意的是,千万不能是NULL。

第四个参数:nID

控件ID,这个不用多说了,每一个看控件都有的。

CListCtrl风格修改

可是若是你已经建立好了一个ListCtrl控件,那么你为其声明了一个CListCtrl控件,那么上面的Create函数你就能够跳过去了~

可是,风格老是要设置的,因此在这里,有一个函数能够调用,专门用来设置风格~

LONG SetWindowLong(
  HWND hWnd,       // handle to window
  int nIndex,      // offset of value to set
  LONG dwNewLong   // new value
);

CListCtrl的窗口句柄是public的,能直接获取。

第二个参数添加:GWL_STYLE,目的就是为了设置新的风格。

第三个参数就是风格的组合了

这个函数的具体内容请看MSDN,我这就再也不多说了~

CListView的扩展风格

CListCtrl能够设置的风格:

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//多工做区

以上风格设置可使用下面的CListCtrl成员函数来设置:

DWORD SetExtendedStyle( DWORD dwNewStyle );

 如今有代码以下:

 1 void CMyRisingDlg::ListCtrlInitial()
 2 {
 3     CRect lc_rect;
 4     DWORD dwStyle = ::GetWindowLong(m_LCTable.m_hWnd, GWL_STYLE); 
 5     dwStyle &= ~(LVS_TYPEMASK);
 6     dwStyle &= ~(LVS_EDITLABELS);
 7     SetWindowLong(m_LCTable.m_hWnd, GWL_STYLE,dwStyle |LVS_REPORT | LVS_NOLABELWRAP | LVS_SHOWSELALWAYS);
 8     m_LCTable.SetExtendedStyle(LVS_EX_ONECLICKACTIVATE|LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
 9     m_LCTable.GetWindowRect(&lc_rect);
10     DWORD dwListLength = lc_rect.Width() / 3;
11     m_imagelist.Create(16, 16, ILC_COLORDDB|ILC_MASK, 0, 1);
12 
13     m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
14     m_imagelist.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
15     m_LCTable.SetImageList(&m_imagelist, LVSIL_SMALL);
16     m_LCTable.InsertColumn(0, _T("Name"), LVCFMT_LEFT | LVCFMT_IMAGE, dwListLength);
17     m_LCTable.InsertColumn(1, _T("PathName"), LVCFMT_LEFT, dwListLength);
18     m_LCTable.InsertColumn(2, _T("Create Time"), LVCFMT_LEFT, dwListLength + 3);
19 
20     m_LCTable.InsertItem(0, LPSTR_TEXTCALLBACK);21 
22 }

很显然,这个函数的功能是初始化一个ListCtrl。从代码里面可以看出来,在初始化上,其实主要的就是风格设置。而后最一行的函数调用是为了作虚拟列表,CListCtrl的虚拟列表内容我会在新的随笔中介绍。

  上面的几个比较主要的成员函数调用,SetExtendedStyle函数就再也不多说了,能够参考样式以及上面的各类风格,或者直接去看MSDN。

  而后下面的SetImageList是为了给列表上主要的首子项添加上文件图标,正在作,还未完成。不过上面的程序界面截图中能看到首列有图标,那个只是目前应付一下的~

接下来要比较重点的介绍InsertClumn函数:

  这个函数是用来完成列的插入的。或者说,创建了一个索引,或者链表头。由此函数调以后才能调用InsertItem函数,不然是无效的,函数刚一调用,估计就直接返回个0了。

  这个函数看下MSDN的介绍:

int InsertColumn( int nCol, const LVCOLUMN* pColumn );

int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1 );

Return Value

The index of the new column if successful or -1 otherwise.

这个函数有两种形式,可是我只介绍第二种,缘由为啥你应该很清楚~。这里第一个参数就是列号了,很少说。第二个参数是列名,也不用太罗嗦,第三个是格式,须要简单说一下。

nFormat参数有一下的几种形式:LVCFMT_LEFT, LVCFMT_RIGHT, or LVCFMT_CENTER.另外还有LVCFMT_IMAGE,默认状况下是从左往右的,也就是咱们的书写顺序。另外须要注意的是,其实这个参数通常来说的话都是直接使用LEFT参数的,缘由就是若是你使用了center或者right参数,会直接致使一个后果:就是这列的所有内容,也都是对应的居中或者置右。另外若是使用了LVCFMT_IMAGE参数,那么就会在最左端添加图片的基础上,默认为LEFT风格,这点仍是须要注意的。

目前除了InsertItem函数以外,其他的基础操做设置就差很少了,至于其余的一些操做我等会也还须要再看~

而后接下来说下如何添加首项的图片。

我以为添加这个图片的目的主要仍是为了提供更好的用户体验。由于若是有图片的话,对大多数用户来讲会提供一个很便利的途径来知道这个文件的类型属性。毕竟大多数的用户是不会去根据文件后缀来判断这个文件究竟是干什么的~

废话很少说,先看一个类:CImageList.

接着贴MSDN:

An “image list” is a collection of same-sized images, each of which can be referred to by its zero-based index. Image lists are used to efficiently manage large sets of icons or bitmaps. All images in an image list are contained in a single, wide bitmap in screen device format. An image list may also include a monochrome bitmap that contains masks used to draw images transparently (icon style). The Microsoft Win32 application programming interface (API) provides image list functions that enable you to draw images, create and destroy image lists, add and remove images, replace images, merge images, and drag images.

大意以下:

一个图像列表是一样大小图像的集合,每一个成员都可以经过以0为起始的目录来访问(其实就是顺序表访问)。图像列表控件可以用来有效的管理大数量的图标或位图。在图像列表中的全部图片都在屏幕设备格式中包含一个单独的,宽(这里不知道怎么翻译)的位图。一个图像列表控件也可能包含一个包含绘制透明图像任务的单色位图(这里不是很肯定)。

后面的就不翻译了,没什么用。

上面我贴的那个函数里CImageList的使用也比较明了,简单介绍下:

对象建立完以后并不须要当即初始化,还不错。而后首先要调用其中的Create函数,就是建立一个初始化一个列表并付给对象,MSDN基本就这个意思。这里再贴一下函数原型:

BOOL Create( int cx, int cy, UINT nFlags, int nInitial, int nGrow );

BOOL Create( UINT nBitmapID, int cx, int nGrow, COLORREF crMask );

BOOL Create( LPCTSTR lpszBitmapID, int cx, int nGrow, COLORREF crMask );

BOOL Create( CImageList& imagelist1, int nImage1, CImageList& imagelist2, int nImage2, int dx, int dy );

BOOL Create( CImageList* pImageList );

Return Value

Nonzero if successful; otherwise 0.

很显然,在个人程序里面调用的函数是其中的第一个,因此我这就只介绍第一个了~前两个参数很明显,就是这个图片的尺寸。我在这里的建议仍是,提供16*16的图片比较合适。我曾经想过作8*8的,结果,过小了……实在不合适。这个尺寸是我作列表比较推荐的。第三个参数很显然就是个标志位,用来设置风格的。

具体风格以下:

ILC_COLOR Use the default behavior if none of the other ILC_COLOR* flags is specified. Typically, the default is ILC_COLOR4; but for older display drivers, the default is ILC_COLORDDB.
ILC_COLOR4 Use a 4-bit (16 color) device-independent bitmap (DIB) section as the bitmap for the image list.
ILC_COLOR8 Use an 8-bit DIB section. The colors used for the color table are the same colors as the halftone palette.
ILC_COLOR16 Use a 16-bit (32/64k color) DIB section.
ILC_COLOR24 Use a 24-bit DIB section.
ILC_COLOR32 Use a 32-bit DIB section.
ILC_COLORDDB Use a device-dependent bitmap.
ILC_MASK Uses a mask. The image list contains two bitmaps, one of which is a monochrome bitmap used as a mask. If this value is not included, the image list contains only one bitmap. 

我上面的函数在这里使用的是后两个参数的组合。DDB的意思是设备相关位图,与之相反的就是大名鼎鼎的DIB了,不过这里没有。个人MSDN版本比较老,是给VC6.0作的,有兴趣的能够去MSDN网站上看看,新版的CImageList有没有提供DIB的。

不过我以为,彷佛个人那个代码里,ILC-MASK参数貌似没什么用处,回头删掉。

而后nInitial参数,就是Imagelist对象中初始化后就包含的图像数目,MSDN:Number of images that the image list initially contains.

最后一个参数:nGrow 原文:Number of images by which the image list can grow when the system needs to resize the list to make room for new images. This parameter represents the number of new images the resized image list can contain.

其实这个参数倒不是很重要,可是,能牵扯到效率问题。若是每次新添加一个图片就要申请一块新的内存,是否是有点效率过低了?因此不如一次申请多个,这样效率更高一下些。可是若是你的列表通常只须要10个,可是你每次resize以后会变成100个,就形成了浪费。因此仍是须要注意一下的,可是小列表设置为5之内的数应该就好了。

这个函数介绍完了,就要接着讲添加的问题。不过这个仍是比较简单的。能够直接调用add成员函数。

int Add( CBitmap* pbmImage, CBitmap* pbmMask );

int Add( CBitmap* pbmImage, COLORREF crMask );

int Add( HICON hIcon );

Return Value

Zero-based index of the first new image if successful; otherwise – 1.

这里提供了三个函数,前两个都是和Bitmap相关的,暂且不谈,只谈第三个。

第三个函数,很简单,只要一个图标资源的句柄就能够了。获取这个句柄资源,在MFC中有一种很简单的方法:直接调用App类的LoadIcon函数。

AfxGetApp()->LoadIcon(IDI_ICON1)

里面直接添加上工程中创建好的图标资源ID就行了。

不过这个成员函数只限CWinApp类的对象使用。另一种方法是调用SDK的函数,其中hInstance就是句柄,这里应该直接添加app的m_hwnd,应该是的,我还没试过。第二参数要使用MAKEINTRESOURCE宏转一下就能够了。

接下来就是如何将图片绑定到列表头部了。

在两个对象都建立完成后,只要调用CListCtrl函数的一个成员函数就能够了:

CImageList* SetImageList( CImageList* pImageList, int nImageList );

Return Value

A pointer to the previous image list.

Parameters

pImageList

Pointer to the image list to assign.

nImageList

Type of image list. It can be one of these values:

    • LVSIL_NORMAL Image list with large icons.

    • LVSIL_SMALL Image list with small icons.

    • LVSIL_STATE Image list with state images. 

不用说太多,我这里第二个参数直接使用的LVSIL_SMALL选项,毕竟16*16的图片绝对不大。

而后这样就实现了绑定,可是此时你须要知道,虽然两个对象绑定了,可是ImageList对象依旧可以独立于ListCtrl进行修改操做。

那么绑定了以后呢?仍是要看InsertItem函数。

InsertItem函数形式有好几个,这里须要使用这种形式:

int InsertItem( int nItem, LPCTSTR lpszItem, int nImage );

这个形式的函数专门添加了nImage这个参数,目的就是为了实现列表的添加。

nImage的选择是对应ImageList中的图像寻址功能,若是在ImageList中添加好了图片,那么InsertItem函数就会根据这个参数的值取寻找对应的图片,而后直接将其添加到列表中。

虚拟列表我会在新的随笔中介绍,并会介绍一下个人思考过程。

相关文章
相关标签/搜索