Skip to content

Instantly share code, notes, and snippets.

@philcleveland
Last active January 17, 2020 01:06
Show Gist options
  • Save philcleveland/7897459 to your computer and use it in GitHub Desktop.
Save philcleveland/7897459 to your computer and use it in GitHub Desktop.
Shows how to use Rx to capture keypress events. I use it for fastforward and reverse in the media sense. ABetterKeyPressCapture.cs was written by Chris Harris @cwharris. I appreciate his answer on StackOverflow.
using System;
using System.Collections.Generic;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows.Forms;
namespace RxStuff
{
class Program
{
private const int KeyPressThresholdMilliSec = 200;
static void Main(string[] args)
{
//var txt = new TextBox();
var frm = new System.Windows.Forms.Form()
{
//Controls = { txt }
};
var disposables = new List<IDisposable>();
var t = TimeSpan.FromMilliseconds(KeyPressThresholdMilliSec);
//Hook up fast forward
var upRightArrow = Observable.FromEventPattern<KeyEventArgs>(frm, "KeyUp")
.Where(x => x.EventArgs.KeyCode == Keys.Right);
upRightArrow.Subscribe(x =>
{
Console.WriteLine("FastForward STOP");
});
var downRightArrow = Observable.FromEventPattern<KeyEventArgs>(frm, "KeyDown")
.Where(x => x.EventArgs.KeyCode == Keys.Right)
.Take(1)
.Concat(upRightArrow.Take(1).IgnoreElements())
.Repeat();
//hook up frame increment
var tapFastForward = downRightArrow.SelectMany(x =>
Observable.Amb(
Observable.Empty<EventPattern<KeyEventArgs>>().Delay(t),
upRightArrow.Take(1)
))
.Publish()
.RefCount();
tapFastForward.Subscribe(x =>
{
Console.WriteLine("Increment Frame");
});
var longPressFastForward = downRightArrow.SelectMany(x =>
Observable.Return(x).Delay(t).TakeUntil(tapFastForward)
).Subscribe(x =>
{
Console.WriteLine("FastForward GO");
});
using (new CompositeDisposable(disposables))
{
Application.Run(frm);
}
}
}
}
public static class KeyPressExtensions
{
public static void WireKey(this object target, Key key, Action tapAction, Action longPressAction, Action keyUpAction)
{
const int tapTimeMilliSec = 300;
var t = TimeSpan.FromMilliseconds(tapTimeMilliSec);
var keyUp = Observable.FromEventPattern<KeyEventArgs>(target, "KeyUp")
.Where(x => x.EventArgs.Key == key);
keyUp.Subscribe(a => keyUpAction());
var keyDown = Observable.FromEventPattern<KeyEventArgs>(target, "KeyDown")
.Where(x => x.EventArgs.Key == key)
.Take(1)
.Concat(keyUp.Take(1).IgnoreElements())
.Repeat();
var tapKey = keyDown.SelectMany(x =>
Observable.Amb(
Observable.Empty<EventPattern<KeyEventArgs>>().Delay(t),
keyUp.Take(1)
))
.Publish()
.RefCount();
tapKey.Subscribe(a => tapAction());
var longPress = keyDown.SelectMany(x => Observable.Return(x).Delay(t).TakeUntil(tapKey))
.Subscribe(a => longPressAction());
}
}
using System;
using System.Collections.Generic;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Windows.Forms;
namespace RxStuff
{
class Program
{
private const int KeyPressThresholdMilliSec = 200;
static void Main(string[] args)
{
//var txt = new TextBox();
var frm = new System.Windows.Forms.Form()
{
//Controls = { txt }
};
var disposables = new List<IDisposable>();
//start FF when we get 2 key presses within the threshold time
disposables.Add(Observable.FromEventPattern<KeyEventArgs>(frm, "KeyDown")
.Where(k => k.EventArgs.KeyCode == Keys.Right)
.Timestamp()
.Buffer(2)
.Where(x => (x[1].Timestamp - x[0].Timestamp).Milliseconds < KeyPressThresholdMilliSec)
.Subscribe(x => Console.WriteLine("FastForward GO")));
//stop ff on the key up
disposables.Add(Observable.FromEventPattern<KeyEventArgs>(frm, "KeyUp")
.Where(k => k.EventArgs.KeyCode == Keys.Right)
.Subscribe(x => { Console.WriteLine("FastForward STOP"); }));
disposables.Add(Observable.FromEventPattern<KeyEventArgs>(frm, "KeyDown")
.Where(k => k.EventArgs.KeyCode == Keys.Left)
.Timestamp()
.Buffer(2)
.Where(x => (x[1].Timestamp - x[0].Timestamp).Milliseconds < KeyPressThresholdMilliSec)
.Subscribe(x => Console.WriteLine("Reverse GO")));
disposables.Add(Observable.FromEventPattern<KeyEventArgs>(frm, "KeyUp")
.Where(k => k.EventArgs.KeyCode == Keys.Left)
.Subscribe(x => { Console.WriteLine("Reverse STOP"); }));
using (new CompositeDisposable(disposables))
{
Application.Run(frm);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment