2016-06-16 30 views
2

Ich mache ein Programm, um Screenshot zu machen. Die Funktionalität ist identisch mit dem Windows Snipping Tool. Der Benutzer definiert den Bereich, indem er ein Rechteck auf dem Bildschirm zeichnet und eine Aufnahme macht.Verzögerung bei der Aufnahme Screenshot von Desktop C# (WPF)

Ich folgte diesem eine erstaunliche tutorial, wie das Öffnen eines neuen Fensters durch Abdeckung des gesamten Desktops. Dann zeichne ich ein Rechteck auf Fenster und mache einen Schuss innerhalb des Rechtecks. Wenn die Maus normal bewegt wird, wird der Screenshot korrekt aufgenommen. Wie dieses Bild

enter image description here

Aber, wenn die Maus schneller bewegt wird, wird Screenshot falsch wie in Abbildung unten genommen. Schuss aus Rechteckbereich genommen

Shot is taken out of rectangle area

Hier Quellcode:

public partial class CapturingArea : Window 
{ 

    public BitmapSource mTakenScreenShot; 
    private Point   mStartPoint; 
    private Point   mEndPoint;     
    private Rectangle  mDrawRectangle;  

    public CapturingArea() 
    { 
     InitializeComponent(); 
     InitMainWindow();    
     Mouse.OverrideCursor = Cursors.Cross; 

     mStartPoint = new Point(); 
     mEndPoint = new Point();    
    }  

    /*Close Window by pressing ESC Button*/ 
    private void Window_KeyUp(object sender, KeyEventArgs e) 
    { 
     if (e.Key == Key.Escape) 
     { 
      Mouse.OverrideCursor = Cursors.Arrow; 
      this.Close();     
     } 
    }   

    /*When Mouse is clicked 
    get the current point of Mouse and Start Drawing Rectangle on the Canvas*/ 
    private void cnDrawingArea_MouseDown(object sender, MouseButtonEventArgs e) 
    {    
     if(mDrawRectangle != null) 
      this.cnDrawingArea.Children.Remove(mDrawRectangle); 

     mStartPoint = e.GetPosition(this);     

     mDrawRectangle = new Rectangle 
     { 
      Stroke = Brushes.Red, 
      StrokeThickness = 0.5 
     }; 

     Canvas.SetLeft(mDrawRectangle, mStartPoint.X); 
     Canvas.SetTop(mDrawRectangle, mStartPoint.Y); 
     this.cnDrawingArea.Children.Add(mDrawRectangle); 
    } 

    /* Continue drawing Rectangle while Mouse is moving on the Canvas Area*/ 
    private void cnDrawingArea_MouseMove(object sender, MouseEventArgs e) 
    { 
     if(e.LeftButton == MouseButtonState.Released) 
     { 
      return; 
     } 

     Point tmpPoint = e.GetPosition(this.cnDrawingArea); 

     int xPos = (int) Math.Min(tmpPoint.X, mStartPoint.X); 
     int yPos = (int) Math.Min(tmpPoint.Y, mStartPoint.Y); 

     int recWidth = (int) Math.Max(tmpPoint.X, mStartPoint.X) - xPos; 
     int recHeight = (int)Math.Max(tmpPoint.Y, mStartPoint.Y) - yPos; 

     mDrawRectangle.Width = recWidth; 
     mDrawRectangle.Height = recHeight; 
     Canvas.SetLeft(mDrawRectangle, xPos); 
     Canvas.SetTop(mDrawRectangle, yPos); 
    } 
    /*Initialize Window to cover whole screen*/ 
    private void InitMainWindow() 
    { 
     this.WindowStyle = WindowStyle.None; 
     this.Title = string.Empty; 
     this.ShowInTaskbar = false; 
     this.AllowsTransparency = true; 
     this.Background = new SolidColorBrush(Color.FromArgb(0x10, 0x10, 0x10, 0x10)); 
    // this.Topmost = true; 
     this.Left = SystemParameters.VirtualScreenLeft; 
     this.Top = SystemParameters.VirtualScreenTop; 
     this.Width = SystemParameters.VirtualScreenWidth; 
     this.Height = SystemParameters.VirtualScreenHeight; 
    } 


