我有一个WPF窗口,我想确定何时用户在桌面上移动一个窗口。我连接到LocationChanged事件,这很好,但我无法弄清楚如何确定用户何时停止移动窗口(通过释放鼠标左键)。WPF窗口LocationChanged结束
没有事件可以帮助我确定类似于LocationChangedEnded事件的事件。我尝试连接到MouseLeftButtonUp,但该事件永远不会被解雇。
任何人有任何想法?
我有一个WPF窗口,我想确定何时用户在桌面上移动一个窗口。我连接到LocationChanged事件,这很好,但我无法弄清楚如何确定用户何时停止移动窗口(通过释放鼠标左键)。WPF窗口LocationChanged结束
没有事件可以帮助我确定类似于LocationChangedEnded事件的事件。我尝试连接到MouseLeftButtonUp,但该事件永远不会被解雇。
任何人有任何想法?
两种可能的方法是:
你真的不知道什么时候鼠标按钮上升。而是等待窗口停止发送这些移动事件。设置一个短暂的计时器,每当您收到一个窗口移动事件时就开始计时。如果它已经打开,重置定时器。当您收到定时器事件时,例如几百毫秒后,你可以假设用户停止移动窗口。即使使用高分辨率鼠标,当按住鼠标左键并试图保持静止时,抖动仍将继续发送移动事件。这种方法记录在here。
尝试从窗口的非客户端区域捕获鼠标通知。您可以设置一个window message hook来捕获窗口消息。一旦看到第一个窗口移动事件,钩子就可以开始查找WM_NCLBUTTONUP事件。这种方法避免了计时器和猜测。但是,它对Windows允许用户定位窗口的方式进行了假设,并且在某些情况下可能会失败,例如,如果用户只用键盘移动用户(Alt + Space,M,箭头键)。
你想要得到的WM_WINDOWPOSCHANGED消息,它添加到您的窗口类:
internal enum WM
{
WINDOWPOSCHANGING = 0x0047,
}
[StructLayout(LayoutKind.Sequential)]
internal struct WINDOWPOS
{
public IntPtr hwnd;
public IntPtr hwndInsertAfter;
public int x;
public int y;
public int cx;
public int cy;
public int flags;
}
private override void OnSourceInitialized(EventArgs ea)
{
HwndSource hwndSource = (HwndSource)HwndSource.FromVisual((Window)this);
hwndSource.AddHook(DragHook);
}
private static IntPtr DragHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled)
{
switch ((WM)msg)
{
case WM.WINDOWPOSCHANGED:
{
WINDOWPOS pos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
if ((pos.flags & (int)SWP.NOMOVE) != 0)
{
return IntPtr.Zero;
}
Window wnd = (Window)HwndSource.FromHwnd(hwnd).RootVisual;
if (wnd == null)
{
return IntPtr.Zero;
}
// ** do whatever you need here **
// the new window position is in the pos variable
// just note that those are in Win32 "screen coordinates" not WPF device independent pixels
}
break;
}
return IntPtr.Zero;
}
您可以监听WM_ENTERSIZEMOVE事件,它应该只火当移动开始。当用户拖动时,您可能会收到WM_MOVING和WM_MOVE事件。后者取决于他们的系统设置(例如窗口随着拖动而移动,而不是拖动轮廓)。最后,WM_EXITSIZEMOVE会指出它们何时完成。
您可能感兴趣的,我已经张贴在这里的答案:
How do you disable Aero Snap in an application?
答案包含一个可靠的方法来检测的禁用Aero对齐的目的窗口移动开始/结束。