16

ToAscii()グローバルな WH_KEYBOARD_LL フックでorを呼び出すToUnicode()と、デッドキーが押されると「破棄」されるようです。

たとえば、Windows で入力言語をスペイン語に設定していて、プログラムでアクセント付き文字áを入力したいとします。通常、一重引用符キー (デッド キー) を押してから文字 "a" を押すと、期待どおり、アクセント付きのáが画面に表示されます。

ToAscii()ただし、またはToUnicode()を低レベルのキーボード フック関数で呼び出した場合、これは機能しません。デッドキーが破壊されたようで、アクセント付きの文字áが画面に表示されません。上記の関数の呼び出しを削除すると問題は解決します...しかし、残念ながら、これらの関数を呼び出せるようにする必要があります。

私はしばらくグーグルで調べましたが、多くの人がこの問題を抱えているように見えましたが、良い解決策は提供されませんでした.

どんな助けでも大歓迎です!

編集: LowLevelKeyboardProcToAscii()フック関数で受け取った仮想キー コードとスキャン コードを、ユーザーの画面に表示される結果の文字に変換するために呼び出しています。

を試しMapVirtualKey(kbHookData->vkCode, 2)ましたが、これは のように「完全な」機能ではありませんToAscii()。たとえば、Shift + 2 を押すと、'@' ではなく '2' が返されます (または、ユーザーのキーボード レイアウト/言語に対して Shift + 2 が生成するもの)。

ToAscii()完璧です...デッドキーが押されるまで。

EDIT2:関係のない情報が削除されたフック関数は次のとおりです。

LRESULT CALLBACK keyboard_LL_hook_func(int code, WPARAM wParam, LPARAM lParam) {

    LPKBDLLHOOKSTRUCT kbHookData = (LPKBDLLHOOKSTRUCT)lParam;
    BYTE keyboard_state[256];

    if (code < 0) {
        return CallNextHookEx(keyHook, code, wParam, lParam);
    }

    WORD wCharacter = 0;

    GetKeyboardState(&keyboard_state);
    int ta = ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode,
                     keyboard_state, &wCharacter, 0);

    /* If ta == -1, a dead-key was pressed. The dead-key will be "destroyed"
     * and you'll no longer be able to create any accented characters. Remove
     * the call to ToAscii() above, and you can then create accented characters. */

    return CallNextHookEx(keyHook, code, wParam, lParam);
}
4

8 に答える 8

5

かなり古いスレッド。残念ながら、私が探していた答えが含まれておらず、どの答えも適切に機能していないようでした。/を呼び出す前に、関数のMSBをチェックして問題を解決しました。魅力のように機能しているようです:MapVirtualKeyToUnicodeToAscii

if(!(MapVirtualKey(kbHookData->vkCode, MAPVK_VK_TO_CHAR)>>(sizeof(UINT)*8-1) & 1)) {
    ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode,
        keyboard_state, &wCharacter, 0);
}

の戻り値で MSDN を引用するとMapVirtualKeyMAPVK_VK_TO_CHARが使用されている場合:

[...] デッド キー (分音符号) は、戻り値の最上位ビットを設定することによって示されます。[...]

于 2016-06-19T17:19:58.490 に答える
3
  1. ToAscii() の使用をやめ、ToUncode() を使用する
  2. ToUnicode は、デッド キーに対しては何も返さない可能性があることに注意してください。これがデッド キーと呼ばれる理由です。
  3. どのキーにもスキャンコードまたは仮想キー コードがありますが、文字は必要ありません。

ボタンと文字を組み合わせてはいけません - キー/ボタンにテキスト表現 (Unicode) があると仮定するのは間違っています。

そう:

  • 入力テキストには、 Windows によって報告された文字を使用します
  • ボタンが押されたことを確認するには(ゲームなど)、スキャンコードまたは仮想キーを使用します(おそらく仮想キーの方が優れています)。
  • キーボード ショートカットには、仮想キーコードを使用します。
于 2009-12-28T16:51:47.620 に答える
2

ToAsciiまたは2 回呼び出すことToUnicodeが答えです。これを見つけて Delphi 用に変換したところ、うまくいきました。

cnt:=ToUnicode(VirtualKey, KeyStroke, KeyState, chars, 2, 0);
cnt:=ToUnicode(VirtualKey, KeyStroke, KeyState, chars, 2, 0); //yes call it twice
于 2012-07-04T07:37:14.707 に答える
2

デッドキーを正しく処理するには、次のように「ToAscii」関数を 2 回呼び出します。

int ta = ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode,
                 keyboard_state, &wCharacter, 0);
int ta = ToAscii((UINT)kbHookData->vkCode, kbHookData->scanCode,
                 keyboard_state, &wCharacter, 0);
If (ta == -1)
 ...
于 2010-09-02T08:19:22.540 に答える
1

C# でキー ロガーを作成しているときにこの問題が発生しましたが、上記の回答はどれもうまくいきませんでした。

ブログを深く検索した後、デッド キーを完全に処理するこのキーボード リスナーを見つけました。

于 2019-10-27T08:44:06.987 に答える