我的代碼與運行在Windows托盤應用程序中的this question非常相似,即使從問題中得到的確切代碼我也會得到相同的行爲。它在經典的Windows應用程序上運行良好,例如Firefox,Chrome,Windows資源管理器等。但是,當鼠標焦點到達UWP應用程序(例如Edge或Calendar或Mail)時,滾動會變得緊張,在執行幾十個滾動後,我的應用程序掛起甚至不能從任務管理器(權限被拒絕)終止,這種行爲是非常可重複的。在Windows10 UWP應用程序上使用SendInput發送滾動命令
我會從這裏的問題粘貼代碼:
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace EnableMacScrolling
{
class InterceptMouse
{
const int INPUT_MOUSE = 0;
const int MOUSEEVENTF_WHEEL = 0x0800;
const int WH_MOUSE_LL = 14;
private static LowLevelMouseProc _proc = HookCallback;
private static IntPtr _hookID = IntPtr.Zero;
public static void Main()
{
_hookID = SetHook(_proc);
if (_hookID == null)
{
MessageBox.Show("SetWindowsHookEx Failed");
return;
}
Application.Run();
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelMouseProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc,
GetModuleHandle(curModule.ModuleName), 0);
}
}
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && MouseMessages.WM_MOUSEWHEEL == (MouseMessages)wParam)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
Console.WriteLine(hookStruct.mouseData);
if (hookStruct.flags != -1) //prevents recursive call to self
{
INPUT input;
input = new INPUT();
input.type = INPUT_MOUSE;
input.mi.dx = 0;
input.mi.dy = 0;
input.mi.dwFlags = MOUSEEVENTF_WHEEL;
input.mi.time = 0;
input.mi.dwExtraInfo = 0;
input.mi.mouseData = -(hookStruct.mouseData >> 16);
try
{
SendInput(1, ref input, Marshal.SizeOf(input));
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
}
return (IntPtr)1;
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private enum MouseMessages
{
WM_MOUSEWHEEL = 0x020A
}
[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public int mouseData;
public int flags;
public int time;
public IntPtr dwExtraInfo;
}
public struct INPUT
{
public int type;
public MOUSEINPUT mi;
}
[StructLayout(LayoutKind.Sequential)]
public struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public uint dwFlags;
public int time;
public int dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("User32.dll", SetLastError = true)]
public static extern int SendInput(int nInputs, ref INPUT pInputs, int cbSize);
} }
難道我處理在此窗口中的錯誤?任何指向我如何可以找出發生了什麼?
更新:
我已用C創建了一個測試Win32應用程序++更容易地再現/演示此問題。這個問題與SendCommand一樣,當任何經典應用程序在焦點中執行時,都可以正常工作。但是,當UWP應用程序處於焦點狀態時執行時,或者甚至Windows啓動/開始菜單導致調用應用程序(我的應用程序)掛起並一直卡住,直到重新啓動窗口。
此問題的有效解決方法是在處理鉤子回調的線程的另一個線程上執行SendCommand調用。立即啓動執行SendCommand並從鉤子回調中返回的線程會產生所需的行爲並且不會導致任何問題。
@hatchet我意識到這一點。我的應用程序不是UWP,它是一款經典的桌面應用程序。 – Vasil
這可能是與SetWindowsHookEx的32/64位問題有關的問題。您可以通過創建第二個線程並在該線程的上下文中運行SetWindowsHookEx來避開它。請參閱32/64和消息泵的討論:https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85)。aspx – hatchet
你的C++示例應用程序在哪裏? –