トップ回答者
EnterキーのPreviewKeyDown, KeyDownイベントが発生しない

質問
-
皆さんこんにちは。
Expression Blendにて作成したウィンドウのKeyDownイベントで、押下されたキー毎の処理記述をしているのですが、Enterキーを押下した時のみ、KeyDownイベントが発生しません。
ちなみに他のキーは全て正常にイベントが発生します。
調査した結果以下のようになりました。
Enter押下時
(×)PreviewKeyDown
(×)KeyDown
(○)PreviewKeyUp
(○)KeyUp
IMEなど環境の問題かと思い、簡単なテストアプリを作成して実行したところ、正常にEnterキーによるKeyDownイベントが発生します。
余談ですが以前IMEがナチュラルインプットモードになっていた際に、Spaceキー、F6~F10がKeydownでImeProcessedというKeyコードであがってくるという経験があります。
正常に動作しないウィンドウで使用している主なコントロールは以下の通りです。
Grid
StackPanel
Label
何か調査する手掛かりを教えてください。
<2007.6.28追記>
少し質問の仕方を変えます。
上記のように、特定キーのKeyDownイベントを発生させないようにすることは可能でしょうか?
他のアプリではEnterのKeyDownイベントは正常に発生するため、貼り付けているコントロールで無効化されているのではとも思うのですが、方法が分かりません。。。よろしくお願いします。
回答
-
ついに謎が解けました!
原因ですが、Main()の中にありました。
元々MVCアーキテクチャーにて開発した非WPFアプリのViewの部分を、WPFを利用したDLLに差替えていました。
Mainの中で記述しているメッセージループ開始処理を、WPF方式に変更することにより、EnterのKeydownが発生するようになりました。
コード ブロックSystem.Windows.Forms.Application.Run()
と記述したいたものを、
コード ブロックinternal class MessageLoop : System.Windows.Application {}
と言うクラスを宣言して、Mainの記述を以下のように変更しました。
コード ブロック// メッセージループ処理(WPF対応)
MessageLoop messageLoop = new MessageLoop();
messageLoop.Run();メッセージループ処理自体に違いがあること自体を把握していなかったのと、変更しなくても今回の件以外は問題なく動作していたことで、解決までにとんでもなく時間がかかってしまいました。
これまでコメントいただき、本当に感謝しています。
ありがとうございました。
すべての返信
-
mkuge さんからの引用 上記のように、特定キーのKeyDownイベントを発生させないようにすることは可能でしょうか?
他のアプリではEnterのKeyDownイベントは正常に発生するため、貼り付けているコントロールで無効化されているのではとも思うのですが、方法が分かりません。。。イベント引数のRoutedEventArgs.Handledプロパティをtrueにする事により、そのハンドラ以降のイベントハンドラが呼び出されなくなります。
後は、イベントハンドラの呼び出される順序を考慮すれば、イベントの発生が抑制されたような動きは作成する事が可能です。
-
しばらくお手上げ状態で、別のキーで代用しているのですが、なんかすっきりしません。
PreviewKeyDown, KeyDownイベントが発生しないキーは、Enter以外にもあることが判明しました。
Enter, Esc, Tab, Up, Down, Left, Right です。
System.Windows.Windowを継承しているクラスにて、明示的にイベントハンドラを追加し、処理済イベントとされていた場合も捕獲できるようにhandledEventsToo引数をTrueにセットしてやってみましたが、やはりイベントが発生しません。
AddHandler(Window.KeyDownEvent, new RoutedEventHandler(KeyDownHandle), true);
WPFコントロールで、これらキー入力を制御するプロパティなど、どなたかご存知ありませんか?
きっと簡単なことを間違えているのだと思うのですが。。。
-
どのような状態で発生しないのか、いまいち認識していません。
コード ブロックpublic partial class Window1 : Window
{public Window1()
{
InitializeComponent();
}protected override void OnKeyDown(KeyEventArgs e)
{
System.Diagnostics.Debug.WriteLine( "OnKeyDown : " + e.Key.ToString() );
base.OnKeyDown(e);
}
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
System.Diagnostics.Debug.WriteLine( "OnPreviewKeyDown : " + e.Key.ToString() );
base.OnPreviewKeyDown(e);
}
}コード ブロック<Window x:Class="WindowsApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowsApplication1" Height="300" Width="300"
>
<StackPanel>
<Label>----- Label -----</Label>
<TextBox/>
</StackPanel>
</Window> -
コード ブロック
protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e) {
base.OnKeyDown(e);
_uiCommon.AcceptKey(InputLabel, e);
System.Console.WriteLine(string.Format("KeyDown {0}", e.Key.ToString()));
}protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e) {
base.OnPreviewKeyDown(e);
System.Console.WriteLine(string.Format("PreviewKeyDown {0}", e.Key.ToString()));
}protected override void OnKeyUp(System.Windows.Input.KeyEventArgs e) {
base.OnKeyUp(e);
System.Console.WriteLine(string.Format("KeyUp {0}", e.Key.ToString()));
}protected override void OnPreviewKeyUp(System.Windows.Input.KeyEventArgs e) {
base.OnPreviewKeyUp(e);
System.Console.WriteLine(string.Format("PreviewKeyUp {0}", e.Key.ToString()));
}System.Windows.Windowを継承している画面に、上記コードを記述しています。
元々はXAMLにイベントに対するトリガーを記述していましたが、今回上記のようにWindowの処理をオーバライドする形に変更してみましたが、結果同じです。
通常のキー(例えばAなど)を押下した場合には、4つのイベントが同時に発生するのですが、Enterキーだと OnPreviewKeyUp, OnKeyUpの2つのイベントしか発生しません。
ためしにテキストボックスを貼り付けて、そのコントロールのKeydownで試してみましたが、同じように Enterキーだと、Up系2種類のイベントしか発生しないのです。
以前の投稿でも書きましたが別の開発したアプリでは、問題なくEnterキーのKeydown, PreviewKeydownイベントが発生するため、外部環境というわけではなさそうです。
Grid, StackPanel, Labelを多数貼り付けていますが、キーイベントは全てWindowでのみキャッチし、Label.Contentプロパティに値を表示するというアプリになります。
-
Grid, StackPanel, Labelを多数貼り付けていますが、キーイベントは全てWindowでのみキャッチし、Label.Contentプロパティに値を表示するというアプリになります。 再現可能な最小なXAMLコードは提示可能なんでしょうか?
そういうのを探るうちに原因がわかったりするもんなんですけどね。
キーボード入力の大元は,実際は,
System.Windows.Input の Keyboardクラスの各attached eventです。
そこにAddHandler( , , true)してみると,どうなってるのか?がわかるかも。
-
ついに謎が解けました!
原因ですが、Main()の中にありました。
元々MVCアーキテクチャーにて開発した非WPFアプリのViewの部分を、WPFを利用したDLLに差替えていました。
Mainの中で記述しているメッセージループ開始処理を、WPF方式に変更することにより、EnterのKeydownが発生するようになりました。
コード ブロックSystem.Windows.Forms.Application.Run()
と記述したいたものを、
コード ブロックinternal class MessageLoop : System.Windows.Application {}
と言うクラスを宣言して、Mainの記述を以下のように変更しました。
コード ブロック// メッセージループ処理(WPF対応)
MessageLoop messageLoop = new MessageLoop();
messageLoop.Run();メッセージループ処理自体に違いがあること自体を把握していなかったのと、変更しなくても今回の件以外は問題なく動作していたことで、解決までにとんでもなく時間がかかってしまいました。
これまでコメントいただき、本当に感謝しています。
ありがとうございました。