确定何时移动WPF窗口

我正在从派生WPF Window类的行为作为应用程序工具栏窗口称为AppBarWindow 。 我已经能够find各种WinForms实现,但没有WPF实现。

我有很多的代码工作,但我需要知道当用户开始拖动窗口周围的窗口,当他们停止,因为窗口的行为将有所不同。 默认的WPF处理不太正确,所以我实现了我自己的Window Procedure,并使用HwndSource对象进行安装。

我在一个没有非客户区域的应用程序中工作。 在这种情况下,有一个LeftMouseButtonDown事件处理程序将标志设置为true,然后调用拖动窗口的DragMove方法。 当该方法返回时,我将该标志设置为false。 一切正常。

但是我现在正在使用一个不使用DragMove方法的普通类。 我可以为该窗口添加另一个LeftMouseButtonDown处理程序,但是我不相信如果鼠标位于非客户区域,则会被调用。

我如何检测到用户正在拖动窗口,以及在这种情况下何时停止?

通过监视从Win32发送到我的窗口的消息,同时拖动它,我发现我需要知道的。

简而言之,Windows在窗口开始移动时发送以下消息:

WM_ENTERSIZEMOVE

接下来,Windows按顺序将以下消息发送到我的窗口过程:

  • WM_MOVING
  • WM_WINDOWPOSCHANGING
  • WM_GETMINMAXINFO
  • WM_WINDOWPOSCHANGED
  • WM_MOVE

这些后面是一条消息,其代码是0xc310。 这没有记录在任何地方,所以我猜这是由.NET / WPF内部使用。

这6条消息随着鼠标的移动而重复发送,窗口跟在后面。

最后,当您释放鼠标左键时,Windows将发送:

  • WM_EXITSIZEMOVE

所以我需要听WM_ENTERSIZEMOVE和WM_EXITSIZEMOVE消息。

不会Window.LocationChanged事件帮助你在这种情况下。

http://msdn.microsoft.com/en-us/library/system.windows.window.locationchanged.aspx

正如Tony所指出的那样,在窗口拖动中有几个窗口消息。 这是一个枚举,可能有所帮助:

 internal enum WindowsMessage { /// <summary>Sent after a window has been moved.</summary> WM_MOVE = 0x0003, /// <summary> /// Sent to a window when the size or position of the window is about to change. /// An application can use this message to override the window's default maximized size and position, /// or its default minimum or maximum tracking size. /// </summary> WM_GETMINMAXINFO = 0x0024, /// <summary> /// Sent to a window whose size, position, or place in the Z order is about to change as a result /// of a call to the SetWindowPos function or another window-management function. /// </summary> WM_WINDOWPOSCHANGING = 0x0046, /// <summary> /// Sent to a window whose size, position, or place in the Z order has changed as a result of a /// call to the SetWindowPos function or another window-management function. /// </summary> WM_WINDOWPOSCHANGED = 0x0047, /// <summary> /// Sent to a window that the user is moving. By processing this message, an application can monitor /// the position of the drag rectangle and, if needed, change its position. /// </summary> WM_MOVING = 0x0216, /// <summary> /// Sent once to a window after it enters the moving or sizing modal loop. The window enters the /// moving or sizing modal loop when the user clicks the window's title bar or sizing border, or /// when the window passes the WM_SYSCOMMAND message to the DefWindowProc function and the wParam /// parameter of the message specifies the SC_MOVE or SC_SIZE value. The operation is complete /// when DefWindowProc returns. /// <para /> /// The system sends the WM_ENTERSIZEMOVE message regardless of whether the dragging of full windows /// is enabled. /// </summary> WM_ENTERSIZEMOVE = 0x0231, /// <summary> /// Sent once to a window once it has exited moving or sizing modal loop. The window enters the /// moving or sizing modal loop when the user clicks the window's title bar or sizing border, or /// when the window passes the WM_SYSCOMMAND message to the DefWindowProc function and the /// wParam parameter of the message specifies the SC_MOVE or SC_SIZE value. The operation is /// complete when DefWindowProc returns. /// </summary> WM_EXITSIZEMOVE = 0x0232 }