回顾:chrome
刚刚写完,由于是分期写的,因此最初想好好作一下的文章格式半途而废了~说的也许会有点啰嗦,可是全部的基础用到的技术细节应该都用到了。app
若是还有什么疑问,请回复留言,我会尽力解答。ide
若是有错误,请指正。函数
这里全部使用到的内容在VS2010中均能正常运行。网站
可运行程序的截图:this
CListCtrl控件的建立spa
若是一个CListCtrl控件对象和dialog上的控件已经绑定,那么能够跳过这个这一步,由于绑定了的对象已经完成了建立。翻译
可是若是要在dialog上凭空建立出来一个列表控件,那么就须要了解CListCtrl类的成员函数:Create指针
先看这个函数的原型:code
BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
第一个参数是用来声明这个列表的风格,具体风格以下 :
一下翻译这么多,有点累,看来个人英语仍是太差,否则怎么会以为累~
第二个参数: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_SMALL选项,毕竟16*16的图片绝对不大。
而后这样就实现了绑定,可是此时你须要知道,虽然两个对象绑定了,可是ImageList对象依旧可以独立于ListCtrl进行修改操做。
那么绑定了以后呢?仍是要看InsertItem函数。
InsertItem函数形式有好几个,这里须要使用这种形式:
int InsertItem( int nItem, LPCTSTR lpszItem, int nImage );
这个形式的函数专门添加了nImage这个参数,目的就是为了实现列表的添加。
nImage的选择是对应ImageList中的图像寻址功能,若是在ImageList中添加好了图片,那么InsertItem函数就会根据这个参数的值取寻找对应的图片,而后直接将其添加到列表中。
虚拟列表我会在新的随笔中介绍,并会介绍一下个人思考过程。