重绘按钮控件

在MFC中,对按钮控件进行重绘;通常的做法是:当按钮处于不同状态时,贴上相应的背景图片。
具体实现分四步:
1. 从CButton类派生一个子类CButtonEx
2. 重载虚函数PreSubclassWindow,将按钮的风格修改为BS_OWNERDRAW
3. 从外部加载按钮处于不同状态下的背景图片
4. 重载虚函数DrawItem;并在函数中,根据按钮的不同状态贴图

具体实现方式,网上很多源码都有介绍。我只想提两点需要注意的地方:背景处理按下状态

背景处理

对于方角矩形,没什么好说的;整张背景图贴上即可。圆角矩形因需要考虑矩形边角与父窗口背景融合的问题,在背景处理上会有些额外的设置。
首先,在子窗口重绘父窗口背景。通常,我们会把父窗口设成Clip children风格,即:子窗口的背景父窗口不处理。
其次,矩形边角的区域需要清除。我们有两种方法处理:方法1,把边角区域设成某颜色(异于按钮背景颜色),绘制时,用TransparentBlt函数,将其透掉。方法2,准备一张掩码图;利用BitBlt光栅运算,把边角清除。

按下状态

对于系统按钮,当鼠标离开按钮区域时,按钮都处于“常态”状态(不管鼠标左键是否按下);而有些软件(比方说:QQ、360),当鼠标左键按下未弹起时,按钮都处于“按下”状态(不管鼠标是否离开按钮区域)。微软为什么要这样设计按钮,我不清楚;不过,我个人更倾向于后者的效果。要实现后者效果,我们只需要设置按钮的显示状态,即:鼠标按下未弹起时,按钮显示状态始终设置成“按下”状态。

部分源码如下:

void CButtonEx::PreSubclassWindow() 
{
// TODO: Add your specialized code here and/or call the base class
ModifyStyle(0, BS_OWNERDRAW) ;

CButton::PreSubclassWindow();
}

void CButtonEx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
// TODO: Add your code to draw the specified item
CBitmap* pBitmap = NULL;

// 获取按钮状态
UINT state = lpDrawItemStruct->itemState;

// 根据状态,设置背景图片
if (IsWindowEnabled())
{
// 点击
if (state & ODS_SELECTED || m_bIsLBtnDown)
{
pBitmap = &m_bmpBk_Select ;
}
// 禁用
else if (state & ODS_DISABLED)
{
pBitmap = &m_bmpBk_Disable ;
}
// 焦点
else if (state & ODS_FOCUS)
{
// 存在焦点且鼠标盘旋
if (m_nMouseState == MOUSE_HOVER)
{
pBitmap = &m_bmpBk_Hover ;
}
// 存在焦点且鼠标离开
else
{
pBitmap = &m_bmpBk_Focus ;
}
}
// 无焦点
else 
{
// 无焦点且鼠标盘旋
if (m_nMouseState == MOUSE_HOVER)
{
pBitmap = &m_bmpBk_Hover ;
}
// 无焦点且鼠标离开
else
{
pBitmap = &m_bmpBk_Normal;
}
}
}
else
{
pBitmap = &m_bmpBk_Disable ;
}

......

}


void CButtonEx::OnLButtonDown(UINT nFlags, CPoint point) 
{
// TODO: Add your message handler code here and/or call default
m_bIsLBtnDown = TRUE;

CButton::OnLButtonDown(nFlags, point);
}

void CButtonEx::OnLButtonUp(UINT nFlags, CPoint point) 

{
// TODO: Add your message handler code here and/or call default
m_bIsLBtnDown = FALSE;

CButton::OnLButtonUp(nFlags, point);
}


效果图如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值