8

我从事一个名为UAWKS(非官方 Apple 无线键盘支持)的项目,该项目可帮助 Windows 用户使用 Apple 的蓝牙键盘。UAWKS 的主要目标之一是将Cmd密钥(Winkey在 Windows 中的行为)与交换Ctrl,允许用户执行Cmd+C用于复制,Cmd+T用于新选项卡等。

它目前使用AutoHotkey开发,在 Windows XP 下运行良好。但是,在 Vista 和 Windows 7 上,Cmd+L会导致问题:

  • 无论低级键盘钩子如何,Win+L总是被 Windows 拦截并通常锁定工作站...
  • 您可以使用此注册表 hack禁用工作站锁定,但按Win+L仍然无法在 AHK 中反弹
  • Win+L使 Winkey 处于 Keydown 状态,直到下一个(附加)Winkey Up。模拟 Keyup 事件似乎也不起作用!

似乎Win+L是一个特殊的和弦,它把其他一切都搞砸了。

我查看了 AHK 源代码,他们尝试SendKey()在 keyboard_mouse.cpp 中解决这个问题(在 v1.0.48.05 中的第 883 行附近),但它不起作用。我用 C# 编写了自己的低级键盘挂钩应用程序,我看到了同样的问题。

有没有其他人遇到过这个?有解决方法吗?

4

3 回答 3

2

我想出了一种在 C# 中执行此操作的方法。在可能的Win+L按键序列中涉及四种状态(无Win、、Win+ LL)。每当达到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# 事件。这里有类似的例子,这里,还有一堆可以在这里找到

另请注意,我使用的是 System.Windows.Input.Key,而不是 System.Windows.Forms.Keys,这可能会使某些人感到困惑。System.Windows.Input.Key 是 .NET 3.0 及更高版本中键的新枚举,而 System.Windows.Forms.Keys 是 Windows 窗体的旧枚举。

于 2010-05-25T19:00:58.047 回答
0

如果您可以检测到键Cmd+ L,您是否可以继续锁定工作站而无需费心转发Winkey+ L?您可以使用 API LockWorkstation(或rundll32.exe user32.dll,LockWorkStation

于 2010-05-25T15:55:55.827 回答
0

我尝试使用Windows 输入模拟器库来中断 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 下工作:/ 抱歉,我无法为您提供更多帮助。

于 2010-05-25T16:00:39.607 回答