2016-10-06 6 views
0

Я попытался самостоятельно создать собственный инструмент для обрезки. Он работает довольно хорошо, за исключением того, что размер области, которую я выбираю, не соответствует размеру в пикселях.Выполнение скриншотов - размеры не совпадают

Я создаю окно с низкой непрозрачностью и рисую прямоугольник, чтобы получить размер и местоположение. Окно имеет размеры 300x300 (позже оно должно быть полноэкранным), но если я возьму скриншот с инструментом для обрезки, он отобразит размер 375x375 пикселей. Поэтому, когда я беру scrennshot со своей собственной программой, я не поймаю все функции, которые я действительно хотел.

Конечная цель - сделать несколько скриншотов одного и того же местоположения с помощью ярлыка (не реализовано), затем сделать некоторые OCR (не реализованы) в определенных регионах и создать имя файла, соответствующее результатам OCR.

Вот код:

Главное окно с #:

int number = 0; 

    System.Windows.Point scsh_Start; 
    System.Windows.Point scsh_Ende; 
    System.Windows.Point OCR_Start; 
    System.Windows.Point OCR_Ende; 

    public MainWindow() 
    { 
     InitializeComponent();    
    } 


    private void button_Click(object sender, RoutedEventArgs e) 
    { 
     int Width = (int)(Math.Abs(scsh_Start.X - scsh_Ende.X)); 
     int Height = (int)(Math.Abs(scsh_Start.Y - scsh_Ende.Y)); 
     using (Bitmap bmpScreenCapture = new Bitmap(Width, 
             Height)) 
     { 
      using (Graphics g = Graphics.FromImage(bmpScreenCapture)) 
      {      
       string outputNumber = ""; 
       if (number < 10) 
       { 
        outputNumber = "00" + number.ToString(); 
       } 
       else if (number < 100) 
       { 
        outputNumber = "0" + number.ToString(); 
       } 
       else 
       { 
        outputNumber = number.ToString(); 
       } 
       Opacity = .0;      
       g.CopyFromScreen((int)scsh_Start.X, 
           (int)scsh_Start.Y, 
           0, 0, 
           bmpScreenCapture.Size); 
       Directory.CreateDirectory("C:\\Users\\Public\\Pictures\\Sample Pictures\\ScreenSave"); 
       bmpScreenCapture.Save("C:\\Users\\Public\\Pictures\\Sample Pictures\\ScreenSave\\test" + outputNumber + ".png"); 
       Opacity = 1; 
       number++; 
      } 
     } 
    } 

    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     this.WindowState = WindowState.Minimized; 
     Window1 w1 = new Window1(); 
     w1.RaiseCustomEvent += pointsScreenshot; 
     w1.ShowDialog(); 

    } 

    private void pointsScreenshot(object sender, customEventArgs e) 
    { 
     if (e.Points[0] == null) 
      return; 
     scsh_Start = e.Points[0]; 
     scsh_Ende = e.Points[1]; 
     B_Image.IsEnabled = true;  
    } 

Главное окно XAML:

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:WpfApplication1" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Button x:Name="B_Image" Content="Image" HorizontalAlignment="Left" Margin="70,31,0,0" VerticalAlignment="Top" Width="75" Click="button_Click" IsEnabled="False"/> 
    <Button x:Name="B_MouseEvents" Content="Mouse" HorizontalAlignment="Left" Margin="70,76,0,0" VerticalAlignment="Top" Width="75" Click="button1_Click"/> 
</Grid> 

Secondary окно, чтобы получить прямоугольник C#:

public partial class Window1 : Window 
{ 
    public event EventHandler<customEventArgs> RaiseCustomEvent; 
    private Point p_Start = new Point(); 
    private Point p_End = new Point(); 
    private Rectangle saveRect = null; 
    private MoveType move = MoveType.Draw; 
    bool top = false; 
    bool left = false; 


    public Window1() 
    { 
     InitializeComponent(); 
     this.Topmost = true; 
     this.Activate(); 
     ////this.WindowState = WindowState.Maximized;  

    } 

    private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     p_Start = e.GetPosition(null); 

     double xAct = e.GetPosition(null).X; 
     double yAct = e.GetPosition(null).Y; 

