2013-04-14 12 views
8

Mam okno bez tytułu, ponieważ chciałem stworzyć własny styl okna.Jak sprawdzić, czy okno jest przeciągane C# WPF

Przyciski tytuł i zminimalizuj, zmaksymalizuj i zamknij znajdują się w panelu dokowania. Dodałem następującą procedurę obsługi zdarzeń, aby zmaksymalizować, przywrócić i przeciągnąć okno.

Problem pojawia się, gdy okno jest zmaksymalizowane.

To, co znalazłem, to to, że za każdym razem jedno kliknięcie tytułu zostaje przywrócone. Kiedy chcę tylko, żeby został przywrócony, jeśli zostanie podwójnie kliknięty lub przeciągnięty. Rozumiem, dlaczego tak się dzieje, ale nie wiem, jak rozwiązać ten problem.

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

Wraz z tej klasy:

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

I to wypracować granice bieżącego ekranu.

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

można dodać odpowiedź następnie oznaczyć je po 2 dniach będzie to lepszy sposób. możesz dostać do niego upvotes :). – Star

+0

Dzięki za napiwek! @Star – Hank

+3

Hank, skopiuj aktualizację do odpowiedzi, a otrzymasz ode mnie propozycję odpowiedzi na pytanie i odpowiedź. –

Odpowiedz

3

Jest elementem WPF (kontrola) o nazwie Thumb, że mogę używać do tworzenia przeciągnij stanie części. Ma zdarzenie DragDelta, które można wykorzystać do zbadania HorizontalOffset i VerticalOffset części możliwej do przeciągnięcia. Możesz zapisać poprzednie wartości i sprawdzić, czy nowe wartości są takie same lub zmienione; co oznacza, że ​​jest przeciągany.

(Tylko sugestia, która działała dla mnie).

+0

Dzięki @Kaveh, zdecydowanie wykorzystam to, aby udoskonalić to, co zrobiłem! – Hank

1

Dobrze, więc może ktoś uzna to za pomocne.

Zmieniłem wszystko, aby rozpoznać przeciągnięcie w dwóch zdarzeniach w zdarzeniach MouseMove i MouseLeftButtonDown.

MouseLeftButtonDown przechwytuje możliwą pozycję początkową dla przeciągania w 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(); 
      } 
     } 

    } 

Oto zmodyfikowana klasa:

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); 
    } 
} 
Powiązane problemy