在MFC中,对按钮控件进行重绘;通常的做法是:当按钮处于不同状态时,贴上相应的背景图片。
具体实现分四步:
1. 从CButton类派生一个子类CButtonEx
2. 重载虚函数PreSubclassWindow,将按钮的风格修改为BS_OWNERDRAW
3. 从外部加载按钮处于不同状态下的背景图片
4. 重载虚函数DrawItem;并在函数中,根据按钮的不同状态贴图
部分源码如下:
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);
}
// TODO: Add your message handler code here and/or call default
m_bIsLBtnDown = FALSE;
CButton::OnLButtonUp(nFlags, point);
}
效果图如下:
具体实现分四步:
1. 从CButton类派生一个子类CButtonEx
2. 重载虚函数PreSubclassWindow,将按钮的风格修改为BS_OWNERDRAW
3. 从外部加载按钮处于不同状态下的背景图片
4. 重载虚函数DrawItem;并在函数中,根据按钮的不同状态贴图
具体实现方式,网上很多源码都有介绍。我只想提两点需要注意的地方:背景处理,按下状态。
背景处理
对于方角矩形,没什么好说的;整张背景图贴上即可。圆角矩形因需要考虑矩形边角与父窗口背景融合的问题,在背景处理上会有些额外的设置。
首先,在子窗口重绘父窗口背景。通常,我们会把父窗口设成Clip children风格,即:子窗口的背景父窗口不处理。
其次,矩形边角的区域需要清除。我们有两种方法处理:方法1,把边角区域设成某颜色(异于按钮背景颜色),绘制时,用TransparentBlt函数,将其透掉。方法2,准备一张掩码图;利用BitBlt光栅运算,把边角清除。
按下状态
部分源码如下:
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);
}
效果图如下: