2009-07-06 8 views
6

Tengo una ventana WPF y quiero determinar cuándo un usuario termina de mover una ventana en el escritorio. Me conecté al evento LocationChanged y está bien, pero no sé cómo determinar cuándo el usuario deja de mover la ventana (soltando el botón izquierdo del mouse).Ubicación de ventana de WPFCambio finalizado

No hay ningún evento que me ayude a determinarlo, algo así como un evento LocationChangedEnded. Intenté conectarme a MouseLeftButtonUp, pero ese evento nunca se dispara.

¿Alguien tiene alguna idea?

Respuesta

6

dos enfoques posibles serían:

  1. No se sabe muy bien cuando se eleva el botón del ratón. En cambio, esperas a que la ventana deje de enviar esos eventos de movimiento. Configure un temporizador de corta duración que comience a funcionar cada vez que reciba un evento de movimiento de ventana. Restablece el temporizador si ya está encendido. Cuando recibe el evento del temporizador, p. después de unos cientos de milisegundos, podría suponer que el usuario dejó de mover la ventana. Incluso con un mouse de alta resolución, al mantener presionado el botón izquierdo del mouse e intentar permanecer quieto, el jitter seguirá enviando eventos de movimiento. Este enfoque está documentado here.

  2. Intenta capturar las notificaciones del mouse desde el área no cliente de la ventana. Puede configurar un window message hook para capturar mensajes de ventana. Una vez que se ve el primer movimiento de movimiento de ventana, el gancho podría comenzar a buscar eventos WM_NCLBUTTONUP. Este enfoque evita el temporizador y la adivinación. Sin embargo, hace suposiciones sobre las formas en que Windows permite al usuario ubicar ventanas, y puede fallar en algunos casos, p. si el usuario mueve al usuario solo con el teclado (Alt + Espacio, M, teclas de flecha).

0

Quiere recibir el mensaje WM_WINDOWPOSCHANGED, agregar esto a su clase Window:

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; 
} 
1

Puede detectar el evento WM_ENTERSIZEMOVE, que sólo debe fuego cuando se inicia el movimiento. Mientras el usuario está arrastrando, puede recibir eventos WM_MOVING y WM_MOVE. Esto último depende de la configuración de su sistema (por ejemplo, la ventana se mueve a medida que arrastra, en lugar de arrastrar un contorno). Finalmente, WM_EXITSIZEMOVE indicará cuándo terminaron.

Cuestiones relacionadas