CListCtrl控件功能扩展
2010年05月19日
一、所有者绘制(owner-draw)和自定义绘制(custom-draw)
这两种方法应该是控件自绘中最常用到的普遍方法。(当然如果只是改变控件颜色只需要处理WM_CTLCOLOR消息就可以了。)但是对于这两者的区别,可能很多开发人员并不是很清楚。如果你做过控件自绘,可能对owner-draw已经很熟悉了。一般只要设置控件的自绘风格属性,并实现owner-draw的消息(WM_DRAWITEM)响应虚函数(DrawItem)就可以了。可以应用这种方法的控件包括拥有自绘风格的Button、ComboBox、ListCtrl、Menu、StatusBar、HeaderCtrl、TabCtrl等大部分控件,MFC在控件需要重绘的时候调用绘制函数,并传递DC及控件位置、大小等信息,我们需要做的就是利用这些信息来绘制自己需求的控件外观。但是这种方式不能用于EditCtrl,也不能用于非report风格的ListCtrl。
custom-draw方式是响应的NM_CUSTOMDRAW消息,与WM_DRAWITEM消息不同,它是被包含在WM_NOTIFY消息中被发送的,需要在类实现中加入消息映射。与owner-draw方式比较,这种绘制方式最大的优势是对绘制的阶段进行了严格控制,可以在不同的响应阶段进行不同的绘制策略,比如既可以进行默认绘制,也可以重载函数进行特殊绘制,还可以只改变一些变量的值让MFC自己去按照要求重绘。我们知道owner-draw方式的绘制函数中,对于所有的绘制细节都需要进行GDI或GDI+的代码控制,而custom-draw方式中,我们可能仅仅改变几个变量值(比如控件颜色)就完成了需求。custom-draw方式支持的控件包括ListView、ToolBar、ToolTip、TreeView等,其中对于ListCtrl支持所有的样式。关于custom-draw的详细信息,可以参考这篇文章http://msdn.microsoft.com/zh-cn/library/ms364048(VS.80).aspx。
二、加载缩略图
这个其实很简单,自己创建一个CImageList类型的对象,并自定义图像的大小及像素类型,然后调用CListCtrl的SetImageList函数设置就可以了。需要注意的一点是,normal和small两种type中,small类型必须设置。
三、自定义表头
需要写一个继承CHeaderCtrl的子类,实现DrawItem函数,在其中进行表头背景和字体、文本颜色等设置并进行绘制;如果要改变表头的高度,可以映射HDM_LAYOUT消息响应函数,在其中设置控件布局。之后在自己的ListCtrl类中声明一个自定义的HeaderCtrl类型变量,并在PreSubclassWindow函数中调用HeaderCtrl的SubclassWindow函数使其子类化,然后在初始化的时候使其各Item的format具有HDF_OWNERDRAW风格就可以了。
四、调整CListCtrl的背景、字体、文本颜色和行高
实现思路与上述表头的方法基本相同。当然要设置list的自绘风格,并选择自绘的方式。另外对于调整行高,如果加载了缩略图的话,行高就会随之调整了。另一个简单的办法就是设置字体的大小来实现,与缩略图是一个道理。如果想自己精确定义行高,则比较麻烦一点。首先设置list的自绘风格,然后重载MeasureItem函数,在其中设置结构体中的item高度变量的值,再在消息映射中添加ON_WM_MEASUREITEM_REFLECT(),就可以让list在合适的时候响应来改变行高。需要注意的两点是:
1、MeasureItem与WM_MEASUREITEM消息响应函数OnMeasureItem是不同的;
2、触发MeasureItem函数调用的WM_MEASUREITEM消息是在一定的情况下才被发送,比较简单的方法是send一个WM_WINDOWPOSCHANGED消息来触发。
3、设置LVS_OWNERDRAWFIXED风格需要在Create或者PreSubclassWindow函数中进行,否则MeasureItem不会被调用。
以上为目前为止的总结,后面有了新的内容会补充进来。
2010年05月19日
一、所有者绘制(owner-draw)和自定义绘制(custom-draw)
这两种方法应该是控件自绘中最常用到的普遍方法。(当然如果只是改变控件颜色只需要处理WM_CTLCOLOR消息就可以了。)但是对于这两者的区别,可能很多开发人员并不是很清楚。如果你做过控件自绘,可能对owner-draw已经很熟悉了。一般只要设置控件的自绘风格属性,并实现owner-draw的消息(WM_DRAWITEM)响应虚函数(DrawItem)就可以了。可以应用这种方法的控件包括拥有自绘风格的Button、ComboBox、ListCtrl、Menu、StatusBar、HeaderCtrl、TabCtrl等大部分控件,MFC在控件需要重绘的时候调用绘制函数,并传递DC及控件位置、大小等信息,我们需要做的就是利用这些信息来绘制自己需求的控件外观。但是这种方式不能用于EditCtrl,也不能用于非report风格的ListCtrl。
custom-draw方式是响应的NM_CUSTOMDRAW消息,与WM_DRAWITEM消息不同,它是被包含在WM_NOTIFY消息中被发送的,需要在类实现中加入消息映射。与owner-draw方式比较,这种绘制方式最大的优势是对绘制的阶段进行了严格控制,可以在不同的响应阶段进行不同的绘制策略,比如既可以进行默认绘制,也可以重载函数进行特殊绘制,还可以只改变一些变量的值让MFC自己去按照要求重绘。我们知道owner-draw方式的绘制函数中,对于所有的绘制细节都需要进行GDI或GDI+的代码控制,而custom-draw方式中,我们可能仅仅改变几个变量值(比如控件颜色)就完成了需求。custom-draw方式支持的控件包括ListView、ToolBar、ToolTip、TreeView等,其中对于ListCtrl支持所有的样式。关于custom-draw的详细信息,可以参考这篇文章http://msdn.microsoft.com/zh-cn/library/ms364048(VS.80).aspx。
二、加载缩略图
这个其实很简单,自己创建一个CImageList类型的对象,并自定义图像的大小及像素类型,然后调用CListCtrl的SetImageList函数设置就可以了。需要注意的一点是,normal和small两种type中,small类型必须设置。
三、自定义表头
需要写一个继承CHeaderCtrl的子类,实现DrawItem函数,在其中进行表头背景和字体、文本颜色等设置并进行绘制;如果要改变表头的高度,可以映射HDM_LAYOUT消息响应函数,在其中设置控件布局。之后在自己的ListCtrl类中声明一个自定义的HeaderCtrl类型变量,并在PreSubclassWindow函数中调用HeaderCtrl的SubclassWindow函数使其子类化,然后在初始化的时候使其各Item的format具有HDF_OWNERDRAW风格就可以了。
四、调整CListCtrl的背景、字体、文本颜色和行高
实现思路与上述表头的方法基本相同。当然要设置list的自绘风格,并选择自绘的方式。另外对于调整行高,如果加载了缩略图的话,行高就会随之调整了。另一个简单的办法就是设置字体的大小来实现,与缩略图是一个道理。如果想自己精确定义行高,则比较麻烦一点。首先设置list的自绘风格,然后重载MeasureItem函数,在其中设置结构体中的item高度变量的值,再在消息映射中添加ON_WM_MEASUREITEM_REFLECT(),就可以让list在合适的时候响应来改变行高。需要注意的两点是:
1、MeasureItem与WM_MEASUREITEM消息响应函数OnMeasureItem是不同的;
2、触发MeasureItem函数调用的WM_MEASUREITEM消息是在一定的情况下才被发送,比较简单的方法是send一个WM_WINDOWPOSCHANGED消息来触发。
3、设置LVS_OWNERDRAWFIXED风格需要在Create或者PreSubclassWindow函数中进行,否则MeasureItem不会被调用。
以上为目前为止的总结,后面有了新的内容会补充进来。