C# 确定移动WPF窗口的时间

C# 确定移动WPF窗口的时间,c#,wpf,windows,window,C#,Wpf,Windows,Window,我正在处理一个派生自WPF窗口类的类,该类充当名为AppBarWindow的应用程序工具栏窗口。我已经能够找到各种WinForms实现,但没有WPF实现 我有很多代码在工作,但我需要知道用户何时开始在屏幕上拖动窗口,何时停止,因为窗口的行为会有所不同。默认的WPF处理不太正确,因此我实现了自己的窗口过程,并使用HwndSource对象安装了它 我在一个没有非客户端区域的应用程序中实现了这一点。在这种情况下,有一个LeftMouseButtonDown事件处理程序将标志设置为true,然后调用拖动

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

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

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

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


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

不会
窗口。LocationChanged
事件在这种情况下会帮助您


通过在拖动窗口的同时监视从Win32发送到窗口的消息,我找到了需要知道的内容

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

WM_ENTERSIZEMOVE

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

  • WM_移动
  • WM_窗口位置更改
  • WM_GETMINMAXINFO
  • WM_WINDOWPOSCHANGED
  • WMU移动
随后是一条代码为0xc310的消息。这在任何地方都没有文档记录,所以我猜这是由.NET/WPF内部使用的

当鼠标移动时,这6条消息会被重复发送,窗口也会跟着移动

最后,当您松开鼠标左键时,Windows将发送:

  • WM_EXITSIZEMOVE

因此,我需要监听WM_ENTERSIZEMOVE和WM_EXITSIZEMOVE消息。

正如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
}
内部枚举窗口消息
{
///在移动窗口后发送。
WM_MOVE=0x0003,
/// 
///当窗口的大小或位置即将更改时发送到窗口。
///应用程序可以使用此消息覆盖窗口的默认最大化大小和位置,
///或其默认的最小或最大跟踪大小。
/// 
WM_GETMINMAXINFO=0x0024,
/// 
///发送到一个窗口,其大小、位置或Z顺序中的位置将因此而改变
///调用SetWindowPos函数或其他窗口管理函数。
/// 
WM_WINDOWPOSCHANGING=0x0046,
/// 
///发送到一个窗口,该窗口的大小、位置或Z顺序中的位置由于
///调用SetWindowPos函数或其他窗口管理函数。
/// 
WM_WINDOWPOSCHANGED=0x0047,
/// 
///发送到用户正在移动的窗口。通过处理此消息,应用程序可以监视
///拖动矩形的位置,如果需要,更改其位置。
/// 
WM_移动=0x0216,
/// 
///在进入移动或调整大小模式循环后发送一次到窗口。窗口进入
///当用户单击窗口的标题栏或调整边框时移动或调整模式循环的大小,或
///当窗口将WM_SYSCOMMAND消息传递给DefWindowProc函数和wParam时
///消息的参数指定SC_移动或SC_大小值。操作完成
///当DefWindowProc返回时。
/// 
///无论是否拖动整个窗口,系统都会发送WM_ENTERSIZEMOVE消息
///已启用。
/// 
WM_ENTERSIZEMOVE=0x0231,
/// 
///一旦退出移动或调整大小模式循环,将发送一次到窗口。窗口将进入
///当用户单击窗口的标题栏或调整边框时移动或调整模式循环的大小,或
///当窗口将WM_SYSCOMMAND消息传递给DefWindowProc函数和
///消息的wParam参数指定SC_移动或SC_大小值。操作为
///DefWindowProc返回时完成。
/// 
WM_EXITSIZEMOVE=0x0232
}

不,不会。正如我在问题中所说,“默认的WPF处理不太正确,因此我实现了自己的窗口过程。”我需要在该级别进行处理<代码>窗口。更改的位置在此过程中太晚了。我需要在WPF获取消息之前对其进行处理。我需要此事件在移动包含WPF的窗口时关闭弹出控件。这个活动对我很有效,因为我可以看到弹出窗口及时关闭。