自绘按钮补遗

2016-01-29 12:04 4 1 收藏

自绘按钮补遗,自绘按钮补遗

【 tulaoshi.com - C语言心得技巧 】

自绘按钮补遗
作者:杜修杏

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

下载本文配套源代码
(包括:改进后的CXPButton类、练习程序、练习程序答案)

在《自绘按钮的实现》一文中所示范的CXPButton按钮从形状上看可以说是一个不规则按钮。我们把MFC中提供的控件成为标准控件,而其中的按钮控件则可称为规则按钮,因为它是的形状是一个规则的矩形。但是随着流线型设计在界面设计中被广泛采用,越来越多的程序设计者都乐意在自己的作品中加入一些非规则形状的控件。以按钮为例,最简单的就到有圆形按钮,三角按钮等。下图是一组定义好的圆形按钮:



但是这些在我们眼中似乎呈现出不规则形状的按钮,有时候的表现却不近乎人意。以之前设计的CXPButton为例,下面我们就来找找它的缺陷。我们把对话框的背景色改为其它颜色,看看会有什么效果。修改背景色的方法如下:为对话框类添加WM_ERASEBKGND消息,如果你在类向导中找不到该消息,请参考《自绘按钮的实现》中介绍的方法,注意在添加对话框中要把Filter for messages available to设为Child Window才能在列表中看到WM_ERASEBKGND消息。我们在函数中添加绘制背景色的代码:

BOOL CXPButtonDemoDlg::OnEraseBkgnd(CDC* pDC) {BOOL retValue= CDialog::OnEraseBkgnd(pDC);CRect rc;GetClientRect(&rc);pDC->FillSolidRect(&rc,RGB(0,0,255));return retValue;}
编译后运行程序,可以看到下面的效果,在按钮的四个角上出现了难看的边角,这就是我所说的缺陷了:



既然发现了问题,下面当然就是动手来解决问题的时间了。在《自绘按钮的实现》一文中曾经讲过,按钮的绘制主要在DrawItem()函数中完成。这里要补充一点就是DrawItem()是MFC所提供的系统函数,所以可以通过下图的方法添加。选择Add Virtual Function…之后在弹出对话框左边的列表中找到DrawItem,选择Add and Edit即可。



好了,我们接着上面的话题。要解决按钮显示的“残角”问题,在这里需要使用一个叫做CRgn的类,这个类在创建不规则控件的时候经常要用到,我们可以通过CRgn类来设置控件的有效区域。那么什么是有效区域呢?以圆形按钮为例,MFC默认的按钮形状是矩形的,为了实现圆形按钮的效果,我们希望能够把原来矩形的四角裁剪掉,只保留中间的圆形区域。这种关系可以用下图来表示:



图中的A是原来的矩形区域,B是需要裁剪的区域,而C是有效区域。我们希望程序不要把B看作按钮的一部分,当鼠标在B上面点击的时候不要产生任何效果。设置按钮的有效区域一般是在PreSubclassWindow()函数里面实现的:
void CXPButton::PreSubclassWindow() {CButton::PreSubclassWindow();ModifyStyle(0, BS_OWNERDRAW);//设置按钮的有效区域CRgn rgn;CRect rc;GetClientRect(&rc);//有效区域为一个角半径为5的圆角矩形rgn.CreateRoundRectRgn(rc.left,rc.top,rc.right,rc.bottom,5,5);SetWindowRgn(rgn,TRUE);rgn.DeleteObject();}
编译后运行程序,我们发现尽管已经设置了按钮的有效区域,但是问题还是没有解决,这是为什么呢?前面我们曾经通过对话框的WM_ERASEBKGND消息函数来改变对话框的底色,其实按钮也有它的WM_ERASEBKGND消息函数,它会使用系统颜色根据控件的默认形状来绘制控件的底色。所以我们要重载按钮的WM_ERASEBKGND消息函数,让它什么都不做:
BOOL CXPButton::OnEraseBkgnd(CDC* pDC) {//禁止绘制底色return TRUE;}
再编译一次,运行后发现,难看的"残角"不见了:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com)

在《自绘按钮的实现》一文中还讲过在DrawItem()函数中应该先画底色,其实这是有前提的,前提就是你已经知道了按钮所在对话框所使用的背景色,你可以使用这个颜色作为按钮的底色来进行填充。这样即使程序会在WM_ERASEBKGND消息函数中使用系统颜色来绘制控件的底色,但是等到它执行DrawItem()的时候,马上又会把之前的矩形底色覆盖,从而不留痕迹地把“残角”掩盖掉。

来源:https://www.tulaoshi.com/n/20160129/1484485.html

延伸阅读
ISO 8859-1 (Latin-1) characters    ¡ ¡¡ ¢ ¢¢ £ ££ ¤ ¤¤ ¥ ¥¥ ¦ ¦¦ § §§ ¨ ¨¨ © ©© ª ª...
标签: ASP
    asp 里面没有urldecode函数,好象aspx里有吧,我不太清楚,但asp里面还是用得很多。在网上查找了有别人写的urldecode函数,但是这个函数有错误,而且在一些方面写得比较难理解。而且有错误,当里面有生僻双字节文字时就会产生错误,如“乄”经urlencoder后为“%81W”,解码就不能成功。   其实双字节编码在这里只要把"W"...
经过我对网络上IP数据包的跟踪,对我写的《TCP/IP学习笔记》进行补充。通过本文,可以加深对TCP/IP的认识。 ●网络环境:ADSL宽带 ●IP数据包内容:通过Outlook发送邮件,帐号是xiaojin8039@163.com,给我的其他邮箱xiaoj@njb.swirebev.com发送邮件,系统从而捕获的IP包。 ●所有IP包均为TCP协议 1、关于IP包的分片情况...
标签: 网络游戏
《艾尔之光》度娘自绘 春天挖坑秋天填坑     1L喂度娘度娘乖乖…~     在温暖的春天挖一个大大的坑…     慢慢填啊填…     填啊填     填啊填     到了秋天~ 这个坑就填完了~?     结构能力还是不行… 眼镜的话总感觉...

经验教程

316

收藏

83
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部