原文:【WPF】WPF截屏

引言

.NET的截图控件在网上流传得不多啊,难得发现一个精品截图控件( 传送门),但是无奈是winform的.后来又找到一个周银辉做的WPF截图(继续传送门),发现截屏是实现了,但是功能略少了点.So,打算自己用WPF去实现一个,无奈略渣,还是简单分享一下吧.

一个Window和一个Canvas

Window是截图的主界面,但是设置好WindowStyle和WindowState就基本没它什么事了,Window里面放个Canvas,Canvas主要承载当前的截屏和画板DrawingPannel以及工具控件.先看看Window和Canvas的代码吧,如下

  1. <Window x:Class="WpfCapture.Window3"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:wpfCapture="clr-namespace:WpfCapture"
  5. Title="Window3" Height="" Width="" WindowStyle="None" WindowState="Maximized">
  6. <Canvas Name="xgrid" >
  7. </Canvas>
  8. </Window>

什么时候加载当前截屏,怎样加载,看代码

  1. public Window3()
  2. {
  3. InitializeComponent();
  4. screenSnapshot = GetScreenSnapshot();
  5. var bmp = ToBitmapSource(screenSnapshot);
  6. bmp.Freeze();
  7. this.xgrid.Background = new ImageBrush(bmp);
  8. }
  9.  
  10. public Bitmap GetScreenSnapshot()
  11. {
  12. try
  13. {
  14. System.Drawing.Rectangle rc = SystemInformation.VirtualScreen;
  15. var bitmap = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  16.  
  17. using (Graphics memoryGrahics = Graphics.FromImage(bitmap))
  18. {
  19. memoryGrahics.CopyFromScreen(rc.X, rc.Y, , , rc.Size, CopyPixelOperation.SourceCopy);
  20. }
  21.  
  22. return bitmap;
  23. }
  24.  
  25. catch (Exception)
  26. {
  27.  
  28. }
  29. return null;
  30. }

画板DrawingPannel

画板DrawingPannel是自定义的一个布局控件类,主要是用来显示DrawingVisual对象的,类定义如下:

  1. public class DrawingCanvas : Panel
  2. {
  3. private List<Visual> visuals = new List<Visual>();
  4.  
  5. protected override Visual GetVisualChild(int index)
  6. {
  7. return visuals[index];
  8. }
  9. protected override int VisualChildrenCount
  10. {
  11. get
  12. {
  13. return visuals.Count;
  14. }
  15. }
  16.  
  17. public void RemoveLastVisual()
  18. {
  19. if (visuals.Count > )
  20. {
  21.  
  22. var item= visuals.FindLast(x => true);
  23. DeleteVisual(item);
  24. }
  25.  
  26. }
  27.  
  28. public void AddVisual(Visual visual)
  29. {
  30. visuals.Add(visual);
  31.  
  32. base.AddVisualChild(visual);
  33. base.AddLogicalChild(visual);
  34. Console.WriteLine(visuals.Count);
  35. }
  36.  
  37. public void DeleteVisual(Visual visual)
  38. {
  39. visuals.Remove(visual);
  40.  
  41. base.RemoveVisualChild(visual);
  42. base.RemoveLogicalChild(visual);
  43. }
  44. }

既然画板有了,当然不能漏了画笔等操作工具,所以最终界面XAML描述如下

  1. <Window x:Class="WpfCapture.Window3"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:wpfCapture="clr-namespace:WpfCapture"
  5. Title="Window3" Height="" Width="" WindowStyle="None" WindowState="Maximized">
  6. <Canvas Name="xgrid" >
  7. <wpfCapture:DrawingCanvas x:Name="grid" Background="AliceBlue" Canvas.Top="" Canvas.Left="" Width="{Binding ActualWidth,ElementName=xgrid}"
  8. Height="{Binding ActualHeight,ElementName=xgrid}"
  9. Opacity="0.8" MouseLeftButtonDown="Grid_OnMouseLeftButtonDown" PreviewMouseMove="grid_PreviewMouseMove_1" MouseLeftButtonUp="Grid_OnMouseLeftButtonUp"
  10. MouseMove="grid_MouseMove_2" MouseRightButtonDown="grid_MouseRightButtonDown_1"
  11. >
  12. </wpfCapture:DrawingCanvas>
  13.  
  14. <StackPanel Orientation="Horizontal" Name="toolpanel" Visibility="Collapsed" Height="" Width="">
  15. <ToolBar>
  16. <RadioButton GroupName="tool" Name="Arrow" >
  17. <Image Source="./icons/Arrow.ico"></Image>
  18. </RadioButton>
  19. <RadioButton GroupName="tool" Name="Rectangular">
  20.  
  21. <Image Source="./icons/Rectangular.ico"></Image>
  22. </RadioButton>
  23. <RadioButton GroupName="tool" Name="Line">
  24. <Image Source="./icons/Line.ico"></Image>
  25. </RadioButton>
  26.  
  27. <Button Click="Button_Click_2">
  28. <Image Source="./icons/Redo.png"></Image>
  29. </Button>
  30. <Button>
  31. <Image Source="./icons/Exit.ico"></Image>
  32. </Button>
  33. <Button Click="Button_Click_1">
  34. <Image Source="./icons/Accept.ico"></Image>
  35. </Button>
  36. </ToolBar>
  37. </StackPanel>
  38. </Canvas>
  39. </Window>

