Bri*_*sen 6 c# winapi autohotkey keyboard-hook windows-7
我正在开展一个名为UAWKS(非官方Apple无线键盘支持)的项目,帮助Windows用户使用Apple的蓝牙键盘.UAWKS的主要目标之一是交换Cmd密钥(其行为与WinkeyWindows一样)Ctrl,允许用户执行Cmd+ C复制,Cmd+ T选择新选项卡等.
它目前使用AutoHotkey开发,在Windows XP下运行良好.但是,在Vista和Windows 7上,Cmd+ L会导致问题:
似乎Win+ L是一个特殊的和弦,其他一切混乱.
我查看了AHK源代码,他们尝试SendKey()在keyboard_mouse.cpp中解决这个问题(在v1.0.48.05的第883行附近),但它不起作用.我在C#中编写了自己的低级键盘钩子应用程序,我也看到了同样的问题.
有没有其他人遇到这个?有解决方法吗?
我想出了一种用 C# 来做到这一点的方法。Win可能的+按键序列涉及四种状态L(无、Win、Win+ L、L)。每当达到Win+状态时,设置一个标志(下面的“winLSet”)。L每当所有按键被释放时,我们都会检查此标志并模拟按下(如果已设置)。
最后一个难题是在Ctrl-之前模拟 WinKey 的 KeyUp L(无 KeyDown)。我在 AutoHotkey 中尝试过类似的方法,但它从未起作用,但它似乎在这里完美工作。
代码如下。如果您打算使用此代码,请参阅底部的解释说明。
public partial class MainWindow : Window
{
LowLevelKeyboardHook hook;
bool winKeyDown;
bool lKeyDown;
bool winLSet;
public MainWindow()
{
InitializeComponent();
hook = new LowLevelKeyboardHook();
hook.KeyDown += OnKeyDown;
hook.KeyUp += OnKeyUp;
}
void OnKeyDown(object sender, LowLevelKeyEventArgs e)
{
e.EventHandled = true;
switch (e.Key)
{
case Key.L:
lKeyDown = true;
UpdateWinLState();
e.EventHandled = winKeyDown;
break;
case Key.LWin:
winKeyDown = true;
UpdateWinLState();
InputSimulator.SimulateKeyDown(VirtualKeyCode.LCONTROL);
break;
case Key.LeftCtrl:
InputSimulator.SimulateKeyDown(VirtualKeyCode.LWIN);
break;
default:
e.EventHandled = false;
break;
}
}
void OnKeyUp(object sender, LowLevelKeyEventArgs e)
{
e.EventHandled = true;
switch (e.Key)
{
case Key.L:
lKeyDown = false;
UpdateWinLState();
e.EventHandled = winKeyDown;
break;
case Key.LWin:
winKeyDown = false;
UpdateWinLState();
InputSimulator.SimulateKeyUp(VirtualKeyCode.LCONTROL);
break;
case Key.LeftCtrl:
InputSimulator.SimulateKeyUp(VirtualKeyCode.LWIN);
break;
default:
e.EventHandled = false;
break;
}
}
void UpdateWinLState()
{
if (winKeyDown && lKeyDown)
{
winLSet = true;
}
else if (!winKeyDown && !lKeyDown && winLSet)
{
winLSet = false;
InputSimulator.SimulateKeyUp(VirtualKeyCode.LWIN);
InputSimulator.SimulateModifiedKeyStroke(
VirtualKeyCode.LCONTROL,
(VirtualKeyCode)'L');
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于后代:请注意,此代码使用了InputSimulator和 LowLevelKeyboardHook,它们不是来自 .NET Framework。LowLevelKeyboardHook 是我不久前编写的一个类,它将全局 KeyDown 和 KeyUp 事件公开为 C# 事件。这里、这里都有类似的例子,这里还可以找到很多类似的例子。
另请注意,我使用的是 System.Windows.Input.Key,而不是 System.Windows.Forms.Keys,这可能会让某些人感到困惑。System.Windows.Input.Key 是 .NET 3.0 及更高版本中新的键枚举,而 System.Windows.Forms.Keys 是 Windows 窗体中的旧枚举。