2016-06-16 8 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가 많은 프로그램에 과부하가 걸리지 않도록 마우스 움직임을 단일 메시지로 집계합니다. Mouse.GetIntermediatePoints을 통해 WPF에서 이러한 중간 지점의 목록을 얻을 수 있습니다.

마우스가 마지막 이동과 왼쪽 단추 사이에서 화면 전체에서 빠르게 움직이고 있으며 중간 지점 전체가 누락되었다고 생각됩니다.

실험으로 사용해 보시고 왼쪽 버튼 조작기에서 사각형을 그려보십시오. 사각형이 스크린 샷 영역과 일치하게 만들 것입니다. 그런 다음 중간 지점을 확인하면 이동 데이터 묶음이 대기열에 있음을 알 수 있습니다.

이 문제를 해결하려면 왼쪽 버튼을 위로 핸들러에서 GetPosition을 호출하는 대신 mEndPoint로 마지막 마우스 이동을 사용하지 않는 것이 어떻습니까? 사각형을 그리는 현재 방법을 정확히 반영하므로 올바른 동작을 제공해야합니다. 그런 다음 중간 이동에 관계없이 왼쪽 단추 위로 위치하여 형성된 새로운 사각형이 아니라 사각형 좌표 자체를 캡처합니다.

+0

답장을 보내 주셔서 감사합니다. – Mamurbek

+0

추천대로 왼쪽 버튼을 핸들러에 직사각형을 그리고 타이머 (지연 100ms)를 시작합니다. 타이머가 틱하면 직사각형의 좌표, 높이 및 너비를 얻은 다음 사각형 영역을 캡처하고 타이머도 중지합니다. – Mamurbek