上一版本(链接:https://blog.csdn.net/u012156872/article/details/103827466)中测试过程中发现,如果鼠标快速在几个按钮之间切换,会有闪烁的问题,说到闪烁多数人就会想到双缓存绘图,但是其实本身就已经采用的双缓存绘制模式,该会是哪里出现了问题呢?鼠标的进入和离开都是在mousemove消息事件里面通过SetCapture来处理的,这种处理方式未尝不可,看来是哪里没处理好?先尝试在mousemove和mouseleave里面分开独立处理试试,闪烁问题有显著改善。
修改后的代码如下:
void CSWButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CButton::OnMouseMove(nFlags, point);
if (nFlags & MK_LBUTTON && m_bTracking == FALSE)
return;
CWnd* pWnd = GetActiveWindow();
CWnd* pParent = GetOwner();
ClientToScreen(&point);
CWnd* pWndUnderMouse = WindowFromPoint(point);
//
if (pWndUnderMouse && pWndUnderMouse->m_hWnd == this->m_hWnd)
{
if (!m_bTracking)
{
m_bTracking = TRUE;
InvalidateRect(NULL, TRUE);
TRACKMOUSEEVENT trackMoureEvent;
trackMoureEvent.cbSize = sizeof(trackMoureEvent);
trackMoureEvent.dwFlags = TME_LEAVE;
trackMoureEvent.hwndTrack = m_hWnd;
::_TrackMouseEvent(&trackMoureEvent);
TRACE("CSWButton::OnMouseMove(1)=%d\n", GetTickCount());
}
}
else
{
if (m_bTracking)
{
m_bTracking = FALSE;
InvalidateRect(NULL, TRUE);
TRACE("CSWButton::OnMouseMove(2)=%d\n", GetTickCount());
}
}
return;
// 以下为之前的处理方式
//
if ((GetCapture() != this) && (pWnd != NULL && pParent != NULL))
{
if (!m_bTracking)// 之前版本少了这个判断,所以闪烁严重
{
m_bTracking = TRUE;
SetCapture();
InvalidateRect(NULL, TRUE);
}
}
else
{
if (pWndUnderMouse && pWndUnderMouse->m_hWnd != this->m_hWnd)
{
if (m_bTracking == TRUE)
{
m_bTracking = FALSE;
InvalidateRect(NULL, TRUE);
}
if (!(nFlags & MK_LBUTTON))
ReleaseCapture();
}
}
}
新增加OnMouseLeave:
void CSWButton::OnMouseLeave()
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_bTracking = FALSE;
InvalidateRect(NULL, TRUE);
CButton::OnMouseLeave();
}