如何指定截图方框

如何画截图边框出来呢.其实上面已经有画板了,那么我们只需要在上面画个方框,再将工具栏显示出来,那么好像有点像样了.如何画?需要用到DrawingVisual类,画框的方法如下:

  1. private void DrawSquare1(DrawingVisual visual)
  2. {
  3. using (DrawingContext dc = visual.RenderOpen())
  4. {
  5. dc.DrawRectangle(drawingBrush, drawingPen,
  6. new Rect(startPoint, endPoint));
  7. }
  8. }

在鼠标事件中利用上面那个方法轻松画出方框,然后接下来我就用笨方法了,在画出方框后,我new了一个新的DrawingCanvas替代方框,再从一开始截屏图片中截取相应的图片作为DrawingCanvas的背景,在这个过程中要注意DPI值的转换,我的电脑是120的DPI,所以从WPF的单位转换为真正分辨率单位时要乘以1.25.

  1. //得到DPI比例
  2. Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
  3. systemdpi = graphics.DpiX / ;
  1. //得到截图方框的背景
  2. private BitmapSource CopyFromScreenSnapshot()
  3. {
  4. 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));
  5. var destRect = new System.Drawing.Rectangle(, , (int)(sourceRect.Width * systemdpi), (int)(sourceRect.Height * systemdpi));
  6. if (screenSnapshot != null)
  7. {
  8. var bitmap = new Bitmap((int)(sourceRect.Width * systemdpi), (int)(sourceRect.Height * systemdpi), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  9. using (Graphics g = Graphics.FromImage(bitmap))
  10. {
  11. g.DrawImage(screenSnapshot, destRect, sourceRect, GraphicsUnit.Pixel);
  12. }
  13. return ToBitmapSource(bitmap);
  14. }
  15. return null;
  16. }

画板工具

画板工具我只定义了几个一个线段,方框和钢笔,也有后退,退出和完成截图工具.直接看代码好了

  1. //画方框
  2. private void DrawSquare(System.Windows.Point point1, System.Windows.Point point2)
  3. {
  4. using (DrawingContext dc = selectionSquare.RenderOpen())
  5. {
  6. dc.DrawRectangle(selectionSquareBrush, selectionSquarePen,
  7. new Rect(point1, point2));
  8. }
  9. }
  10. //画箭头....好吧,是画直线
  11. private void DrawArrow(System.Windows.Point point1, System.Windows.Point point2)
  12. {
  13. using (DrawingContext dc = selectionSquare.RenderOpen())
  14. {
  15. dc.DrawLine(selectionSquarePen, point1, point2);
  16. }
  17. }
  18.  
  19. PathGeometry pgGeometry = new PathGeometry();
  20. PathFigure pfFigure = new PathFigure();
  21. //画钢笔线
  22. private void DrawLine(System.Windows.Point point1, System.Windows.Point point2)
  23. {
  24. using (DrawingContext dc = selectionSquare.RenderOpen())
  25. {
  26. LineSegment lsLineSegment = new LineSegment(point2, true);
  27.  
  28. pfFigure.Segments.Add(lsLineSegment);
  29.  
  30. Console.WriteLine(point2.Y);
  31.  
  32. pgGeometry.Figures.Add(pfFigure);
  33.  
  34. dc.DrawGeometry(selectionSquareBrush, selectionSquarePen, pgGeometry);
  35. }
  36. }

各种鼠标方法我就不一一标出来了,最终效果如下:

小结

其实一句话可以说完整个实现的:将Canvas背景设置为当前屏幕,画个框放画板,在画板上涂涂画画,然后将画板转成图片.多简单,但是上面还有好多细节没有说到,也有比较多功能没有实现,例如拖拉边框等功能.因为是纯练习,代码注释和规则都懒了,还有画板功能也不怎么样,画起来会有延迟的...不能再说下去了....话说,做完这个后,在CodePreject发现一个好东西,也是一个画板来的,也是利用DrawingVisual ,但是比我这个画板强大多了,效率和功能都高一筹,放上传送门,让我们共同学习一下.最后,如果你有更好的做法,请不吝指教.

