WPF窗口LocationChanged结束

时间:2009-07-06 04:10:02

标签: wpf

我有一个WPF窗口,我想确定用户何时完成在桌面上移动窗口。我连接到LocationChanged事件,这很好,但我无法弄清楚如何确定用户何时停止移动窗口(通过释放鼠标左键)。

没有任何事情可以帮助我确定,比如LocationChangedEnded事件。我尝试连接到MouseLeftButtonUp,但该事件永远不会被触发。

任何人都有任何想法?

4 个答案:

答案 0 :(得分:7)

两种可能的方法是:

  1. 您实际上并不知道鼠标按钮何时被抬起。相反,您等待窗口停止发送这些移动事件。设置一个短暂的计时器,每次收到窗口移动事件时都会开始计时。如果计时器已经打开,请重置计时器。当您收到计时器事件时,例如在几百毫秒之后,您可以假设用户停止移动窗口。即使使用高分辨率鼠标,当按住鼠标左键并试图保持静止时,抖动将继续发送移动事件。这种方法记录在案here

  2. 尝试从窗口的非客户区域捕获鼠标通知。您可以设置window message hook来捕获窗口消息。一旦看到第一个窗口移动事件,钩子就可以开始寻找WM_NCLBUTTONUP事件。这种方法避免了计时器和猜测。但是,它假设Windows允许用户定位窗口的方式,并且在某些情况下可能会失败,例如,如果用户仅使用键盘移动用户(Alt + Space,M,箭头键)。

答案 1 :(得分:1)

您可以收听WM_ENTERSIZEMOVE事件,该事件只应在移动开始时触发。当用户拖动时,您可能会收到WM_MOVING和WM_MOVE事件。后者取决于他们的系统设置(例如,窗口在拖动时移动,而不是仅拖动轮廓)。最后,WM_EXITSIZEMOVE将指示它们何时完成。

答案 2 :(得分:0)

您想要获取WM_WINDOWPOSCHANGED消息,将其添加到您的Window类中:

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;
}

答案 3 :(得分:0)

您可能对我在此处发布的答案感兴趣:

How do you disable Aero Snap in an application?

答案包含一种可靠的方法来检测窗口移动的开始/结束,以便禁用Aero snap。