我正试图在窗口处理WPF的SizeChanged
事件时跳过一些箍。我有一些我需要执行的自定义代码在用户完成窗口大小调整之后,遗憾的是没有我能够遇到的事件因此我创建了一个使用Reactive Extensions进行限制的解决方案SizeChange事件:
IObservable<SizeChangedEventArgs> ObservableSizeChanges = Observable
.FromEventPattern<SizeChangedEventArgs>(this, "SizeChanged")
.Select(x => x.EventArgs)
.Throttle(TimeSpan.FromMilliseconds(200));
IDisposable SizeChangedSubscription = ObservableSizeChanges
.ObserveOn(SynchronizationContext.Current)
.Subscribe(x => {
Size_Changed(x);
});
基本上这样做可以确保在调用我的自定义代码之前,必须经过200毫秒没有SizeChanged事件。这工作正常但是我遇到了一个问题,如果用户拖动窗口句柄并继续按住鼠标按钮,代码仍然会被执行。我希望能够确保在鼠标按钮关闭时执行自定义代码 。我尝试插入PreviewMouseLeftButtonDown
,但是当单击窗口句柄时,只有在窗口框架内单击鼠标时才会触发它。是否有任何类似的事件我可以插入鼠标,适用于窗口句柄?或者,任何人都可以为我遇到的问题想出合适的解决方法吗?
答案 0 :(得分:2)
Windows发送一条专用消息,通知窗口模态大小/移动循环已退出。 WM_EXITSIZEMOVE,当用户放开鼠标按钮或按Escape时触发。但是,是的,WPF不公开它。谷歌“wpf wm_exitsizemove”找到你想要的互操作代码。好看的热门是this blog post
答案 1 :(得分:1)
这可能有些过分,但要专门解决“如何判断鼠标按钮是否关闭?”问题,看看这个P / Invoke包装器:
public class ButtonObserver : IDisposable
{
public struct MouseButtons
{
public bool LeftButton;
public bool RightButton;
}
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(int vKey);
private const int VK_LBUTTON = 0x01;
private const int VK_RBUTTON = 0x02;
private Task _pollTask = null;
private Subject<MouseButtons> _pollBuffer = new Subject<MouseButtons>();
private CancellationTokenSource _canceller;
public IObservable<MouseButtons> PollMouse(int pollDelayMs)
{
if(_pollTask == null)
{
_canceller = new CancellationTokenSource();
_pollTask = Task.Factory.StartNew(() =>
{
while(!_canceller.IsCancellationRequested)
{
var mbLeft = GetAsyncKeyState(VK_LBUTTON) != 0;
var mbRight = GetAsyncKeyState(VK_RBUTTON) != 0;
_pollBuffer.OnNext(new MouseButtons{ LeftButton = mbLeft, RightButton = mbRight});
Thread.Sleep(pollDelayMs);
}
});
}
return _pollBuffer;
}
public void Dispose()
{
_canceller.Cancel();
_pollTask.Wait();
_pollTask = null;
}
}
您可以将其用作:
void Main()
{
var buttonObs = new ButtonObserver();
var buttons = buttonObs.PollMouse(100).Where(mb => mb.LeftButton);
using(buttons.Subscribe(mb => Console.WriteLine("Left button down")))
{
Console.ReadLine();
}
buttonObs.Dispose();
}