2009-07-06 16 views
6

Ich habe ein WPF-Fenster, und ich möchte, um zu bestimmen, wenn ein Benutzer beendet ein Fenster um auf dem Desktop bewegen. Ich hakte an dem Location Ereignis und das ist in Ordnung, aber ich kann nicht herausfinden, wie zu bestimmen, wann der Benutzer aufhört, um das Fenster zu bewegen (indem Sie die linke Maustaste loslassen).WPF Fenster Location beendet

Es gibt keinen Fall, mir zu helfen, die bestimmen, so etwas wie ein LocationChangedEnded Ereignis. Ich habe versucht, mich mit MouseLeftButtonUp zu verbinden, aber dieses Ereignis wird nie ausgelöst.

Wer hat irgendwelche Ideen?

Antwort

6

Zwei mögliche Ansätze wäre:

  1. Sie wissen nicht wirklich, wenn die Maustaste ausgelöst wird. Stattdessen warten Sie, bis das Fenster die Übertragungsereignisse nicht mehr sendet. Richten Sie einen kurzlebigen Timer ein, der jedes Mal neu startet, wenn Sie ein Fensterbewegungsereignis erhalten. Setzen Sie den Timer zurück, wenn er bereits eingeschaltet ist. Wenn Sie das Timer-Ereignis empfangen, z. Nach einigen hundert Millisekunden könnten Sie davon ausgehen, dass der Benutzer das Fenster nicht mehr bewegt. Selbst bei einer Maus mit hoher Auflösung, wenn die linke Maustaste gedrückt wird und versucht wird, ruhig zu bleiben, sendet der Jitter weiterhin Bewegungsereignisse. Dieser Ansatz ist dokumentiert here.

  2. Versuch Maus Benachrichtigungen vom Nicht-Client-Bereich des Fensters zu erfassen. Sie könnten eine window message hook einrichten, um Fenstermeldungen zu erfassen. Sobald das erste Fensterbewegungsereignis gesehen wird, kann der Hook nach WM_NCLBUTTONUP-Ereignissen suchen. Dieser Ansatz vermeidet den Timer und das Raten. Es trifft jedoch Annahmen über die Möglichkeiten, wie Windows dem Benutzer ermöglicht, Fenster zu positionieren, und kann in einigen Fällen fehlschlagen, z. wenn der Benutzer den Benutzer nur mit der Tastatur bewegt (Alt + Leertaste, M, Pfeiltasten).

0

Sie wollen die WM_WINDOWPOSCHANGED Nachricht erhalten, fügen Sie diese zu Ihrer Window-Klasse:

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

Sie können für die WM_ENTERSIZEMOVE Ereignis hören, die sollte nur Feuer, wenn die Bewegung gestartet wird. Während der Benutzer zieht, können Sie WM_MOVING- und WM_MOVE-Ereignisse erhalten. Letzteres hängt von den Systemeinstellungen ab (z. B. bewegt sich das Fenster beim Ziehen, anstatt nur einen Umriss zu ziehen). Schließlich würde WM_EXITSIZEMOVE anzeigen, wenn sie fertig sind.

0

können Sie in der Antwort interessiert sein, dass ich hier gepostet habe:

How do you disable Aero Snap in an application?

Die Antwort enthält einen zuverlässigen Weg, um die Start/Ende des Fensters bewegt sich zum Zweck der Deaktivierung Aero Snap zu erkennen.