私が達成しようとしているのは、複雑なキーのプレスとリリースのシーケンスを Rx で処理することです。Rx の経験はほとんどありませんが、現在の仕事には明らかに十分ではないので、助けを求めてここにいます。
私の WinForms アプリはバックグラウンドで実行されており、システム トレイにしか表示されません。特定のキー シーケンスによって、そのフォームの 1 つをアクティブにしたいと考えています。ところで、グローバル キー プレスに接続するために、私は素敵なライブラリhttp://globalmousekeyhook.codeplex.com/を使用しています。すべてのキー ダウン イベントとキー アップ イベントを受け取ることができます。生成されます (標準のキーボード リピート レートで)。
キャプチャしたいキー シーケンスの例の 1 つは、Ctrl + Insert キーをすばやく 2 回押すことです (Ctrl キーを押しながら、Insert キーを一定時間内に 2 回押すなど)。これが私のコードに現在あるものです:
var keyDownSeq = Observable.FromEventPattern<KeyEventArgs>(m_KeyboardHookManager, "KeyDown");
var keyUpSeq = Observable.FromEventPattern<KeyEventArgs>(m_KeyboardHookManager, "KeyUp");
var ctrlDown = keyDownSeq.Where(ev => ev.EventArgs.KeyCode == Keys.LControlKey).Select(_ => true);
var ctrlUp = keyUpSeq.Where(ev => ev.EventArgs.KeyCode == Keys.LControlKey).Select(_ => false);
しかし、私は立ち往生しています。私の考えは、Ctrlキーが押されているかどうかを追跡する必要があるということです。1 つの方法は、そのためのグローバル変数を作成し、それを Merge リスナーで更新することです。
Observable.Merge(ctrlDown, ctrlUp)
.Do(b => globabl_bool = b)
.Subscribe();
しかし、それは Rx アプローチ全体を台無しにすると思います。Rxパラダイムにとどまりながらそれを達成する方法についてのアイデアはありますか?
次に、Ctrl が押されている間に、特定の時間内に 2 回の Insert プレスをキャプチャする必要があります。私はバッファの使用を考えていました:
var insertUp = keyUpSeq.Where(ev => ev.EventArgs.KeyCode == Keys.Insert);
insertUp.Buffer(TimeSpan.FromSeconds(1), 2)
.Do((buffer) => { if (buffer.Count == 2) Debug.WriteLine("happened"); })
.Subscribe();
ただし、キーが押されていなくても、Buffer は 1 秒ごとにイベントを生成するため、これが最も効率的な方法かどうかはわかりません。より良い方法はありますか?また、どうにかしてそれを Ctrl down と組み合わせる必要があります。
繰り返しになりますが、Ctrl を押している間に Insert を 2 回押したことを追跡する必要があります。私は正しい方向に進んでいますか?
PS 別の可能なアプローチは、Ctrl が押されている間のみ、Insert Observable をサブスクライブすることです。しかし、それを達成する方法がわかりません。これについてもいくつかのアイデアがありますか?
編集:私が見つけたもう 1 つの問題は、Buffer が私のニーズに正確に合わないことです。問題は、Buffer が 2 秒ごとにサンプルを生成し、最初のプレスが最初のバッファーに属し、2 番目が次のバッファーに属している場合、何も起こらないという事実から生じます。それを克服する方法は?