当鼠标左键被按住时WM_MOUSELEAVE没有被生成
在我的Win32应用程序中,当我按住鼠标左键并快速移动鼠标指针时,我没有收到WM_MOUSELEAVE消息。但是,如果我按住鼠标左键,从窗口内部开始并缓慢移动到窗口边缘,它将生成一个WM_MOUSELEAVE。当鼠标左键被按住时WM_MOUSELEAVE没有被生成
如果我没有按住鼠标左键,每次无论鼠标指针离开窗口有多快,我都会收到WM_MOUSELEAVE消息。
有什么区别?我能做些什么来正确处理这两种情况?
编辑:如果我离开单击并按住,移出窗口,然后释放鼠标左键我得到WM_MOUSELEAVE消息。但是太晚了。
WM_MOUSELEAVE是这样,你可以检测到鼠标离开你的窗口,当你不有捕获。当你被捕获时,你有责任检测你自己(如果你在乎)。
因此,SetCapture
和TrackMouseEvent
在同一时间没有任何意义,你可以使用一个或另一个。
现在,如果在捕获时看到WM_MOUSELEAVE消息会更方便,在消息泵中执行该操作相对简单。
您只需在消息泵中的GetMessage()
和DispatchMessage()
调用之间添加类似这样的代码即可。
GetMessage(pmsg, ...);
.....
if ((IS_WITHIN(pmsg->message, WM_MOUSEFIRST, WM_MOUSELAST) ||
IS_WITHIN(pmsg->message, WM_NCMOUSEMOVE, WM_NCMBUTTONDBLCLK)) &&
MyMouseLeaveDetection(pmsg, g_hwndNotifyMouseLeave))
{
MSG msg = *pmsg;
msg.message = WM_MOUSELEAVE;
msg.hwnd = g_hwndNotifyMouseLeave; // window that want's
msg.lParam = 0xFFFFFFFF;
g_hwndNotifyMouseLeave = NULL;
DispatchMessage (&msg);
}
.....
TranslateMessage(pmsg);
DispatchMessage(pmsg);
由于等待WM_MOUSELEAVE是不可靠的,我发现的最佳解决方案是在WM_MOUSEMOVE期间直接查看鼠标位置。我将鼠标位置与客户区域进行比较,如果位置在外面,则我将其作为鼠标离开。
当鼠标位于客户区和ReleaseCapture离开时,我也确保调用SetCapture。
在Windows 7上,我试图制作一个自绘按钮。为了更准确地获得更多的mouseenter/mouseleave事件,我将这个按钮分类了下来。当我这样做的时候,当我得到一个WM_MOUSEMOVE时,我使用了TrackMouseEvent,因为只有当鼠标移动到按钮上时才会发布。如果尚未设置,我会设置一个布尔值来指定鼠标悬停在按钮上,并调用TrackMouseEvent,以便只要鼠标离开,我就可以取消设置布尔值。但是,像你一样,当我按住鼠标左键并按住所有者绘制的按钮,然后将鼠标拖出时,我没有收到WM_MOUSELEAVE。在按钮外释放鼠标后,我突然收到WM_MOUSELEAVE消息 - 太迟了。
我确定此行为的原因是默认按钮proc的WM_LBUTTONDOWN处理调用SetCapture,并在稍后发布。 SetCapture的用法是打破我们对WM_MOUSELEAVE事件的接受。但是,作为调用SetCapture的副作用,即使控件不在鼠标下面,我们也会获取WM_MOUSEMOVE事件。因此,我的解决方法是复制WM_MOUSEMOVE处理程序中WM_MOUSELEAVE的逻辑,以取消设置指示鼠标位于按钮上方的布尔值,如果我得到的按钮区域外的mousemove事件。如果在WM_LBUTTONDOWN内部没有实际使用SetCapture作为默认按钮过程,那么我们已经得到了我们的WM_MOUSELEAVE消息,并且代码仍然可以工作......所以这种解决方法在两种情况下都能正常工作。
你的问题听起来像它可能与我的相同,所以希望这可以帮助你。
你在什么时候调用TrackMouseEvent?可能是因为你有延迟,并且你正在设法在'TrackMouseEvent'被调用之前离开窗口? – 2010-02-17 18:46:04
当客户端区域内有鼠标移动时,我会执行TrackMouseEvent。 – djcouchycouch 2010-02-17 19:37:39