问题
在面向Windows事件模型进行编程的时候,我们知道有一个WM_MOUSELEAVE消息表明鼠标离开某个窗口的事件发生了。但是,为什么没有对应的WM_MOUSEENTER消息呢?
问题答案
因为你自己就可以弄明白整个鼠标事件的过程,从而间接的得到WM_MOUSEENTER消息。
详解
当你收到WM_MOUSELEAVE消息的时候,可以设置一个标志位,表明:此时鼠标已经处于窗口之外了。当你收到WM_MOUSEMOVE消息的时候,如果你发现这个标志位已经被设置了,说明鼠标已经移入到窗口的范围了(此时你需要清除这个标志位以对应这个状态)。
让我们以下面的例子代码来解释我们上面所说的。
代码解析
上面代码执行起来的效果是:当鼠标位于窗口客户区的时候,电脑的蜂鸣器将会发出一次声音。我们定义了一个标志g_fMouseInClient,用来表明当前鼠标是否位于窗口客户区。
当我们收到WM_MOUSELEAVE消息时,Windows告知你鼠标已经离开了窗口区域,这个时候我们就将这个标志位设置为FALSE。
当鼠标在窗口上移动的时候,我们会判断这个标志位,如果标志位为FALSE,表明这是鼠标第一次在窗口上移动,也即:鼠标第一次进入窗口区域,这样我们就相当于收到了WM_MOUSEENTER消息。
接下里的处理代码里,我们将标志位设置为TRUE,并发出蜂鸣器声音。需要注意的是,我们还调用了TrackMouseEvent来触发WM_MOUSELEAVE消息。为什么是触发WM_MOUSELEAVE消息,因为我们在tme.dwFlags的标志中显式指明了这一点。
练习题
如果程序开始运行的时候,鼠标就已经在窗口客户区了,此时鼠标没有做任何移动,为什么你还是会听到蜂鸣器的声音呢?
问题答案揭晓
因为Windows在窗口创建的时候会发送虚拟的WM_MOUSEMOVE消息,此时我们的WM_MOUSEMOVE消息处理例程就可以得到执行,所以你会听到蜂鸣器的声音。
这实际上是一个很好的设计,因为在这种情况下,我们就有机会在窗口创建时处理一些与鼠标有关的初始化工作。