2011-01-25 17 views
0

挨拶、WPF処理中に入力されたキーストロークを検出

私は、処理中に、キーの押下を検出することができますWPF Windowsアプリケーション、特に「エスケープ」文字キープレス内で、イベントハンドラ内で実行するコードを書きたいですループ。これにより、ユーザーは処理を逃れることができます。私はこれが何らかのマルチスレッドアプローチで実現できることを認識していますが、問題はとてもシンプルに思えます。次のように達成できるかどうか疑問に思っています:

//試行1:キーボードの静的IsKeyDownメソッドがキー押下実行中。
//これは成功しなかったことに注意してください。キーボードの状態は、処理中に更新されていないようです。

 bool iskeypressed = false; 
     while (!iskeypressed) 
     { 
      System.Threading.Thread.Sleep(1000); 
      if (Keyboard.IsKeyDown(Key.Enter)) 
       iskeypressed = true; 
     } 

ので、上は#2を試みます。 Pinvokeの "GetKeyboardState"メソッドを使っていくつかの記事とサンプルを見ました。私はこの方法を正しく使ったかどうかはわかりませんが、ここでは私の試みです。 WPFアプリケーションでWindows.Forms列挙型を参照するのは少し面倒ですが、うまくいくようです。

//試行2:Pinvoke GetKeyboardStateメソッドを使用します。
//これまでのところ、私はこれでもうまくいっていませんでしたが、私の使い方が正しいかどうかはわかりません。

 bool iskeypressed = false; 
     while (!iskeypressed) 
     { 
      System.Threading.Thread.Sleep(1000); 
      if (isEscapePressed()) 
       iskeypressed = true; 
     } 
    } 


    [DllImport("user32.dll")] public static extern int GetKeyboardState(byte[] lpKeyState); 
    private bool isEscapePressed() 
    { 
     byte[] keyboardState = new byte[255]; 
     int keystate = GetKeyboardState(keyboardState); 

     if (keyboardState[(int)System.Windows.Forms.Keys.Escape] == 128) 
      return true; 
     else 
      return false; 
    }  

残念ながら、これが実行されるとキーボードの状態に変化は見られません。また、処理中にキーボード情報をリフレッシュすることができるかどうかを知るためにDispatcherへの呼び出しを少し回しましたが、どのテクニックも成功していません。

私はアイデアがありません。誰かが何かを提案できますか?ご協力いただきありがとうございます。

  • デビッド

答えて

3

このような何か:

private bool IsCancelled { get; set; } 

private void OnButtonClick(object sender, EventArgs e) 
{ 
    Action doWorkDelegate = DoWork; 

    doWorkDelegate.BeginInvoke(null, null); 
} 

protected override void OnKeyDown(KeyEventArgs e) { 
    if (e.Key == Key.Escape) { 
     IsCancelled = true; 
     e.Handled = true; 
    } else { 
     base.OnKeyDown(e); 
    } 
} 

private void DoWork() 
{ 
    IsCancelled = false; 
    while (!IsCancelled) 
    { 
     System.Threading.Thread.Sleep(1000); 
    } 
} 

重要な点は、メインスレッドは、ユーザ入力を処理することができるように作業を行う方法は(別のスレッドで実行されることですキーストローク)。

+0

私は上記の答えの両方が非常に役に立つと思います。私はマルチスレッドアプローチがこれを達成するための唯一の方法だと受け入れなければなりません。おそらく、マルチスレッドから発生する複雑な問題に躊躇していたため、UIスレッドでWindowsに制御を戻さずにキーボードの状態を確認する方法を実現することを望んでいました。 私たちは、チェックされた例の後で我々のソリューションをモデリングしています。それ以上の重大な合併症があれば投稿します。大変お手伝いしてくれてありがとう。 –

1

非常に長いループを実行してWPFをブロックしている間、キーイベントを検出することはできません。マルチスレッドのアプローチを使用する必要があります。または、ループを分割する必要があります。

BackgroundWorkerを使用すると、ループ実行中にWPFがフロントエンドを処理し続けるようにする簡単な方法です。

private BackgroundWorker bw; 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     if (bw != null) 
      return; 

     bw = new BackgroundWorker(); 
     bw.WorkerSupportsCancellation = true; 
     bw.WorkerReportsProgress = true; 

     bw.DoWork += (senderBw, eBw) => 
     { 
      for (int i = 0; i < 100; i++) 
      { 
       Thread.Sleep(1000); 

       bw.ReportProgress(i); 

       if (eBw.Cancel) 
        return; 
      } 
     }; 
     bw.ProgressChanged += (senderBw, eBw) => 
     { 
      //TODO set progressbar to eBw.ProgressPercentage 
     }; 
     bw.RunWorkerCompleted += (senderBw, eBw) => 
     { 
      this.bw = null; 
      //TODO frontend stuff (hide progressbar etc) 
     }; 

     bw.RunWorkerAsync(); 
    } 

    private void MainWindow_KeyDown(object sender, KeyEventArgs e) 
    { 
     if (this.bw != null && this.bw.IsBusy && e.Key == Key.Escape) 
      this.bw.CancelAsync(); 
    } 
関連する問題