我正在尝试为 WPF 组件编写单元测试。如何模拟组合键(不仅仅是 1 个键)?
模拟按 1 个键很简单:
var window = new Window();
var keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, Substitute.For<PresentationSource>(), 0, Key.E)
{
RoutedEvent = Keyboard.KeyDownEvent,
};
window.RaiseEvent(keyEventArgs);
查明是否使用了特定的组合键(例如 Ctrl+Alt+Shift+E):
if(EventArgs.KeyboardDevice.Modifiers.HasFlag(ModifierKeys.Alt | ModifierKeys.Control | ModifierKeys.Shift)
&& EventArgs.Key == Key.E)
我们看到:可以通过 EventArgs.KeyboardDevice 访问修饰符。
但是我们如何设置它们呢?
我做了很多尝试。我尝试模拟 KeyEventArgs 构造函数的第一个参数,但没有成功。
如何模拟组合键?
SetKeyboardState
为当前线程设置修饰键。这当然只适用于 Windows。
我创建了一个简单的方法,可以根据
ModifierKeys
设置键盘状态。它返回一个 IDisposable
,它将返回 Dispose
中未设置的状态
public static class Keyboard
{
public static IDisposable SetModifierKeys(ModifierKeys keys)
{
var keyState = new byte[256];
keyState[(int)Win32.VirtualKeyStates.LeftShift] = (byte)(keys.HasFlag(ModifierKeys.Shift) ? 0x80 : 0);
keyState[(int)Win32.VirtualKeyStates.LeftControl] = (byte)(keys.HasFlag(ModifierKeys.Control) ? 0x80 : 0);
keyState[(int)Win32.VirtualKeyStates.LeftAlt] = (byte)(keys.HasFlag(ModifierKeys.Alt) ? 0x80 : 0);
keyState[(int)Win32.VirtualKeyStates.LeftWin] = (byte)(keys.HasFlag(ModifierKeys.Windows) ? 0x80 : 0);
SetKeyboardState(keyState);
return new Disposable();
}
private static void SetKeyboardState(byte[] keyState)
{
if (!Win32.SetKeyboardState(keyState))
{
var error = Marshal.GetLastWin32Error();
throw new Win32Exception(error);
}
}
private static class Win32
{
public enum VirtualKeyStates
{
Shift = 0x10,
Control = 0x11,
Alt = 0x12,
LeftWin = 0x5B,
LeftControl = 0xA2,
LeftShift = 0xA0,
LeftAlt = 0xA4,
}
[DllImport("user32.dll")]
public static extern bool SetKeyboardState(byte[] lpKeyState);
}
private sealed class Disposable : IDisposable
{
public void Dispose()
{
var keyState = new byte[256];
SetKeyboardState(keyState);
}
}
}