6

我正在研究一个派生自 WPFWindow类的类,该类充当名为AppBarWindow. 我已经能够找到各种 WinForms 实现,但没有 WPF 实现。

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

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

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

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

4

3 回答 3

8

通过在拖动窗口时监视从 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 消息。

于 2013-09-01T00:26:25.777 回答
2

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

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

于 2013-08-31T20:31:58.867 回答
2

正如托尼指出的那样,窗口拖动涉及一些窗口消息。这是一个可能有帮助的枚举:

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
}
于 2016-10-08T20:50:41.033 回答