为什么使用EVENT_OBJECT_LOCATIONCHANGE的SetWinEventHook会在鼠标移动时触发?

6
我在一个进程上创建了一个钩子,用于注册其窗口移动的事件。 我使用了事件常量EVENT_OBJECT_LOCATIONCHANGE,详情请参见MSDN

对象已更改位置、形状或大小。系统会为以下用户界面元素发送此事件:插入符号和窗口对象。服务器应用程序会为其可访问对象发送此事件。

它确实起作用,但也会在简单的鼠标悬停应用程序时触发。有人能解释一下为什么吗?
这是一个可以重现它的示例:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    static class NativeMethods
    {
        [DllImport("user32.dll")]
        public static extern System.IntPtr SetWinEventHook(uint eventMin, uint eventMax, System.IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);

        public delegate void WinEventDelegate(System.IntPtr hWinEventHook, uint eventType, System.IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
    }

    public partial class Form1 : Form
    {
        private const uint WINEVENT_OUTOFCONTEXT = 0x0000;
        private const uint EVENT_OBJECT_LOCATIONCHANGE = 0x800B;

        public Form1()
        {
            InitializeComponent();
            int processId = Process.GetCurrentProcess().Id;

            NativeMethods.SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, System.IntPtr.Zero, WinEventProc, (uint)processId, (uint)0, WINEVENT_OUTOFCONTEXT);
        }

        private void WinEventProc(System.IntPtr hWinEventHook, uint eventType, System.IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
           if (hwnd == IntPtr.Zero)
            {
                Debug.WriteLine("Mouse moved");
            }
            else
            {
                Debug.WriteLine("Location changed");
            }
        }
    }
}

1
怀疑这与Winforms生成MouseEnter/Leave事件有关。或者它自动实现了一个辅助功能服务器。很难缩小范围,这不能轻易关闭。只需忽略回调,您想通过idObject == OBJID_CURSOR进行过滤。 - Hans Passant
我可以确认,我也看到了鼠标光标移动时的回调 - 不仅适用于Winforms应用程序。 - 500 - Internal Server Error
1个回答

3

头文件WinUser.h中对于EVENT_OBJECT_LOCATIONCHANGE有如下解释:

 * Note also that USER will generate LOCATIONCHANGE notifications for two
 * non-window sys objects:
 *      (1) System caret
 *      (2) Cursor

这就解释了光标移动时为什么会触发该事件。
正如汉斯在评论中所说,只需通过OBJID_CURSOR过滤对象ID即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接