8

イベントが修飾子が設定されたキーに対するものKeyboard.Modifiersかどうかを判断するために を使用することを示唆する多くの回答を見てきました。KeyDown残念なことに、(キーが押されたときのモディファイアの状態ではなく) モディファイアの現在のKeyboard.Modifiers状態を返すため、これは素早いタイピストにとって本当に厄介な断続的なバグになります。

具体的には、誰かが Ctrl+A を押し、A を押してから数ミリ秒後に Ctrl を離したとします。ここで、システムに大きな負荷がかかっていたとします。キー ハンドラは実行を開始しましたが、50 ミリ秒プリエンプトされました。キー ハンドラが再び実行されるまでに、Ctrl の現在の状態は「解放」されています。キー ハンドラーは、Ctrl キーを押さずに "A" が押されたと認識しますが、これは問題です

同様に、速いタイピストが A、Ctrl+End を入力し、私のアプリケーションが を使用するとKeyboard.Modifiers、代わりに Ctrl+A を観察することになる可能性があります...

WinForms では、イベントが処理されるまでに Ctrl が解放されていても、イベントはKeyDownCtrl の状態を正確に教えてくれます。WPFでこれと同じ動作を得るにはどうすればよいですか?

編集: Keyboard.Modifiers が実際には「現在の」修飾キーを取得しない可能性がありますが、代わりに現在処理中のキーダウン メッセージに関連する修飾キーを取得します。WinAPI では、これが「非同期」と非非同期のキー状態関数の違いでした。残念ながら、ドキュメントには「最新」が正確に何を意味するかについては言及されていません。知ってる人いたら教えてください。

4

2 に答える 2

2

イベント引数には修飾子情報がないように見えるため、いくつかのフィールドで状態を自分で追跡し、両方を処理してKeyUpKeyDownそれに応じて更新することができます。

例えば

private bool ctrl = false;
private void This_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.LeftCtrl) //or switch, also: `LeftCtrl` & `RightCtrl` are treated as separate keys
        ctrl = true;
    //etc..
}

private void This_KeyUp(object sender, KeyEventArgs e)
{
    if (e.Key == Key.LeftCtrl)
        ctrl = false;
    //etc..
}

これが実際に良い考えかどうかは、私には言えません...


キージェスチャを処理したいKeyBindings場合は、ジェスチャが発生したときにのみ起動するように、専用のメソッドを使用することをお勧めします。他の入力については、TextInputどちらがより抽象的で、入力が翻訳されたテキストを返すかを確認することもできます。

于 2012-08-25T21:53:14.870 に答える
2

この破壊的な答えで申し訳ありませんが...

少し調査した後、私には明らかになりました...イベントは「KeyCombinationDown」ではなく「KeyDown」と呼ばれるため、前に押された修飾子とは完全に独立しています...

実際には、目標を達成するための正しい方法があります。それは、コマンド パターンを使用することです。

COMMAND を定義し (WPF-Commanding については google を参照)、KeyBinding をアプリケーションに追加します。ここで、コマンドを起動するキーまたはキー/キーの組み合わせを定義します...

ここの例を参照してください: http://msdn.microsoft.com/en-us/library/system.windows.input.keybinding.aspx

私見、これが唯一の方法であり、意味的にもよりエレガントです。

(このパターンが GENERAL で機能しない場合は、pinvoke でネイティブ API を使用する必要があるかもしれません)。

乾杯。

于 2012-08-26T03:17:27.130 に答える