4

キーボードフックをインストールしてすべてのキーをキャプチャし、それらに関連するテキストを表示するプログラムを作成しています。

しかし、私は引っ掛かりにぶつかりました、そしてそれはフックがインストールされるときいくつかのキーが振る舞いを変えることです。

小さいながらも完全なテストプログラムを投稿する方法については説明しますが、ここでは問題について説明します。

この問題は、C#プログラムである.NET4.0のWindows764ビットで発生します。私はこれは問題ではないと思います。

私のフックはそれ自体を経由してインストールSetWindowsHookExし、システムで処理されるすべてのキーを処理します。

フックメソッドが単に戻るか、キーの最小限の処理を実行する場合(動作を変更するものをすぐに投稿します)、キーボードはプログラムで期待どおりに機能します。

ただし、User32.dllからこの関数を呼び出しToAsciiて、キーボードのOemTildeまたは同様のキーが実際にどのキーであるかを判断すると、「次のキーをオーバーレイする」キーは機能しなくなります。そのようなキーの正しい名前はわかりませんが、2つのアポストロフィタイプである「」と「, as well as´〜¨ and」は機能を停止します。

たとえば、を押してからを押す~N、次のように表示されます。

  • キーボードフックが取り付けられていない場合:ñ
  • キーボードフックが取り付けられている場合:n(上記のno〜に注意してください)

なぜこれが起こるのか、そしてどうすればこの問題を解決できるのか誰かが知っていますか?

今のところ、他のプログラムでキーを正しく処理するだけで解決します。それは、自分のプログラムで正しいキーシーケンスを正しく検出できないことを意味します。

いくつかの詳細情報:

ToAsciiフックメソッドの一部として関数を呼び出すと、別の問題が発生します。のようなキー¨は2回処理されます。¨一度押すと、メモ帳は2¨¨文字を受け取り、N今押すと。が追加されますN

ただし、BeginInvoke別のスレッドでキーを処理するために使用する場合、キーボードフックメソッドから戻った後、最初の問題が発生します。


私のプログラムはおそらくその点で少し特別です:

  • キーボードの状態を使用していません(つまり、渡す「キーの状態」の256バイト配列は0でいっぱいです)
  • 私はデッドキーを気にしません(私のプログラムがそれらを処理しないという意味で、私は自分のプログラムがそれらをシステムの他の部分に役に立たなくすることを望まないようにそれらを十分に気にします)

そのため、私のコードは次のようになりました。

private bool IsDeadKey(uint key)
{
    return ((Hook.Interop.MapVirtualKey(key, 2) & 2147483648) == 2147483648);
}

void _Hook_KeyDown_Async(KeyDownEventArgs e)
{
    var inBuffer = new byte[2];
    char key = '\0';
    if (!IsDeadKey((uint)e.KeyCode))
    {
        int ascii = Hook.Interop.ToAscii((int) e.KeyCode,
                                            e.ScanCode,
                                            _KeyState,
                                            inBuffer,
                                            e.Flags);
        if (ascii == 1)
        {
            key = Char.ToUpper((char) inBuffer[0]);
        }
    }

    BeginInvoke(
        new Action<Keys, Boolean, Boolean, Boolean, Char>(ProcessKeyboardEvent),
        e.KeyCode, e.Control, e.Shift, e.Alt, key);
}
4

4 に答える 4

2

これらのキーはデッドキーと呼ばれ、への呼び出しを削除することで問題を解決できる場合がありますToAscii。次の関連スレッドも参照してください。

キーボードフックのToAscii/ToUnicodeは、デッドキーを破棄します。

更新:コードを見ていませんが、コールバック関数のパラメーターを処理するときに、パラメーターが0未満KeyboardProcのときにキーボードメッセージを渡すことを確認できますか?codeドキュメントには次のように書かれています。

コード[in] int

フックプロシージャがメッセージの処理方法を決定するために使用するコード。コードがゼロ未満の場合、フックプロシージャは、それ以上処理せずにメッセージを関数に渡す必要があり、によって返された値を返す必要があります。CallNextHookExCallNextHookEx

MSDNにマネージフックを設定するためのサンプルがあります。

if (nCode < 0)
{
    return CallNextHookEx(hHook, nCode, wParam, lParam);
}
else
{
    // process message here

    return CallNextHookEx(hHook, nCode, wParam, lParam); 
}
于 2010-08-23T15:26:18.203 に答える
2

質問から重要な情報が欠落しています。2つのキーボードフックのどちらを使用しますか?簡単なWH_KEYBOARD_LLは機能しません。実際にキーストロークを取得するプログラムではなく、プログラムのキーボード状態を使用することになります。デッドキーは確かに違いを生みます。

難しいのは、WH_KEYBOARDには、マネージコードで記述できないフックが必要です。すべてのプロセスに挿入できるアンマネージDLLが必要です。それを取得したら、キーボードフックを気にせず、WH_CALLWNDPROCを使用してWM_CHARメッセージをログに記録することもできます。

サンプルDLLはこちらから入手できます。

于 2010-08-23T18:22:31.330 に答える
1

ここで見られる可能性が高いのは、デッドキーが関係しているときにキーをマップしようとした場合の影響です。キーボードマッピングはかなり複雑なプロセスであり、この動作を引き起こす特定の種類のキーの周りに多くの落とし穴があります。

このテーマに関するMichaelKaplanによる次のブログシリーズを読むことをお勧めします。それは私が多くのバグを整理するのに役立ちました。

于 2010-08-23T15:22:26.560 に答える
0

現在の回答と国際的な行動への言及を考えると、「コードページ」を説明する必要があるかもしれません。コードページは国によって異なります。

国コードページの例

  • アメリカ合衆国、イギリス437
  • 多言語850
  • スラブ852
  • ポルトガル語860
  • アイスランド語861
  • カナダ、フランス語863
  • スカンジナビア/北欧865

より詳しい情報

MSDN情報

Windowsアプリケーションの国際化

于 2010-08-23T15:57:18.427 に答える