首页 > 解决方案 > 使用 RX.Net 的移动键盘“Shift”切换类似功能

问题描述

从事一个项目,我需要在移动键盘上模拟“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 触摸屏保持被认为是鼠标右键单击,这就是为什么我能够使用它来模仿长时间保持。我可能仍然会修改旧想法以使其与鼠标兼容,但现在它可以工作。

标签: c#system.reactiverx.net

解决方案


最终采用了不同的方法,请参阅帖子中的修订代码


推荐阅读