我尝试编写自己的剪切工具。除了我选择的区域大小与像素大小不匹配外,它的效果非常好。
我创建了一个低不透明度的窗口并绘制一个矩形来获取大小和位置。该窗口的尺寸为300x300(后来应该是全屏),但如果我使用剪切工具截取屏幕截图,则显示的尺寸为375x375像素。因此,当我用自己的程序拍摄一个scrennshot时,我没有捕捉到我真正想要的所有功能。
最终目标是使用快捷方式(未实现)获取同一位置的多个屏幕截图,然后在特定区域执行一些OCR(未实现)并创建与OCR结果相对应的文件名。
以下是代码:
主窗口c#:
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>
获取矩形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>
所以,这是我的问题:
感谢您的帮助。
答案 0 :(得分: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;
}
当差异足够大(100+像素)时,我仍然关闭1或2像素(不知道为什么),但我可以忍受。
编辑:差异大约为8像素,它始终存在 - 我猜它是窗口边框或其他东西。