2013-08-31 106 views
4

我正在研究WPF Window類派生的類,該類的行爲與名爲AppBarWindow的應用程序工具欄窗口類似。我已經能夠找到各種WinForms實現,但沒有WPF實現。確定何時移動WPF窗口

我有很多代碼可以工作,但我需要知道用戶什麼時候開始在屏幕上拖動窗口以及何時停止,因爲窗口的行爲會有所不同。默認的WPF處理不太正確,所以我實現了我自己的Window Procedure並使用HwndSource對象進行安裝。

我已經在沒有非客戶區的工作應用程序中工作。在這種情況下,有一個LeftMouseButtonDown事件處理程序將標誌設置爲true,然後調用拖動窗口的DragMove方法。當該方法返回時,我將該標誌設置爲false。一切正常。

但我現在正在研究一個不會使用DragMove方法的普通類。我可以爲該窗口添加另一個LeftMouseButtonDown處理程序,但我不相信如果鼠標位於非客戶區域中,將會調用該處理程序。

我該如何檢測到用戶正在拖動窗口,以及在這種情況下何時停止?

回答

5

我發現我需要通過監測的同時拖動它的Win32發送到我的窗口的消息知道。

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

不會Window.LocationChanged事件幫助你在這種情況下。

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

+0

不,它不會。正如我在問題中所說,「默認的WPF處理不太正確,所以我實現了我自己的Window Procedure」。我需要在那個級別進行處理。 'Window.LocationChanged'在這個過程中已經太晚了。我需要在WPF獲取消息之前處理它。 –

1

正如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 
}