     if (saveRect != null) 
     { 
      double rectLeft = saveRect.Margin.Left; 
      double rectTop = saveRect.Margin.Top; 
      double rectRight = saveRect.Margin.Left + saveRect.Width; 
      double rectBottom = saveRect.Margin.Top + saveRect.Height; 

      if (between(xAct, rectLeft + 3, rectRight - 3) && 
       between(yAct, rectTop + 3, rectBottom - 3)) 
       move = MoveType.Drag; 

      else if ((between(xAct, rectLeft - 3, rectLeft) || between(xAct, rectRight - 3, rectRight)) && 
       between(yAct, rectTop, rectBottom)) 
      { 
       move = MoveType.ResizeWidth; 
       left = between(xAct, rectLeft - 3, rectLeft + 3); 
      } 
      else if ((between(yAct, rectTop - 3, rectTop) || between(yAct, rectBottom - 3, rectBottom)) && 
       between(xAct, rectLeft, rectRight)) 
      { 
       move = MoveType.ResizeHeight; 
       top = between(yAct, rectTop - 3, rectTop + 3); 
      } 
      else 
       move = MoveType.Draw; 
     } 
     else 
      move = MoveType.Draw; 
    } 

    private void Window_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
    { 
     move = MoveType.Draw; 
    } 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 


    } 

    private void Window_MouseMove(object sender, MouseEventArgs e) 
    { 
     double xAct = e.GetPosition(null).X; 
     double yAct = e.GetPosition(null).Y; 

     #region select Cursor 
     if (e.LeftButton != MouseButtonState.Pressed) 
     { 
      if (saveRect != null) 
      { 
       double rectLeft = saveRect.Margin.Left; 
       double rectTop = saveRect.Margin.Top; 
       double rectRight = saveRect.Margin.Left + saveRect.Width; 
       double rectBottom = saveRect.Margin.Top + saveRect.Height; 

       if (between(xAct, rectLeft + 3, rectRight - 3) && 
        between(yAct, rectTop + 3, rectBottom - 3)) 
        Cursor = Cursors.Hand; 

       else if ((between(xAct, rectLeft - 3, rectLeft) || between(xAct, rectRight - 3, rectRight)) && 
        between(yAct, rectTop, rectBottom)) 
        Cursor = Cursors.SizeWE; 
       else if ((between(yAct, rectTop - 3, rectTop) || between(yAct, rectBottom - 3, rectBottom)) && 
        between(xAct, rectLeft, rectRight)) 
        Cursor = Cursors.SizeNS; 

       else Cursor = Cursors.Pen; 
      } 
      else 
       Cursor = Cursors.Pen; 
      return; 
     } 
     else 
     { 
      switch (move) 
      { 
       case MoveType.Drag: 
        Cursor = Cursors.Hand; 
        break; 
       case MoveType.Draw: 
        Cursor = Cursors.Pen; 
        break; 
       case MoveType.ResizeHeight: 
        Cursor = Cursors.SizeNS; 
        break; 
       case MoveType.ResizeWidth: 
        Cursor = Cursors.SizeWE; 
        break; 
      } 
     } 
     #endregion 

     if (mainGrid.Children.Count > 0) 
      this.mainGrid.Children.RemoveAt(0); 
     Rectangle r = new Rectangle(); 
     p_End = e.GetPosition(null); 
     switch (move) 
     { 
      case MoveType.Draw:          
       r.Stroke = new SolidColorBrush(Colors.Aqua); 
       r.Opacity = 1; 
       r.Height = Math.Abs(p_End.Y - p_Start.Y); 
       r.Width = Math.Abs(p_End.X - p_Start.X); 
       double t_left = p_End.X > p_Start.X ? p_Start.X : p_End.X; 
       double t_top = p_End.Y > p_Start.Y ? p_Start.Y : p_End.Y; 
       r.VerticalAlignment = VerticalAlignment.Top; 
       r.HorizontalAlignment = HorizontalAlignment.Left; 
       r.Margin = new Thickness(t_left, t_top, 0, 0); 
       this.mainGrid.Children.Add(r); 
       saveRect = r; 
       break; 
      case MoveType.Drag: 
       r = saveRect; 
       double moveHorizontal = p_Start.X - p_End.X; 
       double moveVertical = p_Start.Y - p_End.Y; 
       if (r.Margin.Left - moveHorizontal < 0) 
        moveHorizontal = r.Margin.Left; 
       if (r.Margin.Top - moveVertical < 0) 
        moveVertical = r.Margin.Top; 
       r.Margin = new Thickness(r.Margin.Left - moveHorizontal, r.Margin.Top - moveVertical, 0, 0); 
       this.mainGrid.Children.Add(r); 
       saveRect = r; 
       p_Start = p_End; 
       break; 
      case MoveType.ResizeHeight: 
       r = saveRect; 
       double resize = p_Start.Y - p_End.Y; 
       if (top) 
       {      
        r.Margin = new Thickness(r.Margin.Left, r.Margin.Top - resize, 0, 0);       
        r.Height += resize; 
       } 
       else 
       {      
        r.Height -= resize; 
       } 
       this.mainGrid.Children.Add(r); 
       saveRect = r; 
       p_Start = p_End; 
       break; 
      case MoveType.ResizeWidth: 
       r = saveRect; 
       double resizeX = p_Start.X - p_End.X; 
       if (left) 
       { 
        r.Margin = new Thickness(r.Margin.Left - resizeX, r.Margin.Top, 0, 0); 
        r.Width += resizeX; 
       } 
       else 
       { 
        r.Width -= resizeX; 
       } 
       this.mainGrid.Children.Add(r); 
       saveRect = r; 
       p_Start = p_End; 
       break; 
     } 
    } 

    private void Window_MouseRightButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     RaiseCustomEvent(this, new customEventArgs(getPoints())); 
     this.Close(); 
    } 

    public List<Point> getPoints() 
    { 
     List<Point> p = new List<Point>(); 
     this.Visibility = Visibility.Collapsed; 
     if (mainGrid.Children.Count > 0) 
     { 
      p.Add(new Point(saveRect.Margin.Left, saveRect.Margin.Top)); 
      p.Add(new Point(saveRect.Width+ saveRect.Margin.Left, saveRect.Height+ saveRect.Margin.Top)); 
      return p; 
     } 

     return null; 
    } 

    private bool between(double actual, double min, double max) 
    { 
     if ((actual < min) || (actual > max)) 
      return false; 
     else return true; 
    } 

    private enum MoveType 
    { 
     Draw, 
     Drag, 
     ResizeHeight, 
     ResizeWidth 
    } 

} 

public class customEventArgs : EventArgs 
{ 
    private List<Point> pts; 
    public customEventArgs(List<Point> Points) 
    { 
     pts = Points; 
    } 

    public List<Point> Points 
    { 
     get { return pts; } 
    } 
} 

вторичное окно XAML:

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:WpfApplication1" 
    mc:Ignorable="d" 
    Title="W1" Height="300" Width="300" WindowStyle="None" Topmost="True" BorderThickness="0" Foreground="{x:Null}" AllowsTransparency="True" 
    Left="0" Top="0" 
    MouseLeftButtonDown="Window_MouseLeftButtonDown" Loaded="Window_Loaded" MouseMove="Window_MouseMove" MouseRightButtonDown="Window_MouseRightButtonDown" 
    MouseLeftButtonUp="Window_MouseLeftButtonUp" > 
<Window.Background> 
    <SolidColorBrush Opacity="0.3" Color="Gray"></SolidColorBrush> 
</Window.Background> 
<Grid Name="mainGrid">   
</Grid> 

Итак, вот мои вопросы:

  1. Почему размер окна не фактический размер в пикселях?
  2. Как получить значения, которые я хочу, чтобы изображения, которые я принимаю, включали все функции, которые я хочу им, не менее?

Благодарим за помощь.

+0

в размерах Wpf по умолчанию находятся в провалах (устройство не зависит от устройства), а не в пикселях. Дополнительная информация [здесь] (https://msdn.microsoft.com/en-us/library/windows/desktop/ff684173 (v = vs.85) .aspx) – Pikoh

+0

Если вы используете дисплей с 120 DPI или установили ваш размер текста на экране до 125% на дисплее 96 DPI, тогда пиксели будут отличаться от пикселов, не зависящих от устройства WPF, в 1,25 раза. – haindl

+0

@Pikoh: спасибо, эта ссылка и немного больше поиска помогли много – Thoms

ответ

0

Ссылка Pikoh была в правильном направлении. привели меня к этому How can I get the DPI in WPF?

private double getDPIScale() 
    { 
     PresentationSource source = PresentationSource.FromVisual(this); 

     double dpiX , dpiY; 
     if (source != null) 
     { 
      dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11; 
      dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22; 
      return dpiX/96.0; 
     } 

     return 0;    
    } 

Я до сих пор от 1 или 2 пикселя (не знаю почему), когда разница достаточно велика (100+ пикселей), но я могу жить с этим.

Редактировать: разница составляет около 8 пикселей, и она всегда есть - я думаю, что это граница окна или что-то в этом роде.