8

私は、Windows ユーザーが Apple の Bluetooth キーボードを使用できるようにするUAWKS (Unofficial Apple Wireless Keyboard Support) というプロジェクトに取り組んでいます。UAWKS の主な目標の 1 つは、Cmdキー ( WinkeyWindows のように動作する) をに交換してCtrl、ユーザーがCmd+Cでコピー、Cmd+Tで新しいタブなどを実行できるようにすることです。

現在、 AutoHotkeyを使用して開発されており、これは Windows XP で非常にうまく機能しました。ただし、Vista および Windows 7 では、Cmd+Lは問題を引き起こします。

  • 低レベルのキーボード フックに関係なく、Win+Lは常に Windows によって傍受され、通常はワークステーションをロックします...
  • このレジストリ ハックでワークステーションのロックを無効にすることはできますが、AHK でWin+を押しLてもリバウンドすることはできません。
  • Win+を押すとL、次の (追加の) Winkey Up まで Winkey は Keydown 状態のままになります。Keyup イベントのシミュレーションもうまくいかないようです!

Win+Lは他のすべてを台無しにする特別なコードのようです。

AHK のソース コードを調べたところSendKey()、keyboard_mouse.cpp (v1.0.48.05 の 883 行目付近) でこの問題に対処しようとしましたが、うまくいきません。C# で独自の低レベルのキーボード フック アプリケーションを作成しましたが、同じ問題が発生します。

他の誰かがこれに遭遇しましたか?回避策はありますか?

4

3 に答える 3

2

私はC#でこれを行う方法を考え出しました。Win+Lキーを押す可能性のあるシーケンスには4つの状態が関係しています(なし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');
        }
    }
}

後世のために:このコードは、.NETFrameworkのものではないInputSimulatorとLowLevelKeyboardHookを使用していることに注意してください。LowLevelKeyboardHookは、グローバルなKeyDownイベントとKeyUpイベントをC#イベントとして公開する、私がしばらく前に書いたクラスです。ここ、ここに同様の例があり、ここにたくさんあります

また、System.Windows.Forms.KeysではなくSystem.Windows.Input.Keyを使用していることに注意してください。これにより、一部の人が混乱する可能性があります。System.Windows.Input.Keyは、.NET 3.0以降の新しいキーの列挙であり、System.Windows.Forms.Keysは、Windowsフォームの古い列挙です。

于 2010-05-25T19:00:58.047 に答える
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 で (実装および期待どおり) シフト キーとして機能します。+を
押すと、 だけが返されます。WinKeylL

編集:ただし、このコードは Windows 7 では動作しないというあなたの観察を確認できます:/申し訳ありませんが、これ以上お手伝いすることはできません。

于 2010-05-25T16:00:39.607 に答える
0

キーCmd+を検出できる場合は、わざわざ+Lを転送せずにワークステーションをロックしていただけますか? API (または)でそれを行うことができますWinkeyLLockWorkstationrundll32.exe user32.dll,LockWorkStation

于 2010-05-25T15:55:55.827 に答える