【WPF】WPF截屏
原文:【WPF】WPF截屏
引言
.NET的截图控件在网上流传得不多啊,难得发现一个精品截图控件( 传送门),但是无奈是winform的.后来又找到一个周银辉做的WPF截图(继续传送门),发现截屏是实现了,但是功能略少了点.So,打算自己用WPF去实现一个,无奈略渣,还是简单分享一下吧.
一个Window和一个Canvas
Window是截图的主界面,但是设置好WindowStyle和WindowState就基本没它什么事了,Window里面放个Canvas,Canvas主要承载当前的截屏和画板DrawingPannel以及工具控件.先看看Window和Canvas的代码吧,如下
- <Window x:Class="WpfCapture.Window3"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:wpfCapture="clr-namespace:WpfCapture"
- Title="Window3" Height="" Width="" WindowStyle="None" WindowState="Maximized">
- <Canvas Name="xgrid" >
- </Canvas>
- </Window>
什么时候加载当前截屏,怎样加载,看代码
- public Window3()
- {
- InitializeComponent();
- screenSnapshot = GetScreenSnapshot();
- var bmp = ToBitmapSource(screenSnapshot);
- bmp.Freeze();
- this.xgrid.Background = new ImageBrush(bmp);
- }
- public Bitmap GetScreenSnapshot()
- {
- try
- {
- System.Drawing.Rectangle rc = SystemInformation.VirtualScreen;
- var bitmap = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- using (Graphics memoryGrahics = Graphics.FromImage(bitmap))
- {
- memoryGrahics.CopyFromScreen(rc.X, rc.Y, , , rc.Size, CopyPixelOperation.SourceCopy);
- }
- return bitmap;
- }
- catch (Exception)
- {
- }
- return null;
- }
画板DrawingPannel
画板DrawingPannel是自定义的一个布局控件类,主要是用来显示DrawingVisual对象的,类定义如下:
- public class DrawingCanvas : Panel
- {
- private List<Visual> visuals = new List<Visual>();
- protected override Visual GetVisualChild(int index)
- {
- return visuals[index];
- }
- protected override int VisualChildrenCount
- {
- get
- {
- return visuals.Count;
- }
- }
- public void RemoveLastVisual()
- {
- if (visuals.Count > )
- {
- var item= visuals.FindLast(x => true);
- DeleteVisual(item);
- }
- }
- public void AddVisual(Visual visual)
- {
- visuals.Add(visual);
- base.AddVisualChild(visual);
- base.AddLogicalChild(visual);
- Console.WriteLine(visuals.Count);
- }
- public void DeleteVisual(Visual visual)
- {
- visuals.Remove(visual);
- base.RemoveVisualChild(visual);
- base.RemoveLogicalChild(visual);
- }
- }
既然画板有了,当然不能漏了画笔等操作工具,所以最终界面XAML描述如下
- <Window x:Class="WpfCapture.Window3"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:wpfCapture="clr-namespace:WpfCapture"
- Title="Window3" Height="" Width="" WindowStyle="None" WindowState="Maximized">
- <Canvas Name="xgrid" >
- <wpfCapture:DrawingCanvas x:Name="grid" Background="AliceBlue" Canvas.Top="" Canvas.Left="" Width="{Binding ActualWidth,ElementName=xgrid}"
- Height="{Binding ActualHeight,ElementName=xgrid}"
- Opacity="0.8" MouseLeftButtonDown="Grid_OnMouseLeftButtonDown" PreviewMouseMove="grid_PreviewMouseMove_1" MouseLeftButtonUp="Grid_OnMouseLeftButtonUp"
- MouseMove="grid_MouseMove_2" MouseRightButtonDown="grid_MouseRightButtonDown_1"
- >
- </wpfCapture:DrawingCanvas>
- <StackPanel Orientation="Horizontal" Name="toolpanel" Visibility="Collapsed" Height="" Width="">
- <ToolBar>
- <RadioButton GroupName="tool" Name="Arrow" >
- <Image Source="./icons/Arrow.ico"></Image>
- </RadioButton>
- <RadioButton GroupName="tool" Name="Rectangular">
- <Image Source="./icons/Rectangular.ico"></Image>
- </RadioButton>
- <RadioButton GroupName="tool" Name="Line">
- <Image Source="./icons/Line.ico"></Image>
- </RadioButton>
- <Button Click="Button_Click_2">
- <Image Source="./icons/Redo.png"></Image>
- </Button>
- <Button>
- <Image Source="./icons/Exit.ico"></Image>
- </Button>
- <Button Click="Button_Click_1">
- <Image Source="./icons/Accept.ico"></Image>
- </Button>
- </ToolBar>
- </StackPanel>
- </Canvas>
- </Window>
如何指定截图方框
如何画截图边框出来呢.其实上面已经有画板了,那么我们只需要在上面画个方框,再将工具栏显示出来,那么好像有点像样了.如何画?需要用到DrawingVisual类,画框的方法如下:
- private void DrawSquare1(DrawingVisual visual)
- {
- using (DrawingContext dc = visual.RenderOpen())
- {
- dc.DrawRectangle(drawingBrush, drawingPen,
- new Rect(startPoint, endPoint));
- }
- }
在鼠标事件中利用上面那个方法轻松画出方框,然后接下来我就用笨方法了,在画出方框后,我new了一个新的DrawingCanvas替代方框,再从一开始截屏图片中截取相应的图片作为DrawingCanvas的背景,在这个过程中要注意DPI值的转换,我的电脑是120的DPI,所以从WPF的单位转换为真正分辨率单位时要乘以1.25.
- //得到DPI比例
- Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
- systemdpi = graphics.DpiX / ;
- //得到截图方框的背景
- private BitmapSource CopyFromScreenSnapshot()
- {
- var sourceRect = new System.Drawing.Rectangle((int)(Math.Min(startPoint.X, endPoint.X) * systemdpi), (int)(Math.Min(startPoint.Y, endPoint.Y) * systemdpi), (int)(Math.Abs(startPoint.X - endPoint.X) * systemdpi), (int)(Math.Abs(startPoint.Y - endPoint.Y) * systemdpi));
- var destRect = new System.Drawing.Rectangle(, , (int)(sourceRect.Width * systemdpi), (int)(sourceRect.Height * systemdpi));
- if (screenSnapshot != null)
- {
- var bitmap = new Bitmap((int)(sourceRect.Width * systemdpi), (int)(sourceRect.Height * systemdpi), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- using (Graphics g = Graphics.FromImage(bitmap))
- {
- g.DrawImage(screenSnapshot, destRect, sourceRect, GraphicsUnit.Pixel);
- }
- return ToBitmapSource(bitmap);
- }
- return null;
- }
画板工具
画板工具我只定义了几个一个线段,方框和钢笔,也有后退,退出和完成截图工具.直接看代码好了
- //画方框
- private void DrawSquare(System.Windows.Point point1, System.Windows.Point point2)
- {
- using (DrawingContext dc = selectionSquare.RenderOpen())
- {
- dc.DrawRectangle(selectionSquareBrush, selectionSquarePen,
- new Rect(point1, point2));
- }
- }
- //画箭头....好吧,是画直线
- private void DrawArrow(System.Windows.Point point1, System.Windows.Point point2)
- {
- using (DrawingContext dc = selectionSquare.RenderOpen())
- {
- dc.DrawLine(selectionSquarePen, point1, point2);
- }
- }
- PathGeometry pgGeometry = new PathGeometry();
- PathFigure pfFigure = new PathFigure();
- //画钢笔线
- private void DrawLine(System.Windows.Point point1, System.Windows.Point point2)
- {
- using (DrawingContext dc = selectionSquare.RenderOpen())
- {
- LineSegment lsLineSegment = new LineSegment(point2, true);
- pfFigure.Segments.Add(lsLineSegment);
- Console.WriteLine(point2.Y);
- pgGeometry.Figures.Add(pfFigure);
- dc.DrawGeometry(selectionSquareBrush, selectionSquarePen, pgGeometry);
- }
- }
各种鼠标方法我就不一一标出来了,最终效果如下:
小结
其实一句话可以说完整个实现的:将Canvas背景设置为当前屏幕,画个框放画板,在画板上涂涂画画,然后将画板转成图片.多简单,但是上面还有好多细节没有说到,也有比较多功能没有实现,例如拖拉边框等功能.因为是纯练习,代码注释和规则都懒了,还有画板功能也不怎么样,画起来会有延迟的...不能再说下去了....话说,做完这个后,在CodePreject发现一个好东西,也是一个画板来的,也是利用DrawingVisual ,但是比我这个画板强大多了,效率和功能都高一筹,放上传送门,让我们共同学习一下.最后,如果你有更好的做法,请不吝指教.
【WPF】WPF截屏的更多相关文章
- c# wpf 利用截屏键实现截屏功能
原文:c# wpf 利用截屏键实现截屏功能 最近做一个wpf程序需要截图功能,查找资料费了一些曲折,跟大家分享一下. 先是找到了这样一份代码: static class Scr ...
- WPF技术触屏上的应用系列(六): 视觉冲击、超炫系统主界面、系统入口效果实现
原文:WPF技术触屏上的应用系列(六): 视觉冲击.超炫系统主界面.系统入口效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体 ...
- WPF技术触屏上的应用系列(五): 图片列表异步加载、手指进行缩小、放大、拖动 、惯性滑入滑出等效果
原文:WPF技术触屏上的应用系列(五): 图片列表异步加载.手指进行缩小.放大.拖动 .惯性滑入滑出等效果 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统, ...
- WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放、图片立体轮播、图片倒影立体滚动)效果实现
原文:WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放.图片立体轮播.图片倒影立体滚动)效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7 ...
- WPF技术触屏上的应用系列(三): 视频播放器的使用及视频播放、播放、暂停、可拖动播放进度效果实现
原文:WPF技术触屏上的应用系列(三): 视频播放器的使用及视频播放.播放.暂停.可拖动播放进度效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,5 ...
- WPF技术触屏上的应用系列(一): 3D 图片(照片)墙、柱面墙(凹面墙或者叫远景墙、凸面墙或者叫近景墙)实现
原文:WPF技术触屏上的应用系列(一): 3D 图片(照片)墙.柱面墙(凹面墙或者叫远景墙.凸面墙或者叫近景墙)实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7 ...
- WPF技术触屏上的应用系列(二): 嵌入百度地图、API调用及结合本地数据库在地图上进行自定义标点的实现
原文:WPF技术触屏上的应用系列(二): 嵌入百度地图.API调用及结合本地数据库在地图上进行自定义标点的实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系 ...
- [WPF]程序全屏
原文:[WPF]程序全屏 代码: 使用:
- WPF Popup全屏 弹出方法。解决只显示75%的问题。
WPF Popup全屏 弹出方法.解决只显示75%的问题. WPF 中 Popup 有一个特点.当Popup的高度超过屏幕的75%的时候,只显示75%的高度. 如下代码: <Window x ...
随机推荐
- MaterialRefreshLayout+ListView 下拉刷新 上拉加载
效果图是这样的,有入侵式的,非入侵式的,带波浪效果的......就那几个属性,都给出来了,自己去试就行. 下拉刷新 上拉加载 关于下拉刷新-上拉加载的效果,有许许多多的实现方式,百度了一下竟然有几十种 ...
- Python+Selenium笔记(三):使用unittest
#网络很慢可能会运行报错 (一) 前言 Selenium WebDriver是一个浏览器自动化测试的API集合.它提供了很多与浏览器自动化交互的特性,并且这些API主要是用于测试Web程序.如果仅 ...
- Azure 元数据服务:适用于 Windows VM 的计划事件(预览)
计划事件是 Azure 元数据服务中的其中一个子服务. 它负责显示有关即将发生的事件(例如,重新启动)的信息,使应用程序可以为其做准备并限制中断. 它可用于所有 Azure 虚拟机类型(包括 PaaS ...
- Oracle EBS OPM close batch
--close_batch --created by jenrry DECLARE x_message_count NUMBER; x_message_list VARCHAR2 (4000); x_ ...
- Mariadb配置Galera集群
一.增加MariaDB源 cd /etc/yum.repos.d vi MariaDB.repo # MariaDB 10.1 CentOS repository list - created 201 ...
- 【转】Java十大常用框架介绍(spring系+dubbo+RabbitMQ+Ehcache+redis)
一.SpringMVC Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动 ...
- supervisor 使用系列之一
supervisor 使用系列之一 前几年自己用PHP写过一个服务守护的脚本,初步实现了被守护脚本的状态监控.优雅杀死.以及自动重启的功能.面试的时候也有问到,为什么不使用supervisor这个工具 ...
- October 10th 2017 Week 41st Tuesday
If you focus on what you left behind you will never see what lies ahead. 如果你只顾回头看,那么你永远也看不见前方有什么. Ye ...
- Xmind在win10更改用户设置后出现Invalid Configuration Location 错误的解决办法
错误原因: 因为一开始新建win10用户时,使用的是中文用户名,导致了部分软件比如IDEA读取C盘中配置文件时报错.我用管理员权限修改用户姓名为英文后,IDEA的问题虽然已经解决,但Xmind却报出了 ...
- 题解 P1120 【小木棍 [数据加强版]】
题面 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮 ...