[英]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.