2010-02-17 126 views
3

在我的Win32应用程序中,当我按住鼠标左键并快速移动鼠标指针时,我没有收到WM_MOUSELEAVE消息。但是,如果我按住鼠标左键,从窗口内部开始并缓慢移动到窗口边缘,它将生成一个WM_MOUSELEAVE。当鼠标左键被按住时WM_MOUSELEAVE没有被生成

如果我没有按住鼠标左键,每次无论鼠标指针离开窗口有多快,我都会收到WM_MOUSELEAVE消息。

有什么区别?我能做些什么来正确处理这两种情况?

编辑:如果我离开单击并按住,移出窗口,然后释放鼠标左键我得到WM_MOUSELEAVE消息。但是太晚了。

+2

你在什么时候调用TrackMouseEvent?可能是因为你有延迟,并且你正在设法在'TrackMouseEvent'被调用之前离开窗口? – 2010-02-17 18:46:04

+0

当客户端区域内有鼠标移动时,我会执行TrackMouseEvent。 – djcouchycouch 2010-02-17 19:37:39

回答

4

WM_MOUSELEAVE是这样,你可以检测到鼠标离开你的窗口,当你有捕获。当你被捕获时,你有责任检测你自己(如果你在乎)。

因此,SetCaptureTrackMouseEvent在同一时间没有任何意义,你可以使用一个或另一个。

现在,如果在捕获时看到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); 
-1

由于等待WM_MOUSELEAVE是不可靠的,我发现的最佳解决方案是在WM_MOUSEMOVE期间直接查看鼠标位置。我将鼠标位置与客户区域进行比较,如果位置在外面,则我将其作为鼠标离开。

当鼠标位于客户区和ReleaseCapture离开时,我也确保调用SetCapture。

+0

请记住,仅当用户在窗口内按下鼠标按钮时,SetCapture *才起作用。你是否试图一起使用SetCapture和TrackMouseEvent?这可以解释你所看到的...... – Shog9 2010-02-17 20:50:12

+0

这不是一个答案!这是一个黑客。答案是最多的一个。 – CodeAngry 2014-02-13 10:16:47

5

在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消息,并且代码仍然可以工作......所以这种解决方法在两种情况下都能正常工作。

你的问题听起来像它可能与我的相同,所以希望这可以帮助你。

相关问题