一、自绘控件途径
1、如何以合法的手段来达到美化界面的效果?一般美化界面的方法包括:
1.1 利用Windows的消息机制,截获有用的Windows的消息。通过MFC的消息映射(Message Mapping)和反射(Message Reflecting)机制,在Windows准备或者正在绘制该元素时,偷偷修改它的状态和行为,譬如:让按钮的边框为红色;
在父窗口里,截获自身的或者由子元素(包括控件和菜单等元素)传递的关于界面绘制的消息;
1.2 利用MFC类的虚函数机制,重载有用的虚函数。在MFC框架调用该函数的时候,重新定义它的状态和行为;
子类化子元素,或者为子元素准备一个新的类(一般来说该类必须继承于MFC封装的某个标准类,如:CButton)。在该子元素里,截获自身的或者从父窗口反射过来的关于界面绘制的消息。譬如:用户可以创建一个CXPButton类来实现具有XP风格的按钮,CXPButton继承于CButton。
二、自绘,相关消息
1.WM_PAINT消息相信大家都很熟悉,一个窗口要重绘了,就会有一个WM_PAINT消息发送给窗口。=>它要求应用程序完成元素界面的所有绘制过程,想象一下如何画出一个完整的列表控件?太麻烦了。一般来说,很少有人喜欢使用WM_PAINT;
2.WM_ERASEBKGND消息
Windows在向窗口发送WM_PAINT消息之前,总会发送一个WM_ERASEBKGND消息通知该窗口擦除背景。
可以响应窗口(包括子元素)的WM_ERASEBKGND消息,以更改它们的背景
3. WM_CTLCOLOR消息:
设置前景和背景文本颜色,并为控件或者对话框的非文本区域选定一个刷子。
4. WM_DRAWITEM消息
OnCtlColor只能修改元素的颜色,但不能修改元素的界面框架,WM_DRAWITEM则可以。
当一个具有Owner draw风格的元素(包括按钮、组合框、列表框和菜单等)需要显示外观时,该元素会发送一条WM_DRAWITEM消息至它的隶属窗口(Owner)。
注意:
1、父窗口的OnDrawItem()函数、子控件的DrawItem()函数
在MFC中子控件要绘制的时候框架就会向父窗口发送WM_DRAWITEM消息,而父窗口会在WM_DRAWITEM消息响应函数OnDrawItem()里调用子控件的DrawItem()函数,所以我们既可以在父窗口的OnDrawItem()函数里绘制控件,也可以重载子控件DrawItem()函数,在DrawItem()里自绘控件。一般都是选择在子控件的DrawItem()函数里绘制控件,这样可以避免父窗口代码臃肿。
不是所有设置成自画类型的控件都会调用父窗口的OnDrawItem,例如ListBox的自画,你就必须重载CListBox的DrawItem方法和MeasureItem方法才可以,但按钮、菜单等的自画则会调用OnDrawItem。
三、自绘控件的步骤:
我们以做一个关闭按钮为例
1.先创建一个MFC类继承自CButton。
2. 利用MFC类的虚函数机制,重载有用的虚函数。给这个类添加 一个虚函数DrawItem()、一个虚函数PreSubclassWindow()、一个afx_msg BOOL OnEraseBkgnd()函数(一般以afx开头的函数都会在消息映射里面有一条映射);
3.DrawItem()是控件的自绘处理函数,在这个函数中可以对控件的样式进行描绘。
(按钮Cbutton、列表框ClistBox、列表ClistCtrl)=》都会添加一个虚函数DrawItem()、一个虚函数PreSubclassWindow()、一个afx_msg BOOL OnEraseBkgnd()函数这3个函数;