图像列表控件(CImageList)是相同大小图像的一个集合,每个集合中均以0为图像的索引序号基数,(可以把这些图标看成是以数组方式存储的),图像列表通常由大图标或位图构成,其中包含透明位图模式(实际上,所有的再一个图像列表中的图标都被存储在一个屏幕设备的位图中)。可以利用windows
API来绘制、建立和删除图像,并能实现增加、删除、替换和拖动图像邓操作。图像列表控件提供了控制图像列表额基本方法,这些方法在Windows
95及以后版本才能实现。该控件是不可见的,通常与其他如CListBox、CComboBox、CComboBoxEx以及CTabCtrl一起使用,为他们提供图标资源。
一、图像控件的对象结构
1 图像控件的数据成员
m_hImageList连接图像对象的控件句柄
2 图像控件的建立方法
CImageList&
ImageList建立图像控件对象结构,Create初始化图像列表并绑定对象,图像控件的建立方法如下
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);
其中各项参数的含义为:cx定义图像的宽度,单位为像素;cy定义图像的高度,单位为像素;nFlags确定建立图像列表的类型,可以是以下值的组合:ILC_COLOR、ILC_COLOR4、ILC_COLOR8、ILC_COLOR16、ILC_COLOR24、ILC_COLOR32、ILC_COLORDDB和ILS_MASK;nInitial用来确定图像列表包含的图像;nGrow用来确定图像列表可控制的图像数量。
nBitmapID用来确定图像列表联系的位图标志值;crMask表示颜色屏蔽位;lpszBitmapID用来确定包含位图资源额标识串;imagellist1指向图像列表控件对象的一个指针;nImage1图像列表1中包含的图像数量;imagelist2指向图像列表控件对象的一个指针。
添加图像的两种方法
通常可以向CImageList对象中添加位图和图标资源,其资源可以是程序中资源文件中的资源,也可以直接从外部文件调入。
(1)从程序中资源文件中添加图标和位图图像如下所示
// 创建一个CImageList类的指针变量
CImageList* pImageList;
pImageList = new CImageList();
pImageList->Create(32, 32, ILC_COLOR32, 0, 4);
// 添加图标,图标可以随图像列表大小自动拉伸
pImageList->Add(AfxGetApp()->LoadIcon(IDI_ICON1));
pImageList->Add(AfxGetApp()->LoadIcon(IDI_ICON2));
// 添加位图,并使黑色为透明色,如果图像列表大小和位图大小不一致可能会导致天添加失败
CBitmap bmp;
bmp.LoadBitmap(IDB_BITMAP1)
pImageList->Add(&bmp, RGB(0, 0,
0));
bmp.DeleteObject();
bmp.LoadBitmap(IDB_BITMAP2)
pImageList->Add(&bmp, RGB(0, 0,
0));
(2)从外部文件中添加图标和位图图像
HBITMAP hBitmap;
CBitmap *pBitmap;
CString FilePathName = "e:\TIME.bmp";
pBitmap = new CBitmap;
// 从文件导入位图
hBitmap =
(HBITMAP)LoadImage(AfxGetInstanceHandle(),FilePathName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
pBitmap->Attach(hBitmap);
m_pImageList->Add(pBitmap, RGB(0,0,0));
这样一个图像列表控件就创建好了,并且已经添加了图像,接下来就可以在其它控件中使用其中的图像。通常需要调用SetImageList(m_pImageList)将当前图像列表设置为引用图像源。
3 图像控件的属性类
图像控件的属性类包括返回m_hImageList控制句柄GetSafeHandle,取得图像列表中的图像数量GetImageCount,设置图像列表的背景颜色SetBkColor,取得图像列表的背景颜色GetBkColor。
4 图像控件的操作方法
图像控件的操作方法包括将一个图像列表绑定到一个对象上Attach、将对象上的图像列表解除绑定并返回句柄Detach、删除一个图像列表DeleteImageList、将一个图像增加到图像列表中Add和将一个图像从图像列表中删除Remove等。
另外一种加载BMP位图的方法是:
CImageList* m_pImageList = new
CImageList();
HBITMAP hBitmap;
CBitmap* pBitmap;
CString strFileName;
strFileName.Format("%s\\res\\root.bmp", szPath);
hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),
(LPCTSTR)strFileName,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
pBitmap = new
CBitmap;
pBitmap->Attach(hBitmap);
m_pImageList->Add(pBitmap,RGB(0,0,0));
delete pBitmap;
(另:1.
标签控件的每一个项目的iImage组成了一个序列,这个序列所对应的图形是用另一个类CImageList来管理的。下面请看CImageList的用法。
我在使用CImageList时,只用到以下几个成员函数:
1.BOOL Create(int cx,int cy,UINT nFlags,int
nInitial,int nGrow);
这个函数建立一个含nGrow个图形(每个图形为cx长,cy高以nInitial为初值:通常为0)的空CImageList;其中有个nFlages参数,它用来指定图形的颜色属性,它的值只能为以下几个值中的一个:
ILC_COLOR 使用默认颜色(一般为16色)
ILC_COLOR4 使用4位色(16色)
ILC_COLOR8 使用8位色(256色)
ILC_COLOR16 使用16位色(64K色)
ILC_COLOR24 使用24位色(16M色)
ILC_COLOR32 使用32位色(4G色)
ILC_COLORDDB 使用系统当前色
2.BOOL Create(UINT nBitmapID,int cx,int
nGrow,COLORREF crMask);
这个函数是以nBitmapID所代表的位图(已在rc文件中定义,与定义工具条的位图相似)建立一个含有nGrow个图形(每个图形长为cx)的CImageList;
其中crMask指定位图中的什么颜色将被替换为黑色,一般就用黑色(RGB(0,0,0))。
3.int Add(CBitmap*PBmImage,COLORREF crMask);
这个函数往CImageList中追加一个位图。其中nbmImage可以通过先定义一个CBitmap指针,再用CBitmap的成员LoadBitman来得到。比如:
CBitmap*mVBitmap;
mvhitmap=new CBitmap();
mvbitmap->LoadBitmap(MYPICTURE); //
MYPICTURE是已定义的位图资源crMask参数与前面相同。
4.int Add(HICON hIcon):
这个函数往CImageList中追加一个图标。
其中hIcon可以用AfxGetApp()->LoadIcon(UINT
nIDResource)来得到。如:AfxGetApp()->LoadIcon(MYICON);//其中MYICON是已定义的图标资源,当CImageList定制好后,调用CTabCtrl的成员函数SetImageList,其原型如下:
CImageList*SetImageList(CImageList*pImageList);
其中的pImageList正是指向我们刚才定制的CImageList对象的指针,而以前的iImage参数就是CImageList中的图形序号了。这样,一个带有图形的标签控件就做好了
2.
CBitmap
cBmp;
CClientDC
dc(this);
CDC dcBmp;
dcBmp.CreateCompatibleDC(&dc);
cBmp.CreateCompatibleBitmap(&dc,
nWidth,
nHeight);
CBitmap *pcOldBmp =
dcBmp.SelectObject(&cBmp);
// 开始画图
dcBmp.Rectangle(...);
dcBmp.SelectObject(pcOldBmp);
// 此时得到了位图
CImageList
cImg;
cImg.Add(&cBmp,
(CBitmap*)NULL);
)
二、图像控件的应用技巧
对于图像控件,同样不能单独使用,必须与列表控件、树控件和标签控件相互结合使用,下面分别介绍其具体应用技巧。
1 图像控件在列表控件中的应用技巧
1.1设置图像控件CListCtrl::SetImageList的调用格式如下:
CImageList* SetImageList(CImageList* pImageList,int
nImageList);
其返回值是指向前一个图像列表控件的一个指针,如果不存在前一个图像列表则为NULL;其中参数pImageList是指向图像列表的标识,nImageList是图像列表的类型,可以是如下值:LVSIL_NORMAL用大图标方式进行图像列表;LVSIL_SAMLL用小图标方式进行图像列表;LVSIL_STATE以图像状态进行图像列表。
1.2取得图像控件CListCtrl::GetImageList的调用格式如下:
CImageList* GetImageList(int nImageList)const;
其返回值为指向图像列表控件的指针,其中nImageList用来确定取得返回值的图像列表的值,其取值与设置图像列表函数相同。
CImageList Cil1,Cil2; //定义大小图标像列表
CVCLISTApp *pApp=(CVCLISTApp
*)AfxGetApp();//取得列表控制程序
Cil1.Create(32,32,TRUE,2,2);//建立32位图像控制
Cil1.Add(pApp->LoadIcon(IDI_GJ));//增加选中状态图像
Cil1.Add(pApp->LoadIcon(IDI_XS));//增加非选中状态图像
Cil2.Create(16,16,TRUE,2,2);
//建立16位图像控制
Cil2.Add(pApp->LoadIcon(IDI_GJ));//增加选中状态图像
Cil2.Add(pApp->LoadIcon(IDI_XS));//增加非选中状态图像
m_ListCtrl.SetImageList(&Cil1,LVSIL_NORMAL);//设置大图标控制
m_ListCtrl.SetImageList(&Cil2,LVSIL_SMALL);//设置小图标控制
2 图像控件在树控件中的应用技巧
2.1设置图像控件CTreeCtrl::SetImageList的调用格式如下:
CImageList* SetImageList(CImageList*
pImageList,int nImageListType);
其返回值为指向前一个图像列表的指针,否则为NULL;参数pImageList为指向图像列表的标识,如果pImageList为NULL则所有的图像都将从树控件中被清除;nImageListType为图像列表设置的类型,可以是如下值之一:TVSIL_NORMAL设置正常图像列表,其中包括选中和非选中两种图标;TVSIL_STATE设置图像列表状态,指用户自定义状态。
2.2取得图像控件CTreeCtrl::GetImageList的调用格式如下:
CImageList* GetImageList(UINT nImage);
如果调用成功则返回图像列表控件指针,否则为NULL;nImage为取得返回值的图像列表类型,其取值和取得图像列表控件完全相同。
CImageList Cil1,Cil2;//定义大小图标像列表
CVCTREEApp *pApp=(CVCTREEApp
*)AfxGetApp();//获取应用程序指针
Cil1.Create(16,16,ILC_COLOR,2,2);//建立图像控制
Cil1.Add(pApp->LoadIcon(IDI_PM));//增加选中状态图像
Cil1.Add(pApp->LoadIcon(IDI_CJ));//增加非选中状态图像
m_TreeCtrl.SetImageList(&Cil1,TVSIL_NORMAL);//设置图像控制列表
然后在树控制的结构定义中进行如下设置:
TCItem.item.iImage=0; //设置未选中图像索引号
TCItem.item.iSelectedImage=1;//设置选中时图像引号
MSDN中
由于图像列表不是窗口,它们本身并不是控件;但它们和几种不同类型的控件一起是以,包括列表控件(CListCtrl)、树控件(CTreeCtrl)和选项卡控件(CTabCtrl)。图像列表中的所有图像包含在屏幕设备格式的单个宽位图中。图像列表也可能包括单色位图,该位图包含用于透明地绘制图像(图标样式)的屏蔽。CImageList提供的成员函数使您得以绘制图像,创建和销毁图像列表,添加和移除图像,替换图像,合并图像,以及拖动图像。
图像列表的类型
有两种类型的图像列表(CImageList):非屏蔽的和屏蔽的。非屏蔽的图像列表由包含一个或多个图像的色位图构成。屏蔽的图像列表由相同大小的两个位图构成。第一个是包含图像的色位图,第二个是包含一系列屏蔽的单色位图(一个屏蔽对应第一个位图中的一个图像)。
Create成员函数的一个重载曹永一个标志指示图像列表是否是屏蔽的。(其他重载创建屏蔽的图像列表)。
绘制非屏蔽图像时,只是简单地将其复制到目标DC。绘制屏蔽图像时,图像位和屏蔽位组合,一般在位图中产生显露目标DC背景色的透明区域。绘制屏蔽图像时可以指定几种绘图样式。例如,可以指定图像进行抖色处理以指示选定的对象。
使用图像列表
构造CImageList对象,调用其Create函数的一个重载来创建图像列表并将图像列表附加到CImageList对象;
如果在创建图像列表时没有添加图像,则调用Add或Read成员函数向图像列表添加图像;
通过调用控件的适当成员函数,将图像列表与此控件相关联,或者您自己使用图像列表的Draw成员函数绘制图像列表中的图像;
或许允许用户是以图像列表的内置拖动支持拖动图像。
注意:如果图像列表是用new运算符创建的,则在操作完CImageList对象后必须销毁它。
操作图像列表
Replace成员函数用新的图像替换图像列表(CImageList)中的图像。如果需要动态增加图像列表中的图像数,该函数也有用。SetImageCount函数动态更改存储在图像列表中的图像数。如果增加图像列表的大小,请调用Replace向新图像增加图像。如果减少图像列表的大小,则释放超过新大小的图像。
Remove成员函数移除图像列表中的图像。Copy成员函数可以在图像列表内复制或交换图像。该函数使您得以指示是否应将源图像复制到目标索引,还是应交换源图像和目标图像。
若要通过合并两个图像列表来创建新的图像列表,请使用Create成员函数的适当重载。该Create重载合并现有的图像列表的第一个图像,并将所得的图像存储在新的图像列表对象中。通过在第一个图像上透明地绘制第二个图像来创建新图像。新图像的屏蔽是对两个现有图像的屏蔽位执行逻辑OR元算的结果。
该操作一直重复到所有图像都合并并添加到新的图像列表中。
可以调用Write成员函数将图像信息写入存档,并通过调用Read成员函数读回。
GetSafeHandle、Attach和Detach成员函数使您得以操作附加到CImageList对象的图像列表句柄,而DeleteImageList成员函数删除图像列表但不销毁CImageList对象。
绘制图像列表中的图像
若要绘制图像,请使用CImageList::Draw成员函数。您将需要指定指向DC的指针,要绘制的图像的索引,DC中绘制图像的位置,以及一组指示绘图样式的标志。
指定ILD_TRANSPARENT样式后,Draw是以一个两步进程来绘制屏蔽的图像。