=============================================================
标题:MFC下按钮自绘的实现(四)
摘要:
备注:MFC + VC2005
日期:2010.7.20
姓名:朱铭雷
=============================================================
接下来为自绘的按钮绘制不同状态下的外观,首先绘制按钮按下时的状态。一般在按钮按下时,按钮的文本会向右下方移动一个微小的距离,使其看起来有被“压下”的视觉。
通过如下代码获取按钮的状态:
UINT state = lpDrawItemStruct->itemState;
然后在DrawItem函数中绘制按钮文本之前(DrawText)添加如下代码:
if (state & ODS_SELECTED)
{
rectText.OffsetRect(1, 1);
}
编译运行程序,看下效果。
按钮正常状态:
按钮被按下时:
对比一下,可以看出按钮按下时,按钮上文本向右下方移动一小段距离。测试了一下,效果还不错。
接下来绘制当光标位于按钮之上但按钮并没有被按下时的状态。这里仅仅大致的介绍一下我的方法。
首先在OnMouseMove函数中,添加如下代码:
if (!m_bOver)
{
m_nTimerId = SetTimer(1, 50, TimerProc);
m_bOver = TRUE;
}
其中m_bOver是用来标记光标此时是否在按钮之上的BOOL类型的变量。当光标经过按钮时,触发OnMouseMove函数,在此函数中设置一个定时器,定时时间为50ms,定时时间到了之后将触发TimerProc回调函数。在TimerProc函数中不断的判断此时光标停留在按钮之上,还是已经离开了按钮。
POINT CursorPos;
RECT ButtonRect;
::GetCursorPos(&CursorPos);
::ScreenToClient(hwnd, &CursorPos);
::GetClientRect(hwnd, &ButtonRect);
if (!::PtInRect(&ButtonRect, CursorPos))
{
::PostMessage(hwnd, WM_MOUSELEAVE, 0, 0);
}
else
{
::PostMessage(hwnd, WM_MOUSEHOVER, 0, 0);
}
如果光标停留在按钮之上,投递出WM_MOUSEHOVER消息之后将触发OnMouseHover函数,在该函数中将m_bOver设置为TURE,并调用InvalidateRect函数更新窗口;如果光标已经离开了按钮,投递出WM_MOUSELEAVE消息,触发OnMouseLeave函数,在该函数中将m_bOver设置为FALSE,然后调用InvalidateRect函数更新窗口,接着关闭定时器,因为此时已经不必再连续判断光标是否还停留在按钮之上了。最后在DrawItem函数中判断如果m_bOver为TURE,则绘制一定的图形进行标记。
如下图:
光标不在按钮之上:
光标位于按钮之上: