2016-06-16 19 views
2

私はスクリーンショットを取るためにいくつかのプログラムをやっています。その機能はWindowsのSnipping Toolと同じです。ユーザーは画面上に矩形を描いて領域を定義し、ショットを撮る。デスクトップC#(WPF)のスクリーンショット

私はデスクトップ全体をカバーすることによって新しいウィンドウを開くような、驚くべきtutorialを追跡しました。次に、ウィンドウに矩形を描き、矩形の内側で撮影します。マウスが正常に動かされると、スクリーンショットが正しく撮られます。マウスが速く移動して、この画像

enter image description here

しかし、同じように、スクリーンショットは、下図のように、誤って解釈されます。ショットは、ここでは矩形領域の外に

Shot is taken out of rectangle area

を取られたソースコードである:

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

は、マウスを右のスクリーンショットを撮るために高速移動して任意の解決策や提案があります。

ありがとうございます。

答えて

2

マウスを非常に速く動かすと、WindowsはWM_MOUSEMOVEのトンでプログラムをオーバーロードしないように、マウスの動きを1つのメッセージに集約します。これらの中間点のリストは、WPFでMouse.GetIntermediatePoints経由で取得できます。

マウスが最後の移動と左ボタンの間で画面全体をすばやく移動していて、途中の点が一杯になっていないことが問題だと思われます。

これを実験として試してください。また、左ボタンアップハンドラで四角形を描画してください。私はそれが四角形をスクリーンショット領域に一致させると信じています。中間点を確認すると、一連の移動データが並んでいる可能性が高くなります。

これを回避するには、左ボタンアップハンドラでGetPositionを呼び出すのではなく、最後のマウス移動をmEndPointとして使用しないでください。これは、現在の矩形を描画する方法を正確に反映するため、正しい動作を提供するはずです。次に、中間の動きにかかわらず、左ボタンの上に配置された新しい矩形ではなく、矩形の座標自体をキャプチャします。

+0

ありがとうございました。 – Mamurbek

+0

あなたは、左ボタンアップハンドラに長方形を描き、タイマー(遅延100ms)を開始することをお勧めします。タイマーが刻々と変化すると、矩形の座標、高さ、幅を取得し、長方形の領域をキャプチャし、タイマーも停止します。 – Mamurbek

関連する問題