代码之家  ›  专栏  ›  技术社区  ›  edfoh

WPF窗口位置已更改结束

wpf
  •  6
  • edfoh  · 技术社区  · 17 年前

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

    没有任何事件可以帮助我确定这一点,比如位置改变事件。我试着和MouseLeftButtonUp搭讪,但那件事从来没有发生过。

    有人有什么想法吗?

    4 回复  |  直到 17 年前
        1
  •  7
  •   Oren Trutner    17 年前

    两种可能的办法是:

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

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

        2
  •  1
  •   CodeNaked    17 年前

    WM_ENTERSIZEMOVE 事件,该事件应仅在移动开始时激发。当用户拖动时,您可能会收到WM_移动和WM_移动事件。后者取决于其系统设置(例如,窗口在拖动时移动,而不是仅拖动轮廓)。最后,WM_EXITSIZEMOVE将指示何时完成这些操作。

        3
  •  0
  •   Nir    17 年前

    要获取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;
    }
    
        4
  •  0
  •   Community Mohan Dere    9 年前

    您可能对我在这里发布的答案感兴趣:

    How do you disable Aero Snap in an application?