《如何在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); }我选择了第一种,简单直接。第二种可以借鉴。