WPF WindowChanged Window Completed

I have a WPF window and I want to determine when the user has finished moving the window on the desktop. I connected to the LocationChanged event and it’s fine, but I can’t figure out how to determine when the user stops moving the window (releasing the left mouse button).

There is no event to help me define this, something like the LocationChangedEnded event. I tried connecting to MouseLeftButtonUp, but this event never fires.

Does anyone have any idea?

+6
wpf
source share
4 answers

Two possible approaches are possible:

  • You really don't know when the mouse button is up. Instead, you wait until the window stops sending these move events. Set a short timer that starts ticking every time you receive a window move event. Reset timer if it is already on. When you get a timer event, for example. after a few hundred milliseconds, you can assume that the user has stopped moving the window. Even with a high-resolution mouse, holding the left mouse button and trying to stay still, the jitter will continue to send movement events. This approach is documented here .

  • Trying to capture mouse notifications from a non-client area of ​​the window. You can configure the error message window to capture window messages. After viewing the events of the first window, the hook can start searching for WM_NCLBUTTONUP events. This approach avoids the timer and guessing. However, he makes assumptions about how Windows allows the user to position windows and may fail in some cases, for example. if the user moves the user only from the keyboard (Alt + Space, M, arrow keys).

+6
source share

You can listen to the WM_ENTERSIZEMOVE event, which should fire only when the move starts. While dragging, you can receive WM_MOVING and WM_MOVE events. The latter depends on their system settings (for example, the window moves as you drag it, but simply drags the outline). Finally, WM_EXITSIZEMOVE will indicate when they will be done.

+1
source share

If you want to receive the WM_WINDOWPOSCHANGED message, add this to your Window class:

internal enum WM { WINDOWPOSCHANGING = 0x0047, } [StructLayout(LayoutKind.Sequential)] internal struct WINDOWPOS { public IntPtr hwnd; public IntPtr hwndInsertAfter; public int x; public int y; public int cx; public int cy; public int flags; } private override void OnSourceInitialized(EventArgs ea) { HwndSource hwndSource = (HwndSource)HwndSource.FromVisual((Window)this); hwndSource.AddHook(DragHook); } private static IntPtr DragHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handeled) { switch ((WM)msg) { case WM.WINDOWPOSCHANGED: { WINDOWPOS pos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS)); if ((pos.flags & (int)SWP.NOMOVE) != 0) { return IntPtr.Zero; } Window wnd = (Window)HwndSource.FromHwnd(hwnd).RootVisual; if (wnd == null) { return IntPtr.Zero; } // ** do whatever you need here ** // the new window position is in the pos variable // just note that those are in Win32 "screen coordinates" not WPF device independent pixels } break; } return IntPtr.Zero; } 
0
source share

You may be interested in the answer I wrote here:

How to disable Aero Snap in the application?

The answer provides a reliable way to detect the start / end of window movement in order to disable Aero snap.

0
source share

All Articles