使用RX.Net的移动键盘“ Shift”切换功能

时间:2018-10-09 17:50:49

标签: c# system.reactive rx.net

正在研究一个项目,需要模拟移动键盘上的“ Shift”按钮的功能;即,当按下时将切换状态切换为开启,然后在按下另一个键后返回关闭状态,但是在按住时它保持开启状态并同时按下其他键,并且仅在再次按下/保持后才关闭。我最近一直在研究RX,因此想尝试一下。

由于可以肯定有更好的方法,我可以专心研究已有的东西,甚至我都不知道如何跟踪“锁定”状态。我有标准的拨动开关工作(我认为),但是现在似乎在任何一个事件发生时都会触发两次。这是我到目前为止所拥有的

ShiftDown = Observable.FromEventPattern(ShiftBtn, "PreviewMouseLeftButtonDown");
ShiftUp = Observable.FromEventPattern(ShiftBtn, "PreviewMouseLeftButtonUp");

ShiftClickedEvent = ShiftDown.Select(_ => ShiftUp.TakeUntil(Observable.Timer(TimeSpan.FromMilliseconds(250))))
            .Switch()
            .StartWith(new object());

ShiftHeldEvent = ShiftDown.Select(_ => Observable.Timer(TimeSpan.FromMilliseconds(1000)).TakeUntil(ShiftUp))
            .Switch()
            .StartWith(0);

IObservable<bool> ShiftState= Observable.CombineLatest(ShiftClickedEvent, ShiftHeldEvent,  (x, y) => new object())
            .Scan(false, (currentState, z) => !currentState)
            .StartWith(false)
            .DistinctUntilChanged();

只是想弄清楚我离基准有多远。感谢任何帮助。

编辑

最终换档并以不同的方式处理它。这完成了我最初想要做的事情,也使我更容易实现一些其他想法。仍然可以接受任何建议,但这是新代码:

public MainWindow()
{
    InitializeComponent();
    this.DataContext = this;
    ShiftState = Observable.FromEventPattern(ShiftButton, "Click")
        .Select(_ => "shift");
    ShiftHoldState = Observable.FromEventPattern(ShiftButton, "MouseRightButtonDown")
        .Select(_ => "lock");
    CtrlState = Observable.FromEventPattern(CtrlButton, "Click")
        .Select(_ => "ctrl");
    PosState = Observable.FromEventPattern(POSButton, "Click")
        .Select(_ => "pos");

    KeyPress = Observable.Merge(
        FindLogicalChildren<HMKEnglishKey>(this).Select(
            o => Observable.FromEventPattern<RoutedEventHandler, RoutedEventArgs>(
                h => o.Click += h,
                h => o.Click -= h
                )
                .Select(_ => "default")
            ));

    ModState = Observable.Merge(ShiftState, PosState, CtrlState, ShiftHoldState, KeyPress)
            .Scan("default" , (prev, current) => UpdateMods(prev, current))
            .StartWith("default")
            .DistinctUntilChanged();

    TestButton.Init();
}

private string UpdateMods(string prev, string current)
{
    string returnVal =
        (prev == "lock" && current == "default") ? "lock"
        : (prev == "lock" && current == "shift") ? "default"
        : prev == current ? "default" : current;
    return returnVal;
}

*注意-事实证明Windows 10触摸屏保持被认为是鼠标右键单击,这就是为什么我能够使用它来模仿长时间保持的原因。我可能仍会修改旧的想法以使其与鼠标兼容,但现在可以使用了。

1 个答案:

答案 0 :(得分:0)

最终采用了另一种方法,请参阅后文中的修订代码