[英]Global low-level mouse hook doesn't get called when UWP desktop app is out of focus
我正在创建一个桌面 UWP 应用程序,我需要设置一个全局低级鼠标钩子来检测和更改它移动到屏幕的某些位置时的位置。
当我的应用程序窗口处于焦点并且值被正确记录到输出窗口时它工作正常(意味着钩子工作正常)。
此 UWP 应用不会在商店中出现,只会在 Windows 10 桌面 (1903+) 上使用。
我试过在不同的线程上调用SetWindowsHookEx
(它没有做任何事情)。 在调用SetWindowsHookEx
时也尝试传递线程 ID 无济于事。 还尝试使用以下受限功能来防止应用程序在未聚焦时挂起: extendedExecutionUnconstrained
和extendedBackgroundTaskTime
以及此处显示的PreventFromSuspending
方法。 我尝试的另一件事是在应用程序清单uiAccess
设置为 true,这也不起作用。
即使应用程序不在前台,全局钩子也应该可以工作,但它只在具有活动窗口焦点时工作。
#region Structures
[StructLayout(LayoutKind.Sequential)]
/* MSLLHOOKSTRUCT */
public struct NativeMouseLowLevelHook
{
public override string ToString()
{
return $"{nameof(Point)}: {Point}, {nameof(MouseData)}: {MouseData}, {nameof(Flags)}: {Flags}";
}
public NativePoint Point;
public int MouseData;
public int Flags;
public int Time;
public UIntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
public class NativePoint
{
public override string ToString()
{
return $"{nameof(X)}: {X}, {nameof(Y)}: {Y}";
}
public int X;
public int Y;
}
#endregion
#region Hook
public class ManagedMouseHook : SafeHandleZeroOrMinusOneIsInvalid
{
public static List<ManagedMouseHook> KnownHooks { get; set; } = new List<ManagedMouseHook>();
public HookProc HookImpl { get; set; }
public ManagedMouseHook() : base(true)
{
Hook();
}
private void Hook()
{
HookImpl = NativeHookCallback;
KnownHooks.Add(this);
using (var curProcess = Process.GetCurrentProcess())
using (var curModule = curProcess.MainModule)
{
DoHook(curModule);
}
}
private void DoHook(ProcessModule curModule)
{
SetHandle(SetWindowsHookEx(14 /*WH_MOUSE_LL*/, HookImpl, GetModuleHandle(curModule.ModuleName), 0));
}
private bool UnHook()
{
var result = UnhookWindowsHookEx(DangerousGetHandle());
KnownHooks.Remove(this);
HookImpl = null;
return result;
}
/* LowLevelMouseProc */
private IntPtr NativeHookCallback(int code, IntPtr wparam, IntPtr lparam)
{
if (code >= 0)
{
var info = (NativeMouseLowLevelHook) Marshal.PtrToStructure(lparam,
typeof(NativeMouseLowLevelHook));
Debug.WriteLine(info); //Output example: Point: X: 408, Y: 535, MouseData: 0, Flags: 0
return new IntPtr(-1);
}
return CallNextHookEx(IntPtr.Zero, code, wparam, lparam);
}
protected override bool ReleaseHandle()
{
return UnHook();
}
}
#endregion
#region Interop
public delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int hookType, HookProc lpfn, IntPtr hMod, ulong dwThreadId);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam,
IntPtr lParam);
#endregion
然后,开始使用它:
public ManagedMouseHook MouseHook { get; set; }
MouseHook/*property*/ = new ManagedMouseHook();
并解开:
MouseHook/*property*/.Close();
UWP 应用程序在沙箱中运行,所以这听起来并不奇怪。 如果您认为如果应用程序可以接收这样的输入并且“安全”被列为 UWP 的第一特征,那么这是一个安全问题,这种行为是正常的。
我在评论的帮助下决定,最好的方法是使用我的 UWP 应用程序作为前端,并使用 win32 应用程序来实现挂钩功能本身。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.