简体   繁体   English

如何防止在按下鼠标按钮时发生mousemove事件?

[英]How can I prevent mousemove events while mouse button is pressed?

I got a grid that I want to move mouse over. 我有一个想要将鼠标移到上方的网格。 While I am just hovering and moving mouse I want events to fire, but when I press mousedown they should pause firing. 当我只是悬停和移动鼠标时,我希望事件触发,但是当我按下mousedown时,它们应该暂停触发。 Once I fire mouseup they should continue. 一旦我将mouseup触发,它们应该继续。

If that sounds super easy, it probably isn't. 如果听起来超级简单,那可能并非如此。 After some time we came up with a not very elegant solution, but I wonder whether something better exists. 一段时间后,我们提出了一个不太优雅的解决方案,但我想知道是否存在更好的解决方案。 I won't influence your approach with our hack. 我不会通过我们的hack来影响您的方法。

So initial code that doesn't work 所以初始代码不起作用

mouseMove.TakeUntil(mouseDown).Repeat()

Adding .SkipUntil(mouseUp) left or right to TakeUntil basicly stop above code from working at all. 添加.SkipUntil(mouseUp)向左或向右TakeUntil basicly停止上述代码从所有工作。

How about this: 这个怎么样:

bool mouseIsDown = false;
Observable.Merge(
    mouseDown.Select(_ => true),
    mouseUp.Select(_ => false)
).Subscribe(x => mouseIsDown = x);

mouseMove.Where(_ => !mouseIsDown);

The technically correct answer involves the Window operator, but this is just as good and easier to grok (and easier for me to write) 从技术上讲,正确的答案涉及Window运算符,但这既好又容易理解(对我来说更容易编写)

this could be a posible solution 这可能是一个可能的解决方案

// create the observables
IObservable<Point> mouseMove = Observable.FromEventPattern<MouseEventArgs>(this, "MouseDown")
    .Select(e=>e.EventArgs.GetPosition(this));

IObservable<bool> mouseDown = Observable.FromEventPattern(this, "MouseDown").Select(_ => false);
IObservable<bool> mouseUp = Observable.FromEventPattern(this, "MouseUp").Select(_ => true);

var merged = mouseUp.Merge(mouseDown).StartWith(true);

// sends the moves with the current state of the mouse button
var all = mouseMove.CombineLatest(merged, (move, take) => new {Take = take, Move = move});

// the result is all the points from mouse move where the mouse button isn't pressed
var result = all.Where(t => t.Take).Select(t => t.Move);

Below are 2 possible solutions 以下是2种可能的解决方案

var beh = new BehaviorSubject<bool>(true);
mousedown.Select(_ => false).Subscribe(beh);
mouseup.Select(_ => true).Subscribe(beh);
mousemove.SelectMany(e =>
{
     return mousemove.TakeUntil(beh.Where(b => !b));
}).Subscribe( .... );

OR 要么

var du = mousedown.Select(_ => false).Merge(mouseup.Select(_ => true)).Merge(Observable.Return(true));
mousemove.CombineLatest(du, (ev, b) => new Tuple<MouseEventArgs, bool>(ev.EventArgs, b))
 .Where(t => t.Item2)
 .Select(t => t.Item1)
 .Subscribe(....);

This works: 这有效:

        var mouseMoveWhileUpOnly =
            mouseUp
                .Select(mu =>
                    mouseMove
                        .TakeUntil(mouseDown))
                .Switch();

The only trick you need to do to get the observable started without actually needing to manually do a mouse up is this: 您无需真正手动向上移动鼠标即可启动可观察对象的唯一技巧是:

        var mouseUp = Observable
            .FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(
                h => this.MouseLeftButtonUp += h,
                h => this.MouseLeftButtonUp -= h)
            .Select(ep => Unit.Default)
            .StartWith(Unit.Default);

Note the StartWith . 注意StartWith

Otherwise the mouseDown & mouseMove observables are defined normally. 否则,将正常定义mouseDownmouseMove可观察对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM