在我的应用程序中,我正在捕获击键,当击键不是条形码的一部分时,我想将它们发送到应用程序。击键需要发送到应用程序本身。
我尝试了不同的方法但没有成功。
internal class InputSimulator
{
#pragma warning disable SA1305 // Field names should not use Hungarian notation
#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
#pragma warning disable SA1400 // Access modifier should be declared
[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
[DllImport("user32.dll")]
internal static extern uint MapVirtualKey(uint uCode, uint uMapType);
struct INPUT
{
public INPUTType type;
public INPUTUnion Event;
}
[StructLayout(LayoutKind.Explicit)]
struct INPUTUnion
{
[FieldOffset(0)]
internal MOUSEINPUT mi;
[FieldOffset(0)]
internal KEYBDINPUT ki;
[FieldOffset(0)]
internal HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct MOUSEINPUT
{
public int dx;
public int dy;
public int mouseData;
public int dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public KEYEVENTF dwFlags;
public int time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
enum INPUTType : uint
{
INPUT_KEYBOARD = 1
}
[Flags]
enum KEYEVENTF : uint
{
EXTENDEDKEY = 0x0001,
KEYUP = 0x0002,
SCANCODE = 0x0008,
UNICODE = 0x0004
}
public static void ProcessKeys(Key[] keys)
{
INPUT[] inputs = new INPUT[keys.Length + 1];
for (int i = 0; i < keys.Length; i++)
{
var virtualKey = KeyInterop.VirtualKeyFromKey(keys[i]);
uint skey = MapVirtualKey((uint)virtualKey, 0x0);
inputs[i].type = INPUTType.INPUT_KEYBOARD;
inputs[i].Event.ki.dwFlags = KEYEVENTF.SCANCODE;
inputs[i].Event.ki.wScan = (ushort)skey;
}
inputs[keys.Length].type = INPUTType.INPUT_KEYBOARD;
inputs[keys.Length].Event.ki.dwFlags = KEYEVENTF.UNICODE;
inputs[keys.Length].Event.ki.dwFlags |= KEYEVENTF.KEYUP;
uint cSuccess = SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
}
public static void Send(Key key)
{
if (Keyboard.PrimaryDevice != null)
{
if (Keyboard.PrimaryDevice.ActiveSource != null)
{
var e = new KeyEventArgs(Keyboard.PrimaryDevice, Keyboard.PrimaryDevice.ActiveSource, 0, key)
{
RoutedEvent = Keyboard.PreviewKeyDownEvent
};
InputManager.Current.ProcessInput(e);
}
}
}
#pragma warning restore SA1305 // Field names should not use Hungarian
notation
#pragma warning restore SA1307 // Accessible fields should begin with
upper-case letter
#pragma warning restore SA1400 // Access modifier should be declared
}
下面的代码中有两种方法
ProcessKeys
和Send
,但它们不起作用。我究竟做错了什么?还有其他方法可以实现这一目标吗?目前我使用 System.Windows.Forms.SendKeys.SendWait
但我更喜欢一种不引用 System.Windows.Forms
的方法
编辑:我的问题已被标记为可能重复:WPF应用程序中的SendKeys.Send方法我尝试了两种解决方案,但它们都不起作用,也许我的SendInput实现中有问题,但我无法找出问题所在
以下内容对我有用。确保您的应用程序具有焦点。
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Input;
// https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-mapvirtualkeyw
// https://www.codeproject.com/Articles/5264831/How-to-Send-Inputs-using-Csharp
namespace Demo;
public static class WindowsEventSender // only for Windows 7+
{
public static void SendChar(char c)
{
var input = new Input(InputType.Keyboard);
input.Union.Keyboard.ScanCode = c;
input.Union.Keyboard.Flags = KeyboardInputFlags.Unicode;
input.Union.Keyboard.ExtraInfo = GetMessageExtraInfo();
var inputs = new[] { input };
var sent = SendInput((uint)inputs.Length, inputs, Marshal.SizeOf<Input>());
if (sent == inputs.Length)
return;
ThrowWin32Exception(nameof(SendInput));
}
public static void SendKey(Key key, params Key[] modifiers)
{
// create input array
var inputs = new Input[2 * (modifiers.Length + 1)];
var idx = 0;
// add key modifiers down
foreach (var modifier in modifiers)
{
inputs[idx++] = GetKeyInput(modifier, true);
}
// add key down
inputs[idx++] = GetKeyInput(key, true);
// add key up
inputs[idx++] = GetUpKeyInput(inputs[modifiers.Length]);
// add key modifiers up
for (var index = 0; index < modifiers.Length; ++index)
{
inputs[idx++] = GetUpKeyInput(inputs[index]);
}
// send keys
var sent = SendInput((uint)inputs.Length, inputs, Marshal.SizeOf<Input>());
if (sent == inputs.Length)
return;
ThrowWin32Exception(nameof(SendInput));
}
static Input GetKeyInput(Key key, bool pressed)
{
const int MAPVK_VK_TO_VSC_EX = 4;
// calculate key values
var virtualKey = KeyInterop.VirtualKeyFromKey(key);
var scanCode = MapVirtualKey((uint)virtualKey, MAPVK_VK_TO_VSC_EX);
var scanCodeFlag = scanCode > 0 ? KeyboardInputFlags.ScanCode : 0;
var extendedKeyFlag = (scanCode & 0xE000) == 0xE000 ? KeyboardInputFlags.ExtendedKey : 0;
var keyFlags = extendedKeyFlag | scanCodeFlag;
// add key
var input = new Input(InputType.Keyboard);
input.Union.Keyboard.VirtualKey = (ushort)virtualKey;
input.Union.Keyboard.ScanCode = (ushort)scanCode;
input.Union.Keyboard.Flags = (pressed ? KeyboardInputFlags.KeyDown : KeyboardInputFlags.KeyUp) | keyFlags;
return input;
}
static Input GetUpKeyInput(Input downKeyInput)
{
var input = new Input(InputType.Keyboard);
input.Union.Keyboard.VirtualKey = downKeyInput.Union.Keyboard.VirtualKey;
input.Union.Keyboard.ScanCode = downKeyInput.Union.Keyboard.ScanCode;
input.Union.Keyboard.Flags = downKeyInput.Union.Keyboard.Flags | KeyboardInputFlags.KeyUp;
return input;
}
static void ThrowWin32Exception(string functionId)
{
var errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode, $"{functionId} error code {errorCode}: {new Win32Exception(errorCode).Message}");
}
[StructLayout(LayoutKind.Sequential)]
struct Input(InputType type)
{
public InputType InputType = type;
public InputUnion Union = new();
}
enum InputType : uint { Mouse = 0, Keyboard = 1, Hardware = 2 }
[StructLayout(LayoutKind.Explicit)]
struct InputUnion
{
[FieldOffset(0)] public MouseInput Mouse;
[FieldOffset(0)] public KeyboardInput Keyboard;
[FieldOffset(0)] public HardwareInput Hardware;
}
[StructLayout(LayoutKind.Sequential)]
struct MouseInput
{
public int DeltaX;
public int DeltaY;
public uint MouseData;
public MouseEventFlags Flags;
public uint Time;
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct KeyboardInput
{
public ushort VirtualKey;
public ushort ScanCode;
public KeyboardInputFlags Flags;
public uint Time;
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HardwareInput
{
public int uMsg;
public short wParamL;
public short wParamH;
}
[Flags]
enum MouseEventFlags : uint
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040,
XDown = 0x0080,
XUp = 0x0100,
Wheel = 0x0800,
VirtualDesk = 0x4000,
Absolute = 0x8000
}
[Flags]
enum KeyboardInputFlags : uint
{
KeyDown = 0x0000,
ExtendedKey = 0x0001,
KeyUp = 0x0002,
Unicode = 0x0004,
ScanCode = 0x0008
}
[DllImport("user32.dll")]
static extern IntPtr GetMessageExtraInfo();
[DllImport("user32.dll")]
static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint cInputs, [In, MarshalAs(UnmanagedType.LPArray)] Input[] pInputs, int cbSize);
}