确定何时移动WPF窗口

时间:2013-08-31 20:25:53

标签: c# wpf windows window

我正在处理一个派生自WPF Window类的类,该类充当名为AppBarWindow的应用程序工具栏窗口。我已经能够找到各种WinForms实现,但没有WPF实现。

我有很多代码正在运行,但我需要知道用户何时开始在屏幕上拖动窗口以及何时停止,因为窗口的行为会有所不同。默认的WPF处理不太正确,所以我实现了自己的Window Procedure并使用HwndSource对象安装它。

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

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

我如何检测用户是否在拖动窗口以及何时停止这种情况?

3 个答案:

答案 0 :(得分:7)

通过监控从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消息。

答案 1 :(得分:2)

在这种情况下,

不会Window.LocationChanged事件帮助你。

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

答案 2 :(得分:2)

Tony指出,窗口拖动涉及一些Windows消息。这是一个可能有用的枚举:

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
}