MFC自绘控件学习总结,100分奉下,欢迎拍砖

MFC自绘控件学习总结,100分奉上,欢迎拍砖。
备注:本来想给300分的,但论坛只允许我给100分内的帖子..........
      对下面我即将说的废话不感兴趣的可以直接从14条看起,文章最后给出了程序的 Release。

前言:从这学期开始就一直在学习自绘控件(mfc),目标是做出一款播放器界面,主要是为了打好基础,因为我基础实在是很烂....说说我自己心得体会以及自绘控件的方法吧,算是吐槽吧,说的不对和不全的地方,或者有更好的方法,请不吝赐教。

我的机器环境是:Windows7旗舰版 Service Pack 1,Visual studio 2005

1).重绘某个控件时,强烈推荐使用子类化方法,比如想自绘Button控件, 首先添加自己的类CMYButton 继承自 CButton ,声明一个CMYButton 对象,然后使用 SubclassDlgItem(UINT nID, CWnd* pParent ); // 第一个参数表示控件ID,第二个参数表示指向父窗口对象指针,一般用this表示(如果不想用SubclassDlgItem。那么可以使用CMYButton自身提供的Create方法 动态创建一个Button),这样子就可以在自己类中添加重写WindowProc()这个窗口过程函数了,非常,非常,重要 ,其他控件自绘都参考这一条.

2).我入手的第一个控件是 Button,我终于知道我的基础有多烂,很多基本的函数如GetDlgItem() , SubclassDlgItem() 都不知道,查资料,看源码 ,费了不少时间才基本完成Button的自绘,另外自绘

的按钮默认情况下是不能响应键盘按下Enter的,需要额外做一些处理。(关键词:BS_OWNERDRAW ,DrawItem),(在后期我仿造qq登陆的Button加了个效果,Hover和Leave时是渐变的,只在设置

对话框里面的Button使用了)

3).然后是 RadioButton ,CheckBox 其实和Button异曲同工的,推荐了解3个API函数CheckRadioButton(),SetCheck(),GetCheck().

4).另外对于不规则按钮实现需要掌握 SetWindowRgn(),CombineRgn(),SelectClipRgn() 3个API函数,其他不规则窗口,控件也可以参考这个方法。

5).然后是Edit控件自绘,不算是完全自绘,只重绘了非客户区(如果没特殊需要也没必要重绘客户区),和改变背景颜色,改变字体,不过后期我加了个效果,鼠标在Edit上和离开Edit时边框是渐变的(关

键词:CtlColor,WM_NCPAINT),RichEdit也可以用这个方法

6).然后是ToolTip(气泡提示控件),微软提供了NM_CUSTOMDRAW这个通告消息,以WM_NOTIFY形式发送,可以用MFC类向导添加到自己的派生类中,不过我推荐重写OnPaint函数,完全自绘(难点:

需要根据文本内容计算出控件的大小,显示位置等)
在后期我实现了,淡入,点击/超时 淡出的效果(需要映射TTN_POP 和TTN_SHOW两个通告消息),不过挪开淡出效果没能实现,求指导。

7).然后是Sliderctrl, 微软提供了NM_CUSTOMDRAW这个通告消息,以WM_NOTIFY形式发送,可以用MFC类向导添加到自己的派生类中,前期我是用的这种方法,不过后期发现这种方法局限性很大,

推荐重写OnPaint函数,完全自绘(关键点:在PreSubclassWindow 里面把 Thumb(拇指按钮),Channel(凹槽),以及整个控件大小保存起来,以便在OnPaint里面绘制)

8).然后是Staic控件,这个比较简单,重写OnPaint函数 画上文本,把DC设为透明模式就行了,有人会说直接在CtlColor直接SetBkMode(TRANSPARENT)就行了,不用在OnPaint处理,但这是有个问

题的, 如果要求文本一直变化,旧的文本没有擦除,新设置的文本又盖上了。所以根据这个控件的用途,自己选择适合的方法吧。

9).然后是Menu,这个较难,严格来说Menu 并不算控件,他是派生自CObject类的,微软提供了MeasureItem,DrawItem两个虚函数类供自绘 ,MeasureItem作用是计算出菜单的高度和宽度,系统

会自动根据文本内容最长那项来作为Menu的宽度。DrawItem作用顾名思义就是画了,但是有个致命的问题,自绘出来的Menu 有个系统默认的边框,十分邪恶和难看,(ModifyStyle和

SetWindowLong去不掉边界的)这时到自己派生的CMYMenu里面 发现微软只给咱们提供了仅仅5个虚函数,没有提供WindowProc()这个窗口过程函数,这不是坑爹嘛.......这时一般做法都是派生自

CWnd 自己实现菜单的功能.不过查了下资料任然可以自绘的:需要使用钩子 替换菜单的窗口过程,在WM_CREATE时 去掉边界Stytle 有兴趣的朋友可以Google一下。(难点:替换菜单窗口过程)

10). 然后是Combobox控件,这个较难, 微软提供了CompareItem,DeleteItem,DrawItem,MeasureItem 4个虚函数供自绘。我只用了后2个,(如果只加了 CBS_SORT 必须重写CompareItem这个

函数,除非使用了CBS_HASSTRINGS | CBS_SORT就可以不重写CompareItem()), 别以为这样子就完了,运行后,打开Combobox 显示的 List 有系统默认的边框!!!ModifyStyle和SetWindowLong

去不掉边界.老规矩查资料去,不看不知道,一看吓一跳,Combobox 是由3个控件组合成成的(难怪叫组合框),分别是Edit,Listbox,和combo本身(除去Edit ,Listbox剩下那部分),当时我就震惊了,迷茫

了! 这时需要添加OnCtlColor这个函数,在里面 使用SubclassWindow()这个API函数子类化 ListBox 和 Edit(在这之前 你还需要准备自绘好的 ListBox控件 和Edit控件)Combobox 有3种样式 

CBS_SIMPLE, CBS_DROPDOWNLIST,CBS_DROPDOWN,第一种不说了不常用,第二种是不能输入只能点击选择,第三种可以输入可点击选择. 我的程序里面使用的是CBS_DROPDOWNLIST样式

11).Combobox 在 Windows7 下疑惑:关闭滑动打开组合框特效 ,自绘Combobox是可以去掉边界并进行窗口剪切的(圆角矩形) ,  如果是 开启滑动打开组合框特效,系统会加上边框, 剪切的圆角又

变成直角了, 跟踪调试发现是在WM_WINDOWPOSCHANGING 消息里面搞的鬼 ,有兴趣的朋友可以对比看看,暂时为找到解决方案。。。
开启/关闭 滑动打开组合框特效 :计算机-右键属性-高级系统设置-高级-性能设置-视觉效果

12).然后是 TabCtrl ,微软提供了DrawItem,MeasureItem 2 个虚函数供自绘,需要加 TCS_OWNERDRAWFIXED这个Stytle,表明这个控件需要自绘,不过我没有用这种方式,我直接重写了OnPaint函数

完全自绘(难点:需要自己计算每个标签大小,位置,以及与之绑定的Dialog显示位置)
 
13).最后是窗体框架绘制(非客户区),这个较难,看了很多例子源码,也花了不少时间,WM_MOVE,WM_PAINT ,WM_NCPAINT,WM_NCACTIVATE,这4个消息自绘成功的关键 ,  在绘制时候还需要