当前位置:网站首页>wpf实现简易画板功能(带截取画板,签名截图等等)
wpf实现简易画板功能(带截取画板,签名截图等等)
2022-08-09 11:09:00 【一头小驴】
参照自:https://www.cnblogs.com/jixin/p/4730170.html
https://blog.csdn.net/u012408847/article/details/86482399
截图功能将会把红色方块区域内的内容截取下来,保存在img文件夹中。
window1.xaml
<Window x:Class="_1_5GraphicsWpf.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:_1_5GraphicsWpf"
xmlns:cvr="clr-namespace:_1_5GraphicsWpf.ControlValidationRule"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<Grid>
<DockPanel Background="AliceBlue">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"></ColumnDefinition>
<ColumnDefinition Width="13*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Canvas Grid.Column="1" x:Name="myCanvas" DockPanel.Dock="Right" Background="LightGray"
PreviewMouseLeftButtonDown="Canvas_PreviewMouseLeftButtonDown" PreviewMouseMove="Canvas_PreviewMouseMove"
MouseLeftButtonUp="MyCanvas_MouseLeftButtonUp"
></Canvas>
<Grid DockPanel.Dock="Left" x:Name="LeftDockPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30px"></RowDefinition>
<RowDefinition Height="30px"></RowDefinition>
<RowDefinition Height="30px"></RowDefinition>
<RowDefinition Height="30px"></RowDefinition>
<RowDefinition Height="30px"></RowDefinition>
<RowDefinition Height="30px"></RowDefinition>
<RowDefinition Height="30px"></RowDefinition>
</Grid.RowDefinitions>
<Label Grid.Column="0" Grid.Row="0">颜色œ˜œ˜œ˜œ˜</Label>
<ComboBox x:Name="ComboColor" Grid.Row="0" Grid.Column="1" Margin="6 3"
SelectedValuePath="{Binding Path=ID}" SelectedIndex="{Binding Path=Combo_ColorIndex}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=PColor}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Label Grid.Column="0" Grid.Row="1">线条粗细œ˜œ˜œ˜œ˜</Label>
<TextBox x:Name="textBoxThick" Grid.Row="1" Grid.Column="1" Margin="6,3" >
<TextBox.Text>
<Binding Path="Thickness" NotifyOnValidationError="True" NotifyOnSourceUpdated="True" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<cvr:DataValidationRule ValidatesOnTargetUpdated="True"></cvr:DataValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Slider Minimum="0" Maximum="100" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" Value="{Binding Path=Thickness, Mode=TwoWay}"></Slider>
<Label Grid.Column="0" Grid.Row="3">样式œ˜œ˜œ˜œ˜</Label>
<ComboBox x:Name="ComboStyle" Grid.Row="3" Grid.Column="1" Margin="6 3"
SelectedValuePath="{Binding Path=ID}" SelectedIndex="{Binding Path=Combo_StyleIndex}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=PStyle}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Margin="10 3" Content="清除" Click="Button_Click"></Button>
<Button Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2" Margin="10 3" Content="截图" Click="Button_Click_1"></Button>
</Grid>
</Grid>
</DockPanel>
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using _1_5GraphicsWpf.ViewModel;
using _1_5GraphicsWpf.ControlValidationRule;
using System.Drawing;
namespace _1_5GraphicsWpf
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
Init();
}
ObservableCollection<VMColor> ColorCollection;
ObservableCollection<VMStyle> StyleCollection;
Global_Window1 GlobalVaries;
void Init()
{
ColorCollection = new ObservableCollection<VMColor> {
new VMColor{ID = 0,PColor="默认"},
new VMColor{ID = 1,PColor="红色"},
new VMColor{ID = 2,PColor="绿色" }
};
StyleCollection = new ObservableCollection<VMStyle> {
new VMStyle{ID = 0,PStyle="平坦"},
new VMStyle{ID = 1,PStyle="直角"},
new VMStyle{ID = 2,PStyle="三角"},
new VMStyle{ID = 3,PStyle="圆形"}
};
GlobalVaries = new Global_Window1() {
Combo_ColorIndex = 0,
Combo_StyleIndex = 0,
Thickness = 1
};
this.ComboColor.ItemsSource = ColorCollection;
this.ComboStyle.ItemsSource = StyleCollection;
this.DataContext = GlobalVaries;
this.textBoxThick.AddHandler(Validation.ErrorEvent,new RoutedEventHandler(this.ValidationError));
}
void ValidationError(object sender,RoutedEventArgs e)
{
TextBox obj = sender as TextBox;
if (Validation.GetErrors(obj).Count>0)
{
obj.ToolTip = Validation.GetErrors(this.textBoxThick)[0].ErrorContent.ToString();
}
}
System.Windows.Point startPoint;
List<System.Windows.Point> pointList = new List<System.Windows.Point>();
private void Canvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
startPoint = e.GetPosition(myCanvas);
}
private void Canvas_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
// 返回指针相对于Canvas的位置
System.Windows.Point point = e.GetPosition(myCanvas);
if (pointList.Count == 0)
{
// 加入起始点
pointList.Add(new System.Windows.Point(this.startPoint.X, this.startPoint.Y));
}
else
{
// 加入移动过程中的point 颜色
pointList.Add(point);
}
// 去重复点
var disList = pointList.Distinct().ToList();
var count = disList.Count(); // 总点数
if (point != this.startPoint && this.startPoint != null)
{
var l = new Line();
//string color = (ComboColor.SelectedItem as ComboBoxItem).Content as string;
int color = int.Parse((ComboColor.SelectedValue as VMColor).ID.ToString());
switch (color)
{
case 0:
l.Stroke = System.Windows.Media.Brushes.Black;
break;
case 1:
l.Stroke = System.Windows.Media.Brushes.Red;
break;
case 2:
l.Stroke = System.Windows.Media.Brushes.Green;
break;
default:
l.Stroke = System.Windows.Media.Brushes.Black;
break;
}
int style = int.Parse((ComboStyle.SelectedValue as VMStyle).ID.ToString());
switch (style)
{
case 0:
l.StrokeDashCap = PenLineCap.Flat;
l.StrokeStartLineCap = PenLineCap.Flat;
l.StrokeEndLineCap = PenLineCap.Flat;
break;
case 1:
l.StrokeDashCap = PenLineCap.Square;
l.StrokeStartLineCap = PenLineCap.Square;
l.StrokeEndLineCap = PenLineCap.Square;
break;
case 2:
l.StrokeDashCap = PenLineCap.Triangle;
l.StrokeStartLineCap = PenLineCap.Triangle;
l.StrokeEndLineCap = PenLineCap.Triangle;
break;
case 3:
l.StrokeDashCap = PenLineCap.Round;
l.StrokeStartLineCap = PenLineCap.Round;
l.StrokeEndLineCap = PenLineCap.Round;
break;
default:
l.StrokeDashCap = PenLineCap.Round;
l.StrokeStartLineCap = PenLineCap.Round;
l.StrokeEndLineCap = PenLineCap.Round;
break;
}
//l.StrokeLineJoin = PenLineJoin.Round;
//l.StrokeStartLineCap = PenLineCap.Triangle;
l.StrokeThickness = this.GlobalVaries.Thickness ;
if (count < 2)
return;
l.X1 = disList[count - 2].X; // count-2 保证 line的起始点为点集合中的倒数第二个点。
l.Y1 = disList[count - 2].Y;
// 终点X,Y 为当前point的X,Y
l.X2 = point.X;
l.Y2 = point.Y;
myCanvas.Children.Add(l);
}
}
}
private void MyCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
pointList.Clear();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.myCanvas.Children.Clear();//清除
pointList.Clear();
}
#region 截图
public static Shape CreateShape()
{
//矩形区域
return new System.Windows.Shapes.Rectangle() { Fill = null, Stroke = System.Windows.Media.Brushes.Red, StrokeThickness = 1 };
//圆形区域
//return new System.Windows.Shapes.Ellipse() { Fill = null, Stroke = System.Windows.Media.Brushes.Red, StrokeThickness = 1 };
}
bool drawFlag = false;
Shape insertShape;
System.Windows.Point startPosition;
private void Mask_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
insertShape = CreateShape();
if (insertShape != null)
{
drawFlag = true;
Canvas board = sender as Canvas;
//board.Children.Clear();
startPosition = e.GetPosition(board);
insertShape.Opacity = 1;
Canvas.SetLeft(insertShape, e.GetPosition(board).X);
Canvas.SetTop(insertShape, e.GetPosition(board).Y);
board.Children.Add(insertShape);
}
}
private void image_MouseMove(object sender, MouseEventArgs e)
{
Canvas board = sender as Canvas;
if (drawFlag && insertShape != null)
{
if (e.GetPosition(board).X > startPosition.X)
{
insertShape.Width = e.GetPosition(board).X - startPosition.X;
//Canvas.SetRight(insertShape, startPosition.X);
}
else
{
insertShape.Width = startPosition.X - e.GetPosition(board).X;
Canvas.SetLeft(insertShape, e.GetPosition(board).X);
}
if (e.GetPosition(board).Y > startPosition.Y)
{
insertShape.Height = e.GetPosition(board).Y - startPosition.Y;
//Canvas.SetBottom(insertShape, startPosition.Y);
}
else
{
insertShape.Height = startPosition.Y - e.GetPosition(board).Y;
Canvas.SetTop(insertShape, e.GetPosition(board).Y);
}
}
}
private void Mask_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Canvas board = sender as Canvas;
System.Windows.Point position = board.PointToScreen(new System.Windows.Point(0, 0));
drawFlag = false;
int width = (int)insertShape.Width +150 ;
int height = (int)insertShape.Height +110 ;
System.Drawing.Size size = new System.Drawing.Size(width, height);
int startX = (e.GetPosition(board).X < startPosition.X) ? (int)e.GetPosition(board).X : (int)startPosition.X ;
int startY = (e.GetPosition(board).Y < startPosition.Y) ? (int)e.GetPosition(board).Y : (int)startPosition.Y ;
//int endX = (e.GetPosition(board).X > startPosition.X) ? (int)e.GetPosition(board).X + 10 : (int)startPosition.X + 10;
//int endY = (e.GetPosition(board).Y > startPosition.Y) ? (int)e.GetPosition(board).Y + 10 : (int)startPosition.Y + 10;
if (insertShape != null)
{
insertShape.Opacity = 1;
System.Windows.Point p = e.GetPosition(board);
//BitmapSource memory = new Bitmap(width, height);
//Graphics g = Graphics.FromImage(memory);
//g.CopyFromScreen(this.Location.X + 1, this.Location.Y + 1, 0, 0, new System.Drawing.Size(width, height));
Clipboard.SetImage(memory);//把图片放到剪切板中
//bmp.Save("C:\\Screenshots\\" + filename);
using (Bitmap bmp = new Bitmap(width, height))
{
using (Graphics g = Graphics.FromImage(bmp))
{
String filename = "ScreenCapture-" + DateTime.Now.ToString("ddMMyyyy-hhmmss") + ".png";
g.CopyFromScreen(startX+(int)position.X, startY+(int)position.Y, 0, 0, size);
bmp.Save("..\\..\\img\\" + filename);
Button_Click_2();
}
}
}
}
#endregion
bool canShot = false;
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.myCanvas.MouseLeftButtonDown += Mask_MouseLeftButtonDown;
this.myCanvas.MouseMove += image_MouseMove;
this.myCanvas.MouseLeftButtonUp += Mask_MouseLeftButtonUp;
this.myCanvas.PreviewMouseLeftButtonDown -= Canvas_PreviewMouseLeftButtonDown;
this.myCanvas.PreviewMouseMove -= Canvas_PreviewMouseMove;
this.myCanvas.MouseLeftButtonUp -= MyCanvas_MouseLeftButtonUp;
canShot = true;
}
private void Button_Click_2()
{
if (canShot ==true)
{
this.myCanvas.MouseLeftButtonDown -= Mask_MouseLeftButtonDown;
this.myCanvas.MouseMove -= image_MouseMove;
this.myCanvas.MouseLeftButtonUp -= Mask_MouseLeftButtonUp;
this.myCanvas.PreviewMouseLeftButtonDown += Canvas_PreviewMouseLeftButtonDown;
this.myCanvas.PreviewMouseMove += Canvas_PreviewMouseMove;
this.myCanvas.MouseLeftButtonUp += MyCanvas_MouseLeftButtonUp;
}
canShot = false;
}
}
}
边栏推荐
- x86 Exception Handling and Interrupt Mechanism (1) Overview of the source and handling of interrupts
- pip common commands and changing source files
- 实现strcat函数
- activemq message persistence
- STM32使用静态队列保存数据
- ThreadLocal及其内存泄露分析
- matlab图像分割,从基因芯片荧光图像中提取阴性点(弱)和阳性点(强)
- STM32启动方式及BootLoader
- 1008 Elevator (20分)
- Cesium加载三维模型数据
猜你喜欢
x86 Exception Handling and Interrupt Mechanism (1) Overview of the source and handling of interrupts
wait system call
信息系统项目的十大管理
matlab图像分割,从基因芯片荧光图像中提取阴性点(弱)和阳性点(强)
支付宝小程序的接入
PTA 实验7-5 输出大写英文字母(10 分)
golang 标准库json Marshal、Unmarshal坑
ICML 2022 | Out-of-Distribution Detection with Deep Nearest Neighbors
程序员的专属浪漫——用3D Engine 5分钟实现烟花绽放效果
FreeRTOS任务创建源码分析
随机推荐
SQL Server查询优化
1007 Maximum Subsequence Sum (25分)
UNIX Philosophy
基于STM32F103移植FreeRTOS
x86 exception handling and interrupt mechanism (2) interrupt vector table
centos7.5 设置Mysql开机自启动
微信小程序——天气查询
vite的原理,手写vite
x86异常处理与中断机制(2)中断向量表
Beauty Values
PTA 实验7-5 输出大写英文字母(10 分)
∘(空心的点乘)的数学含义
golang 标准库json Marshal、Unmarshal坑
性能测试(01)-jmeter元件-线程组、调试取样器
电磁场与电磁波-场论基础
爱可可AI前沿推介(8.9)
OC-块对象
UNIX哲学
faster-rcnn learn
Quartz的理解