当我滚动鼠标滚轮时会触发几个MouseWheel事件。我正在使用这些事件来缩放图像。
我希望在一系列MouseWheel
事件结束时调用方法。我怎么知道它们何时结束?
这是我到目前为止的实现
private void ModelWindowBorder_MouseWheel(object sender, MouseWheelEventArgs e)
{
intervaltimer = null;
// Do stuff like zooming and etc
CheckEventInterval()
}
private void CheckEventInterval()
{
intervaltimer = new Stopwatch();
intervaltimer .Start();
if (intervaltimer.ElapsedMilliseconds > 50)
{
// Do some other stuff
}
}
答案 0 :(得分:11)
实际上,由于摩擦轮旋转是无止境的,因此没有特殊事件来通知使用的结束滚动。但是在您的情况下,您可以测试用户是否在短时间内停止滚动。这可以通过一个简单的计时器完成:
//Use dispatcher timer to avoid problems when manipulating UI related objects
DispatcherTimer timer;
float someValue = 0;
public MainWindow()
{
InitializeComponent();
timer = new DispatcherTimer();
timer.Tick += timer_Tick;
timer.Interval = TimeSpan.FromMilliseconds(500 /*Adjust the interval*/);
MouseWheel += MainWindow_MouseWheel;
}
void timer_Tick(object sender, EventArgs e)
{
//Prevent timer from looping
(sender as DispatcherTimer).Stop();
//Perform some action
Console.WriteLine("Scrolling stopped (" + someValue + ")");
//Reset for futher scrolling
someValue = 0;
}
void MainWindow_MouseWheel(object sender, MouseWheelEventArgs e)
{
//Accumulate some value
someValue += e.Delta;
timer.Stop();
timer.Start();
}
正如您所见,MouseWheel事件将启动计时器。如果在计时器触发时发生新的MouseWheel事件,它将重新启动计时器。这样,只有在特定时间间隔内没有车轮事件时,计时器才会启动。
答案 1 :(得分:2)
这是一种替代方法,它允许您指定要检测鼠标滚轮移动和灵敏度的UI元素(例如画布,窗口,控件等),这是以毫秒为单位的超时时间。哪个轮被视为非活动(触发自定义停止事件):
public sealed class MouseWheelMonitor : IDisposable
{
private AutoResetEvent _resetMonitorEvent;
private readonly Dispatcher _dispatcher;
private readonly UIElement _canvas;
private readonly int _sensitivity;
private bool _disposed;
private volatile bool _inactive;
private volatile bool _stopped;
public event EventHandler<MouseWheelEventArgs> MouseWheel;
public event EventHandler<EventArgs> MouseWheelStarted;
public event EventHandler<EventArgs> MouseWheelStopped;
public MouseWheelMonitor(UIElement canvas, int sensitivity)
{
_canvas = canvas;
_canvas.MouseWheel += (s, e) => RaiseMouseWheel(e);
_sensitivity = sensitivity;
_dispatcher = Dispatcher.CurrentDispatcher;
_resetMonitorEvent = new AutoResetEvent(false);
_disposed = false;
_inactive = true;
_stopped = true;
var monitor = new Thread(Monitor) {IsBackground = true};
monitor.Start();
}
private void Monitor()
{
while (!_disposed)
{
if (_inactive) // if wheel is still inactive...
{
_resetMonitorEvent.WaitOne(_sensitivity/10); // ...wait negligibly small quantity of time...
continue; // ...and check again
}
// otherwise, if wheel is active...
_inactive = true; // ...purposely change the state to inactive
_resetMonitorEvent.WaitOne(_sensitivity); // wait...
if (_inactive) // ...and after specified time check if the state is still not re-activated inside mouse wheel event
RaiseMouseWheelStopped();
}
}
private void RaiseMouseWheel(MouseWheelEventArgs args)
{
if (_stopped)
RaiseMouseWheelStarted();
_inactive = false;
if (MouseWheel != null)
MouseWheel(_canvas, args);
}
private void RaiseMouseWheelStarted()
{
_stopped = false;
if (MouseWheelStarted != null)
MouseWheelStarted(_canvas, new EventArgs());
}
private void RaiseMouseWheelStopped()
{
_stopped = true;
if (MouseWheelStopped != null)
_dispatcher.Invoke(() => MouseWheelStopped(_canvas, new EventArgs())); // invoked on cached dispatcher for convenience (because fired from non-UI thread)
}
public void Dispose()
{
if(!_disposed)
{
_disposed = true;
DetachEventHandlers();
if (_resetMonitorEvent != null)
{
_resetMonitorEvent.Close();
_resetMonitorEvent = null;
}
}
}
private void DetachEventHandlers()
{
if (MouseWheel != null)
{
foreach (var handler in MouseWheel.GetInvocationList().Cast<EventHandler<MouseWheelEventArgs>>())
{
MouseWheel -= handler;
}
}
if (MouseWheelStarted != null)
{
foreach (var handler in MouseWheelStarted.GetInvocationList().Cast<EventHandler<EventArgs>>())
{
MouseWheelStarted -= handler;
}
}
if (MouseWheelStopped != null)
{
foreach (var handler in MouseWheelStopped.GetInvocationList().Cast<EventHandler<EventArgs>>())
{
MouseWheelStopped -= handler;
}
}
}
}
使用示例:
var monitor = new MouseWheelMonitor(uiElement, 1000);
monitor.MouseWheel += (s, e) => { Debug.WriteLine("mouse wheel turned"); };
monitor.MouseWheelStarted += (s, e) => { Debug.WriteLine("mouse wheel started"); };
monitor.MouseWheelStopped += (s, e) => { Debug.WriteLine("mouse wheel stopped"); };