У меня есть код, очень похожий на this question, работающий в приложении лотка Windows, даже с этим точным кодом из вопроса я получаю такое же поведение. Все это хорошо работает в классических приложениях Windows, таких как Firefox, Chrome, Windows Explorer и т. Д. Однако, когда фокус мыши попадает в приложение UWP, такое как Edge или Calendar или Mail, свиток становится неустойчивым и после нескольких десятков свитков выполняется мое приложение зависает и даже не может быть прекращено из диспетчера задач (разрешение отклонено), это поведение очень воспроизводимо.Отправка команд прокрутки с помощью SendInput в приложениях UWP Windows10
Я вставить код из вопроса здесь:
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);
} }
Возможно ли, что я имею дело с ошибкой в окнах здесь? Любые указания на то, как я могу узнать, что происходит?
Update:
Я создал тестовый Win32 приложение в C++ более легко воспроизвести/показать проблему. Проблема заключается в SendCommand, который, когда выполняется, когда какое-либо классическое приложение находится в фокусе, отлично работает. Однако при выполнении в то время, когда приложение UWP находится в фокусе, или даже меню запуска/запуска Windows заставляет вызывающее приложение (мое приложение) зависать и застревать до перезапуска окон.
Эффективное обходное решение/решение этой проблемы - выполнить вызов SendCommand в другом потоке из потока, обрабатывающего обратный вызов hook. Сразу же запуск потока, который выполняет SendCommand, и возврат из обратного вызова hook вызывает желаемое поведение и не вызывает никаких проблем.
@hatchet Я знаю об этом. Мое приложение не UWP, это классическое настольное приложение. – Vasil
Это может быть проблема, связанная с 32/64-разрядной версией SetWindowsHookEx. Вы можете обойти это, создав второй поток и запустив SetWindowsHookEx в контексте этого потока. См. Обсуждение 32/64 и насоса сообщений: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx – hatchet
Где ваше приложение на C++? –