2013-04-14 13 views
8

Ho una finestra senza titolo, poiché volevo creare uno stile di finestra per conto mio.Come verificare se una finestra viene trascinata C# WPF

I pulsanti titolo e Riduci a icona, Ingrandisci e Chiudi sono in un pannello del dock. Ho aggiunto il seguente gestore di eventi per massimizzare, ripristinare e trascinare la finestra.

Il problema si presenta quando la finestra è ingrandita.

Quello che ho trovato è che ogni volta che faccio un singolo clic sul titolo viene ripristinato. Quando voglio solo ripristinarlo se viene fatto doppio clic o trascinato. Posso capire perché sta accadendo, ma non so come risolverlo.

public void TITLEBAR_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     DockPanel dp = (DockPanel)sender; 
     Window parentWindow = Window.GetWindow(dp); 
     bool doubleClick = IsDoubleClick(sender, e); 

     if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed && !doubleClick) 
     { 


      if (parentWindow.WindowState == WindowState.Maximized) 
      { 
       double mouseX = e.GetPosition(parentWindow).X; 
       double width = parentWindow.RestoreBounds.Width; 
       System.Drawing.Rectangle screenBounds = getCurrentScreenBounds(parentWindow); 
       double x = screenBounds.Left + (mouseX - ((width/100.00) * ((100.00/screenBounds.Width) * mouseX))); 

       if (x < 0) 
       { 
        x = 0; 
       } 
       else 
       { 
        if (x + width > screenBounds.Left + screenBounds.Width) 
        { 
         x = screenBounds.Left + screenBounds.Width - width; 
        } 
       } 

       parentWindow.Left = x; 
       parentWindow.Top = screenBounds.Top; 
       parentWindow.WindowState = System.Windows.WindowState.Normal; 
      } 

      parentWindow.DragMove(); 
      //MessageBox.Show(""); 
     } 

     if (doubleClick) 
     { 
      if (parentWindow.WindowState == System.Windows.WindowState.Maximized) 
      { 
       parentWindow.WindowState = System.Windows.WindowState.Normal; 
      } 
      else 
      { 
       parentWindow.WindowState = System.Windows.WindowState.Maximized; 
      } 
     } 
    } 

Insieme a questa classe:

public static class MouseButtonHelper 
{ 
    private const long k_DoubleClickSpeed = 500; 
    private const double k_MaxMoveDistance = 10; 

    private static long _LastClickTicks = 0; 
    private static System.Windows.Point _LastPosition; 
    private static WeakReference _LastSender; 

    public static bool IsDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     System.Windows.Point position = e.GetPosition(null); 
     long clickTicks = DateTime.Now.Ticks; 
     long elapsedTicks = clickTicks - _LastClickTicks; 
     long elapsedTime = elapsedTicks/TimeSpan.TicksPerMillisecond; 
     bool quickClick = (elapsedTime <= k_DoubleClickSpeed); 
     bool senderMatch = (_LastSender != null && sender.Equals(_LastSender.Target)); 

     if (senderMatch && quickClick && position.Distance(_LastPosition) <= k_MaxMoveDistance) 
     { 
      // Double click! 
      _LastClickTicks = 0; 
      _LastSender = null; 
      return true; 
     } 

     // Not a double click 
     _LastClickTicks = clickTicks; 
     _LastPosition = position; 
     if (!quickClick) 
      _LastSender = new WeakReference(sender); 
     return false; 
    } 


    private static double Distance(this System.Windows.Point pointA, System.Windows.Point pointB) 
    { 
     double x = pointA.X - pointB.X; 
     double y = pointA.Y - pointB.Y; 
     return Math.Sqrt(x * x + y * y); 
    } 
} 

E questo a lavorare fuori dai limiti dello schermo corrente.

public static class WindowHelper 
{ 
    public static System.Drawing.Rectangle getCurrentScreenBounds(System.Windows.Window pWnd) 
    { 
     System.Windows.Forms.Screen parentScreen = GetCurrentScreen(pWnd); 

     if (parentScreen == null) 
     { 
      return System.Windows.Forms.Screen.PrimaryScreen.Bounds; 
     } 

     return parentScreen.Bounds; 
    } 

    private static System.Windows.Forms.Screen GetCurrentScreen(System.Windows.Window pWnd) 
    { 
     System.Drawing.Rectangle intersectingRect = new System.Drawing.Rectangle(); 
     System.Drawing.Rectangle windowRect = new System.Drawing.Rectangle(Convert.ToInt32(pWnd.Left), Convert.ToInt32(pWnd.Top), Convert.ToInt32(pWnd.Width), Convert.ToInt32(pWnd.Height)); 
     int largestIntersectingArea = 0; 
     System.Windows.Forms.Screen curScreen = null; 

     foreach (System.Windows.Forms.Screen s in System.Windows.Forms.Screen.AllScreens) 
     { 
      if (s.Bounds.IntersectsWith(windowRect)) 
      { 
       intersectingRect = System.Drawing.Rectangle.Intersect(s.Bounds, windowRect); 
       int intersectingArea = intersectingRect.Width * intersectingRect.Height; 
       if (intersectingArea > largestIntersectingArea) 
       { 
        largestIntersectingArea = intersectingArea; 
        curScreen = s; 
       } 
      } 
     } 

     return curScreen; 
    } 
} 
+6