    /*First calculate Starting Ending points according to 
    mouse move and take screenshot*/ 
    private void CaptureScreen(int X1, int Y1, int X2, int Y2) 
    { 
     int StartXPosition = 0; 
     int StartYPosition = 0; 
     int tmpWidth = 0; 
     int tmpHeight = 0; 

     if (X1 < X2 && Y1 < Y2)   /*Drawing Left to Right*/ 
     { 
      StartXPosition = X1; 
      StartYPosition = Y1; 
      tmpWidth = X2 - X1; 
      tmpHeight = Y2 - Y1; 
     } 
     else if(X1 > X2 && Y1 < Y2)  /*Drawing Top to Down*/ 
     { 
      StartXPosition = X2; 
      StartYPosition = Y1; 
      tmpWidth = X1 - X2; 
      tmpHeight = Y2 - Y1; 
     } 
     else if(X1 > X2 && Y1 > Y2)  /*Drawing Down to Top*/ 
     { 
      StartXPosition = X2; 
      StartYPosition = Y2; 
      tmpWidth = X1 - X2; 
      tmpHeight = Y1 - Y2; 
     } 
     else if(X1 < X2 && Y1 >Y2)  /*Drawing Right to Left */ 
     { 
      StartXPosition = X1; 
      StartYPosition = Y2; 
      tmpWidth = X2 - X1; 
      tmpHeight = Y1 - Y2; 
     } 
     StartXPosition += 2; 
     StartYPosition += 2; 
     tmpWidth -= 2; 
     tmpHeight -= 2; 
     mTakenScreenShot = ScreenCapture.CaptureRegion(StartXPosition, StartYPosition, tmpWidth, tmpHeight, false); 
     Mouse.OverrideCursor = Cursors.Arrow; 
    } 

    /*get the screenshot and by calculating real positions of Desktop*/ 
    private void cnDrawingArea_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
    {    
      if (e.LeftButton == MouseButtonState.Released) 
      { 
       mEndPoint = e.GetPosition(this.cnDrawingArea); 

       if (mDrawRectangle != null) 
        this.cnDrawingArea.Children.Remove(mDrawRectangle); 

       Point StartDesktopPosition = this.PointToScreen(mStartPoint); 
       Point EndDesktopPosition = this.PointToScreen(mEndPoint); 

       int tempX1 = (int)StartDesktopPosition.X; 
       int tempY1 = (int)StartDesktopPosition.Y; 
       int tempX2 = (int)EndDesktopPosition.X; 
       int tempY2 = (int)EndDesktopPosition.Y; 

       CaptureScreen(tempX1, tempY1, tempX2, tempY2); 
       this.DialogResult = true; 
       this.Close(); 
      } 
     } 
    } 

Gibt es eine Lösung oder einen Vorschlag, wenn die Maus schnell bewegt wird rechts Screenshot zu machen.

Vielen Dank.

Antwort

2

Wenn die Maus sehr schnell bewegt wird, aggregiert Windows Mausbewegungen in eine einzelne Nachricht, um keine Programme mit Tonnen von WM_MOUSEMOVEs zu überlasten. Sie können eine Liste dieser Zwischenpunkte in WPF über Mouse.GetIntermediatePoints abrufen.

Ich vermute, dass Ihr Problem darin besteht, dass sich die Maus schnell zwischen dem letzten Zug und dem linken Knopf über den Bildschirm bewegt und Ihnen eine ganze Reihe von Zwischenpunkten fehlt.

Versuchen Sie dies als ein Experiment, zeichnen Sie auch Ihr Rechteck in der linken Schaltfläche herauf Handler. Ich glaube, dass das Rechteck dem Screenshot-Bereich entsprechen wird. Wenn Sie dann die Zwischenpunkte überprüfen, werden Sie wahrscheinlich eine Reihe von Bewegungsdaten in der Warteschlange sehen.

Um dies zu umgehen, warum nicht einfach die letzte Mausbewegung als mEndPoint anstelle des Aufrufs von GetPosition im linken Button-Up-Handler verwenden? Das sollte Ihnen das richtige Verhalten geben, da es Ihre aktuelle Methode zum Zeichnen des Rechtecks ​​genau widerspiegelt. Dann werden Sie unabhängig von Zwischenbewegungen die Rechteckkoordinaten selbst erfassen, nicht das neue Rechteck, das von der linken oberen Position gebildet wird.

+0

Vielen Dank für Ihre Antwort. – Mamurbek

+0

Wie Sie empfehlen, zeichne ich ein Rechteck in den linken Button-up-Handler und starte Timer (Delay 100ms). Wenn timer ticks, erhalten Sie die Koordinaten, Höhe und Breite des Rechtecks, erfassen Sie dann die Rechteckregion und stoppen Sie den Timer. – Mamurbek