【WPF】WPF截屏的更多相关文章

  1. c# wpf 利用截屏键实现截屏功能

    原文:c# wpf 利用截屏键实现截屏功能     最近做一个wpf程序需要截图功能,查找资料费了一些曲折,跟大家分享一下.     先是找到了这样一份代码:     static class Scr ...

  2. WPF技术触屏上的应用系列(六): 视觉冲击、超炫系统主界面、系统入口效果实现

    原文:WPF技术触屏上的应用系列(六): 视觉冲击.超炫系统主界面.系统入口效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,54寸大屏电脑电视一体 ...

  3. WPF技术触屏上的应用系列(五): 图片列表异步加载、手指进行缩小、放大、拖动 、惯性滑入滑出等效果

    原文:WPF技术触屏上的应用系列(五): 图片列表异步加载.手指进行缩小.放大.拖动 .惯性滑入滑出等效果 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统, ...

  4. WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放、图片立体轮播、图片倒影立体滚动)效果实现

    原文:WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放.图片立体轮播.图片倒影立体滚动)效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7 ...

  5. WPF技术触屏上的应用系列(三): 视频播放器的使用及视频播放、播放、暂停、可拖动播放进度效果实现

    原文:WPF技术触屏上的应用系列(三): 视频播放器的使用及视频播放.播放.暂停.可拖动播放进度效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系统,5 ...

  6. WPF技术触屏上的应用系列(一): 3D 图片(照片)墙、柱面墙(凹面墙或者叫远景墙、凸面墙或者叫近景墙)实现

    原文:WPF技术触屏上的应用系列(一): 3D 图片(照片)墙.柱面墙(凹面墙或者叫远景墙.凸面墙或者叫近景墙)实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7 ...

  7. WPF技术触屏上的应用系列(二): 嵌入百度地图、API调用及结合本地数据库在地图上进行自定义标点的实现

    原文:WPF技术触屏上的应用系列(二): 嵌入百度地图.API调用及结合本地数据库在地图上进行自定义标点的实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7操作系 ...

  8. [WPF]程序全屏

    原文:[WPF]程序全屏 代码: 使用:

  9. WPF Popup全屏 弹出方法。解决只显示75%的问题。

    WPF Popup全屏 弹出方法.解决只显示75%的问题.   WPF 中 Popup 有一个特点.当Popup的高度超过屏幕的75%的时候,只显示75%的高度. 如下代码: <Window x ...

随机推荐

  1. MaterialRefreshLayout+ListView 下拉刷新 上拉加载

    效果图是这样的,有入侵式的,非入侵式的,带波浪效果的......就那几个属性,都给出来了,自己去试就行. 下拉刷新 上拉加载 关于下拉刷新-上拉加载的效果,有许许多多的实现方式,百度了一下竟然有几十种 ...

  2. Python+Selenium笔记(三):使用unittest

    #网络很慢可能会运行报错 (一)   前言 Selenium WebDriver是一个浏览器自动化测试的API集合.它提供了很多与浏览器自动化交互的特性,并且这些API主要是用于测试Web程序.如果仅 ...

  3. Azure 元数据服务:适用于 Windows VM 的计划事件(预览)

    计划事件是 Azure 元数据服务中的其中一个子服务. 它负责显示有关即将发生的事件(例如,重新启动)的信息,使应用程序可以为其做准备并限制中断. 它可用于所有 Azure 虚拟机类型(包括 PaaS ...

  4. Oracle EBS OPM close batch

    --close_batch --created by jenrry DECLARE x_message_count NUMBER; x_message_list VARCHAR2 (4000); x_ ...

  5. Mariadb配置Galera集群

    一.增加MariaDB源 cd /etc/yum.repos.d vi MariaDB.repo # MariaDB 10.1 CentOS repository list - created 201 ...

  6. 【转】Java十大常用框架介绍(spring系+dubbo+RabbitMQ+Ehcache+redis)

    一.SpringMVC Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动 ...

  7. supervisor 使用系列之一

    supervisor 使用系列之一 前几年自己用PHP写过一个服务守护的脚本,初步实现了被守护脚本的状态监控.优雅杀死.以及自动重启的功能.面试的时候也有问到,为什么不使用supervisor这个工具 ...

  8. October 10th 2017 Week 41st Tuesday

    If you focus on what you left behind you will never see what lies ahead. 如果你只顾回头看,那么你永远也看不见前方有什么. Ye ...

  9. Xmind在win10更改用户设置后出现Invalid Configuration Location 错误的解决办法

    错误原因: 因为一开始新建win10用户时,使用的是中文用户名,导致了部分软件比如IDEA读取C盘中配置文件时报错.我用管理员权限修改用户姓名为英文后,IDEA的问题虽然已经解决,但Xmind却报出了 ...

  10. 题解 P1120 【小木棍 [数据加强版]】

    题面 乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍的长度,编程帮 ...