Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining when a WPF window is being moved

I'm working on a class derived from the WPF Window class that behaves as an application toolbar window called AppBarWindow. I have been able to find various WinForms implementations, but no WPF implementations.

I've got a lot of the code working, but I need to know when the user starts dragging the window around the screen and when they stop, as the window's behavior will differ. The default WPF handling isn't quite right, so I've implemented my own Window Procedure and installed it using an HwndSource object.

I've got this working in an application at work that does not have a non-client area. In that case, there's a LeftMouseButtonDown event handler that sets a flag to true, then calls the DragMove method which drags the window around. When that method returns, I set the flag to false. Everything works.

But I'm working now on a general class that won't use the DragMove method. I can add another LeftMouseButtonDown handler for the window, but I don't believe that will get called if the mouse is in the non-client area.

How am I going to detect that the user is dragging the window and when they've stopped in this case?

like image 436
Tony Vitabile Avatar asked Aug 31 '13 20:08

Tony Vitabile


3 Answers

I've found what I needed to know by monitoring the messages sent to my window from Win32 while dragging it.

In short, Windows sends the following message when the window starts to move:

WM_ENTERSIZEMOVE

Next, Windows sends the following messages to my window procedure in sequence:

  • WM_MOVING
  • WM_WINDOWPOSCHANGING
  • WM_GETMINMAXINFO
  • WM_WINDOWPOSCHANGED
  • WM_MOVE

These are followed with a message whose code is 0xc310. This is not documented anywhere, so I'm guessing this is used internally by .NET / WPF.

These 6 messages are sent repeatedly as the mouse moves and the window follows after it.

Finally, when you release the left mouse button, Windows sends:

  • WM_EXITSIZEMOVE

So I need to listen for the WM_ENTERSIZEMOVE and WM_EXITSIZEMOVE messages.

like image 192
Tony Vitabile Avatar answered Nov 03 '22 17:11

Tony Vitabile


wont Window.LocationChanged event help you in this case.

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

like image 45
Nitin Avatar answered Nov 03 '22 17:11

Nitin


As Tony points out, there are a few windows messages involved in window dragging. Here's an enum that might help:

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
}
like image 2
Drew Noakes Avatar answered Nov 03 '22 16:11

Drew Noakes