none
EnterキーのPreviewKeyDown, KeyDownイベントが発生しない RRS feed

  • 質問

  •  

    皆さんこんにちは。

     

    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イベントは正常に発生するため、貼り付けているコントロールで無効化されているのではとも思うのですが、方法が分かりません。。。

     

    よろしくお願いします。

    2007年6月26日 12:20

回答

  •  

    ついに謎が解けました!

     

    原因ですが、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();

     

     

    メッセージループ処理自体に違いがあること自体を把握していなかったのと、変更しなくても今回の件以外は問題なく動作していたことで、解決までにとんでもなく時間がかかってしまいました。

     

    これまでコメントいただき、本当に感謝しています。

    ありがとうございました。

    2007年10月18日 6:55

すべての返信

  •  mkuge さんからの引用

    上記のように、特定キーのKeyDownイベントを発生させないようにすることは可能でしょうか?
    他のアプリではEnterのKeyDownイベントは正常に発生するため、貼り付けているコントロールで無効化されているのではとも思うのですが、方法が分かりません。。。

     

    イベント引数のRoutedEventArgs.Handledプロパティをtrueにする事により、そのハンドラ以降のイベントハンドラが呼び出されなくなります。

    後は、イベントハンドラの呼び出される順序を考慮すれば、イベントの発生が抑制されたような動きは作成する事が可能です。

    2007年6月28日 2:28
  • FC-Shiroさん、回答ありがとうございます。

     

    EnterキーのみKeyDownを発生させたくない場合、貼り付けているコントロールのKeyDown処理でRoutedEventArgs.HandledプロパティをTrueにするということですね。

    全てのソースファイルを"Handled"で検索してみましたが、見つかりませんでした。

     

    他に何か原因があるようです。

     

    2007年6月28日 7:10
  • ちょっと試してないんで、無責任モードですが、

    KeyboardNavigation.AcceptsReturn

    この辺りのアタッチプロパティは関係ないですかね?

     

    2007年6月28日 10:20
  • 情報ありがとうございます。

    Windowに貼り付けている全てのコントロールのKeyboardNavigation.AcceptsReturnを確認してみましたが、全てFalseのデフォルトになっています。うまくEnterキーのKeydownイベントが発生するアプリの方も確認してみましたが、同じ値です。

    残念ですが、他に原因があるようです。

    2007年6月29日 1:10
  •  

    しばらくお手上げ状態で、別のキーで代用しているのですが、なんかすっきりしません。

     

    PreviewKeyDown, KeyDownイベントが発生しないキーは、Enter以外にもあることが判明しました。

    Enter, Esc, Tab, Up, Down, Left, Right です。

     

    System.Windows.Windowを継承しているクラスにて、明示的にイベントハンドラを追加し、処理済イベントとされていた場合も捕獲できるようにhandledEventsToo引数をTrueにセットしてやってみましたが、やはりイベントが発生しません。

     

    AddHandler(Window.KeyDownEvent, new RoutedEventHandler(KeyDownHandle), true);

     

    WPFコントロールで、これらキー入力を制御するプロパティなど、どなたかご存知ありませんか?

    きっと簡単なことを間違えているのだと思うのですが。。。

    2007年10月16日 7:56
  • どのような状態で発生しないのか、いまいち認識していません。

     

    コード ブロック

     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>

     

     

    の状態で、TextBoxにフォーカスがある時、ない時、共にKeyDown、PreviewKeyDownが来てます。
    2007年10月16日 10:34
  • コード ブロック

     

      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プロパティに値を表示するというアプリになります。

     

    2007年10月17日 14:37
  •  

    Grid, StackPanel, Labelを多数貼り付けていますが、キーイベントは全てWindowでのみキャッチし、Label.Contentプロパティに値を表示するというアプリになります。

     

    再現可能な最小なXAMLコードは提示可能なんでしょうか?

    そういうのを探るうちに原因がわかったりするもんなんですけどね。

     

    キーボード入力の大元は,実際は,

    System.Windows.Input の Keyboardクラスの各attached eventです。

    そこにAddHandler( , , true)してみると,どうなってるのか?がわかるかも。

     

     

     

     

     

     

     

     

     

    2007年10月17日 20:57
  • いただいた情報を元に、下記のコードを画面初期化処理に追加してみました。

    結果、やはりEnterはKeyUp, PreviewKeyUpイベントしか発生しないことが判明しました。

     

    コード ブロック

    AddHandler(Keyboard.KeyDownEvent, new RoutedEventHandler(KeyDownHandle), true);

     

     

    アドバイスどおりXAMLを最小限化し、どの時点でこの現象が発生するのか探ってみます。

     

    2007年10月18日 0:23
  •  

    ついに謎が解けました!

     

    原因ですが、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();

     

     

    メッセージループ処理自体に違いがあること自体を把握していなかったのと、変更しなくても今回の件以外は問題なく動作していたことで、解決までにとんでもなく時間がかかってしまいました。

     

    これまでコメントいただき、本当に感謝しています。

    ありがとうございました。

    2007年10月18日 6:55