《如何在MFC设计超链接控件类》
原文传送门:http://blog.kingsamchen.com/archives/517#comment-1912
运行之后一切都完美,只有一个问题,当弹出IE窗口挡住了Label之后,在切换会原来的程序,鼠标移动到Label上时不会再次显示手型鼠标指针。查询资料跟踪程序后发现:
void CLinkLabel::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_bTrack)
{
if (m_bMouseOn)
{
CRect rec;
GetClientRect(&rec);
// 鼠标离开了LinkLabel
if (!rec.PtInRect(point))
{
m_bMouseOn = FALSE;
::ReleaseCapture();
}
}
// 鼠标进入LabelLink
else
{
m_bMouseOn = TRUE;
SetCapture();
// #define IDC_HAND MAKEINTRESOURCE(32649)
// 直接引用IDC_HAND需要添加头文件
::SetCursor(AfxGetApp()->LoadStandardCursor(MAKEINTRESOURCE(32649)));
Invalidate(TRUE);
}
}
CStatic::OnMouseMove(nFlags, point);
}
如果我鼠标悬停在CLinkLabel,如果突然有窗口阻挡了CLinkLabel所在的主窗口,鼠标再次移动到CLinkLabel,因为之前主窗口丢失了焦点,手型鼠标被重置成焦点窗口默认样式,SetCapture(手型)已经自动失效
鼠标不在CLinkLabel,不会发生CLinkLabel::OnMouseMove,鼠标在CLinkLabel,则 rec.PtInRect(point)==TRUE,不会进入进入if (!rec.PtInRect(point))执行m_bMouseOn = FALSE
,因此m_bMouseOn一直是等于TRUE,CLinkLabel认为鼠标一直在控件上,不会再次::SetCursor()。
通过论坛朋友帮助和网上查询咨询找到了两种解决方案:
1、在WM_SETCURSOR消息中执行SetCursor(论坛提供)
2、在PreTranslateMessage中截获WM_MOUSEMOVE,添加一个监视,如果鼠标离开则产生WM_MOUSELEAVE事件,然后处理之。传送门
PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
// m_ToolTip.RelayEvent(pMsg);
switch( pMsg->message ){
case WM_MOUSEMOVE: //为了让系统产生上面的WM_MOUSELEAVE消息,你必需做如下处理
TRACKMOUSEEVENT trmouse;
trmouse.cbSize = sizeof(TRACKMOUSEEVENT);
trmouse.dwFlags = TME_LEAVE;
trmouse.dwHoverTime = 400;
trmouse.hwndTrack = pMsg->hwnd;
if(!_TrackMouseEvent(&trmouse))
return FALSE;
break;
}
return CLinkLabel::PreTranslateMessage(pMsg);
}
我选择了第一种,简单直接。第二种可以借鉴。