鼠标挂钩断开
Mouse hook getting disconnected
我正在尝试实现一个颜色选择器,它从屏幕上各处的像素中获取颜色。
为此,我计划使用全局鼠标挂钩来监听 WM_MOUSEMOVE,以便在鼠标四处移动时更新颜色,并监听鼠标点击以确认(WM_LBUTTONDOWN)或取消( WM_RBUTTONDOWN) 操作。
我遵循了众多教程中的一个,并想出了这个(在控制台应用程序中,只是为了测试该过程是否有效):
static IntPtr hook;
static bool click;
static NativeMethods.LowLevelHookStruct llhs;
static void Main(string[] args)
{
hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, MouseHookCallback, (IntPtr)null, 0);
if (hook != IntPtr.Zero)
{
Console.WriteLine("Hook Set");
while (!Console.KeyAvailable) {
Console.WriteLine("{0} {1} {2}", hook, llhs.pt.x, llhs.pt.y);
if(click) Console.WriteLine("click!");
click = false;
System.Threading.Thread.Sleep(250);
}
}
}
和
public static IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
NativeMethods.LowLevelHookStruct hookStruct = (NativeMethods.LowLevelHookStruct)Marshal.PtrToStructure(lParam, typeof(NativeMethods.LowLevelHookStruct));
if (NativeMethods.MouseMessages.WM_MOUSEMOVE == (NativeMethods.MouseMessages)wParam)
{
llhs = hookStruct;
}
if (NativeMethods.MouseMessages.WM_LBUTTONDOWN == (NativeMethods.MouseMessages)wParam)
{
click = true;
}
else if (NativeMethods.MouseMessages.WM_RBUTTONDOWN == (NativeMethods.MouseMessages)wParam)
{
}
}
return NativeMethods.CallNextHookEx(hook, nCode, wParam, lParam);
}
NativeMethods 只是一个 class 我保留所有 DllImport 相关内容的地方。
一旦我 运行 控制台应用程序,鼠标光标就会卡住几秒钟,并且在控制台中我得到这个 - 即使光标 是 卡住了
Hook Set
3945554872 0 0
3945554872 0 0
3945554872 0 0
3945554872 0 0
...
在调试中,似乎我的钩子从未被调用过,一次也没有。
知道哪里出了问题吗?
根据@Hans Passant 的评论,我将测试代码移至 WinForms 应用程序,回调开始出现。
然后发现回调正在被垃圾收集只是一个问题,所以我所要做的就是改变
hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, MouseHookCallback, (IntPtr)null, 0);
至
private NativeMethods.LowLevelHookProc _hookCallback;
...
_hookCallback = new NativeMethods.LowLevelHookProc(MouseHookCallback);
hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, _hookCallback, (IntPtr)null, 0);
为了保留对回调的引用,这样它就不会被 GC。
我正在尝试实现一个颜色选择器,它从屏幕上各处的像素中获取颜色。 为此,我计划使用全局鼠标挂钩来监听 WM_MOUSEMOVE,以便在鼠标四处移动时更新颜色,并监听鼠标点击以确认(WM_LBUTTONDOWN)或取消( WM_RBUTTONDOWN) 操作。
我遵循了众多教程中的一个,并想出了这个(在控制台应用程序中,只是为了测试该过程是否有效):
static IntPtr hook;
static bool click;
static NativeMethods.LowLevelHookStruct llhs;
static void Main(string[] args)
{
hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, MouseHookCallback, (IntPtr)null, 0);
if (hook != IntPtr.Zero)
{
Console.WriteLine("Hook Set");
while (!Console.KeyAvailable) {
Console.WriteLine("{0} {1} {2}", hook, llhs.pt.x, llhs.pt.y);
if(click) Console.WriteLine("click!");
click = false;
System.Threading.Thread.Sleep(250);
}
}
}
和
public static IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
NativeMethods.LowLevelHookStruct hookStruct = (NativeMethods.LowLevelHookStruct)Marshal.PtrToStructure(lParam, typeof(NativeMethods.LowLevelHookStruct));
if (NativeMethods.MouseMessages.WM_MOUSEMOVE == (NativeMethods.MouseMessages)wParam)
{
llhs = hookStruct;
}
if (NativeMethods.MouseMessages.WM_LBUTTONDOWN == (NativeMethods.MouseMessages)wParam)
{
click = true;
}
else if (NativeMethods.MouseMessages.WM_RBUTTONDOWN == (NativeMethods.MouseMessages)wParam)
{
}
}
return NativeMethods.CallNextHookEx(hook, nCode, wParam, lParam);
}
NativeMethods 只是一个 class 我保留所有 DllImport 相关内容的地方。
一旦我 运行 控制台应用程序,鼠标光标就会卡住几秒钟,并且在控制台中我得到这个 - 即使光标 是 卡住了
Hook Set
3945554872 0 0
3945554872 0 0
3945554872 0 0
3945554872 0 0
...
在调试中,似乎我的钩子从未被调用过,一次也没有。 知道哪里出了问题吗?
根据@Hans Passant 的评论,我将测试代码移至 WinForms 应用程序,回调开始出现。
然后发现回调正在被垃圾收集只是一个问题,所以我所要做的就是改变
hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, MouseHookCallback, (IntPtr)null, 0);
至
private NativeMethods.LowLevelHookProc _hookCallback;
...
_hookCallback = new NativeMethods.LowLevelHookProc(MouseHookCallback);
hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, _hookCallback, (IntPtr)null, 0);
为了保留对回调的引用,这样它就不会被 GC。