我从事一个名为 UAWKS(非官方 Apple 无线键盘支持)的项目,该项目帮助 Windows 用户使用苹果的蓝牙键盘。 UAWKS 的主要目标之一是将 Cmd 键(在 Windows 中的行为类似于 Winkey)与 Ctrl 交换,允许用户执行< kbd>Cmd+C 用于复制,Cmd+T 用于新选项卡等。
目前使用 AutoHotkey,在 Windows XP 下运行得很好。但是,在 Vista 和 Windows 7 上,Cmd+L 会导致问题:
- 无论低级键盘挂钩如何,Win+L< /kbd> 始终被 Windows 拦截并通常锁定工作站...
- 您可以使用 这个注册表 hack,但是在 AHK 中按 Win+L 仍然无法反弹
- < kbd>Win+L 使 Winkey 处于 Keydown 状态,直到下一次(额外的)Winkey Up。模拟 Keyup 事件似乎也不起作用!
看起来Win+L是一个特殊的和弦,它把其他一切都搞乱了。
我查看了AHK源代码,他们尝试在keyboard_mouse.cpp(v1.0.48.05中第883行附近)的SendKey()
中解决这个问题,但它不起作用。我用 C# 编写了自己的低级键盘挂钩应用程序,并且看到了同样的问题。
还有其他人遇到过这个吗?有解决方法吗?
I work on a project called UAWKS (Unofficial Apple Wireless Keyboard Support) that helps Windows users use Apple's bluetooth keyboard. One of the main goals of UAWKS is to swap the Cmd key (which behaves as Winkey in Windows) with Ctrl, allowing users to do Cmd+C for copy, Cmd+T for new tab, etc.
It is currently developed using AutoHotkey, which worked pretty well under Windows XP. However, on Vista and Windows 7, Cmd+L causes problems:
- Regardless of low-level keyboard hooks, Win+L is always intercepted by Windows and normally locks the workstation...
- You can disable workstation locking with this registry hack, but pressing Win+L still can't be rebound in AHK
- Pressing Win+L leaves Winkey in the Keydown state until the next (additional) Winkey Up. Simulating a Keyup event doesn't seem to work either!
It seems that Win+L is a special chord that messes everything else up.
I've looked through the AHK source code, and they try to address this problem in SendKey()
in keyboard_mouse.cpp (near line 883 in v1.0.48.05), but it doesn't work. I wrote up my own low-level keyboard hook application in C#, and I see the same problem.
Has anyone else run into this? Is there a workaround?
发布评论
评论(3)
我想出了一种用 C# 来做到这一点的方法。可能的 Win+L 按键序列涉及四种状态(无、Win、Win+L,L)。每当达到 Win+L 状态时,设置一个标志(下面的“winLSet”)。每当所有按键被释放时,我们都会检查此标志并模拟按下(如果已设置)。
最后一个难题是在 Ctrl-L 之前模拟 WinKey 的 KeyUp(无 KeyDown)。我在 AutoHotkey 中尝试过类似的方法,但它从未起作用,但它似乎在这里完美工作。
代码如下。如果您打算使用此代码,请参阅底部的说明性注释。
对于后代:请注意,此代码使用 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 窗体中的旧枚举。
I figured out a way to do this in C#. There are four states involved in a possible Win+L keypress sequence (None, Win, Win+L, L). Whenever the Win+L state is reached, set a flag ("winLSet" below). Whenever all of the keys have been released, we check for this flag and simulate the press if it's been set.
The final piece of the puzzle is to simulate the WinKey's KeyUp before the Ctrl-L (no KeyDown). I've tried similar approaches in AutoHotkey and it never worked, but it seems to work perfectly here.
The code is below. Please see explanatory notes at the bottom if you plan to use this code.
For posterity: please note that this code uses InputSimulator and LowLevelKeyboardHook, which are not from the .NET Framework. LowLevelKeyboardHook is a class I wrote a while back that exposes global KeyDown and KeyUp events as C# events. There are similar examples here, here, and a bunch can be found here.
Also notice that I'm using System.Windows.Input.Key, not System.Windows.Forms.Keys, which could confuse some people. System.Windows.Input.Key is the new enumeration of keys in .NET 3.0 and above, while System.Windows.Forms.Keys is the old enumeration from Windows Forms.
我尝试使用 Windows 输入模拟器 库中断 Windows 键。这是我的回调:
使用这个钩子,我的左 Windows 键在 Win XP 下充当 Shift 键(如实现和预期)。
按 WinKey + l 仅返回
L
。编辑:但是,我可以证实您的观察,该代码不再在 Windows 7 下工作:/抱歉,我无法为您提供进一步的帮助。
I tried to interrupt the windows key using the Windows Input Simulator library. This is my callback:
Using this hook my left windows key acts as a shift key (as implemented & expected) under Win XP.
Pressing WinKey + l returns just
L
.EDIT: However, I can confirm your observation, that this code does not work under Windows 7 anymore :/ Sorry, I can't help you any further.
如果您可以检测到密钥 Cmd+L,您可以直接锁定工作站,而无需转发 Winkey+L< /kbd>?您可以使用 API
LockWorkstation< /code>
(或
rundll32.exe user32.dll,LockWorkStation
)If you can detect the key Cmd+L could you just go ahead and lock the workstation without bothering to forward Winkey+L? you can do it with the API
LockWorkstation
(orrundll32.exe user32.dll,LockWorkStation
)