我正在研究一个名为UAWKS(非官方Apple无线键盘支持)的项目,该项目可帮助Windows用户使用Apple的蓝牙键盘。 UAWKS的主要目标之一是使用 Ctrl 交换 Cmd 键(在Windows中表现为 Winkey ),允许用户执行<用于复制的kbd> Cmd + C ,用于新选项卡的 Cmd + T 等
目前使用AutoHotkey开发,在Windows XP下运行良好。但是,在Vista和Windows 7上, Cmd + L 会导致问题:
似乎 Win + L 是一个特殊的和弦,让其他一切混乱。
我查看了AHK源代码,他们尝试在keyboard_mouse.cpp中的SendKey()
中解决此问题(在v1.0.48.05中的第883行附近),但它不起作用。我在C#中编写了自己的低级键盘钩子应用程序,我也看到了同样的问题。
有没有其他人遇到这个?有解决方法吗?
答案 0 :(得分:2)
我想出了一种在C#中实现这一目标的方法。可能的 Win + L 按键序列涉及四种状态(无, Win , Win + L , L )。每当达到 Win + L 状态时,设置一个标志(下面的“winLSet”)。每当所有的钥匙都被释放后,我们会检查这个标志并模拟按下它是否已经设定。
最后一个难题是在 Ctrl - L (无KeyDown)之前模拟WinKey的KeyUp。我在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');
}
}
}
对于后代:请注意,此代码使用InputSimulator和LowLevelKeyboardHook,它们不是来自.NET Framework。 LowLevelKeyboardHook是我之前写的一个类,它将全局KeyDown和KeyUp事件公开为C#事件。有类似的示例here,here,可以找到一堆here。
还要注意我使用的是System.Windows.Input.Key,而不是System.Windows.Forms.Keys,这可能会让一些人感到困惑。 System.Windows.Input.Key是.NET 3.0及更高版本中新的密钥枚举,而System.Windows.Forms.Keys是Windows Forms中的旧枚举。
答案 1 :(得分:0)
如果您能够检测到键 Cmd + L ,您可以直接锁定工作站而无需转发 Winkey + →?您可以使用API LockWorkstation
(或rundll32.exe user32.dll,LockWorkStation
)
答案 2 :(得分:0)
我尝试使用Windows Input Simulator库中断Windows密钥。这是我的回调:
private static unsafe IntPtr HookCallback( int nCode, IntPtr wParam, IntPtr lParam )
{
if( nCode >= 0 && ( wParam == (IntPtr)WM_KEYDOWN ) )
{
var replacementKey = (KBDLLHOOKSTRUCT*)lParam;
if( replacementKey->vkCode == (int)VirtualKeyCode.LWIN )
{
InputSimulator.SimulateKeyDown( VirtualKeyCode.SHIFT );
return (IntPtr)1;
}
}
return CallNextHookEx( m_HookID, nCode, wParam, lParam );
}
使用此挂钩,我的左侧Windows键在Win XP下充当shift键(已实现和预期)
按 WinKey + l 仅返回L
。
编辑:但是,我可以确认您的观察,此代码在Windows 7下无效:/抱歉,我无法再帮助您。