puoi aggiungere la tua risposta allora segnare dopo 2 giorni questo sarà un modo migliore. potresti ottenere voti positivi :) – Star

+0

Grazie per il suggerimento! @Star – Hank

+3

Hank, copia il tuo aggiornamento in una risposta e riceverai un preventivo da parte mia per la tua domanda e la tua risposta. –

risposta

3

V'è un elemento WPF (controllo) di nome Thumb, io uso che per la produzione di pezzi di drag-grado. Ha un evento DragDelta che è possibile utilizzare per esaminare HorizontalOffset e VerticalOffset della parte trascinabile. È possibile salvare i valori precedenti e verificare se i nuovi valori sono uguali o modificati; il che significa che viene trascinato.

(Solo un suggerimento che ha funzionato per me).

+0

Grazie @ Kaveh, userò sicuramente questo per perfezionare quello che ho fatto! – Hank

1

Ok, quindi forse qualcuno troverà utile questo.

Ho modificato le cose in modo che riconosca il trascinamento attraverso due eventi, negli eventi MouseMove e MouseLeftButtonDown.

MouseLeftButtonDown acquisisce una possibile posizione iniziale per il trascinamento in setStartPosition().

public void TITLEBAR_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     DockPanel dp = (DockPanel)sender; 
     Window parentWindow = Window.GetWindow(dp); 
     doubleClick = IsDoubleClick(sender, e); 

     if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed && !doubleClick) 
     { 
      if (parentWindow.WindowState == WindowState.Maximized) 
      { 
       setStartPosition(sender, e); 
      } 
     } 

     if (doubleClick) 
     { 
      if (parentWindow.WindowState == System.Windows.WindowState.Maximized) 
      { 
       parentWindow.WindowState = System.Windows.WindowState.Normal; 
      } 
      else 
      { 
       parentWindow.WindowState = System.Windows.WindowState.Maximized; 
      } 
     } 
    } 

    private void TITLEBAR_MouseMove(object sender, MouseEventArgs e) 
    { 
     DockPanel dp = (DockPanel)sender; 
     Window parentWindow = Window.GetWindow(dp); 

     if (e.LeftButton == MouseButtonState.Pressed) 
     { 
      if (IsDragging(sender, e) && !doubleClick) 
      { 
       if (parentWindow.WindowState == WindowState.Maximized) 
       { 
        double mouseX = e.GetPosition(parentWindow).X; 
        double width = parentWindow.RestoreBounds.Width; 
        System.Drawing.Rectangle screenBounds = getCurrentScreenBounds(parentWindow); 
        double x = screenBounds.Left + (mouseX - ((width/100.00) * ((100.00/screenBounds.Width) * mouseX))); 

        if (x < 0) 
        { 
         x = 0; 
        } 
        else 
        { 
         if (x + width > screenBounds.Left + screenBounds.Width) 
         { 
          x = screenBounds.Left + screenBounds.Width - width; 
         } 
        } 

        parentWindow.Left = x; 
        parentWindow.Top = screenBounds.Top; 
        parentWindow.WindowState = System.Windows.WindowState.Normal; 
       } 

       parentWindow.DragMove(); 
      } 
     } 

    } 

Ecco la classe modificata:

public static class MouseButtonHelper 
{ 
    private const long k_DoubleClickSpeed = 500; 
    private const double k_MaxMoveDistance = 10; 

    private static long _LastClickTicks = 0; 
    private static System.Windows.Point _LastPosition; 
    private static WeakReference _LastSender; 

    private static System.Windows.Point _DragStartPosition; 

    public static bool IsDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     System.Windows.Point position = e.GetPosition(null); 
     long clickTicks = DateTime.Now.Ticks; 
     long elapsedTicks = clickTicks - _LastClickTicks; 
     long elapsedTime = elapsedTicks/TimeSpan.TicksPerMillisecond; 
     bool quickClick = (elapsedTime <= k_DoubleClickSpeed); 
     bool senderMatch = (_LastSender != null && sender.Equals(_LastSender.Target)); 

     if (senderMatch && quickClick && position.Distance(_LastPosition) <= k_MaxMoveDistance) 
     { 
      // Double click! 
      _LastClickTicks = 0; 
      _LastSender = null; 
      return true; 
     } 

     // Not a double click 
     _LastClickTicks = clickTicks; 
     _LastPosition = position; 
     if (!quickClick) 
      _LastSender = new WeakReference(sender); 
     return false; 
    } 

    public static void setStartPosition(object sender, System.Windows.Input.MouseButtonEventArgs e) 
    { 
     _DragStartPosition = e.GetPosition(null); 
    } 

    public static bool IsDragging(object sender, System.Windows.Input.MouseEventArgs e) 
    { 
     System.Windows.Point mousePos = e.GetPosition(null); 
     System.Windows.Vector diff = _DragStartPosition - mousePos; 

     if (Math.Abs(diff.X) > System.Windows.SystemParameters.MinimumHorizontalDragDistance || Math.Abs(diff.Y) > System.Windows.SystemParameters.MinimumVerticalDragDistance) 
     { 
      return true; 
     } 
     return false; 
    } 

    private static double Distance(this System.Windows.Point pointA, System.Windows.Point pointB) 
    { 
     double x = pointA.X - pointB.X; 
     double y = pointA.Y - pointB.Y; 
     return Math.Sqrt(x * x + y * y); 
    } 
} 
Problemi correlati