前言  QQ、微信截图功能已很强大了,似乎没必要在开发一个截图程序了。但是有时QQ热键就是被占用,不能快速的开启截屏;有时,天天挂着QQ,领导也不乐意。既然是程序员,就要自己开发截屏工具,功能随心所欲,岂不快哉。

再强调一点:工具就是生产力!没有掌握WPF之前,我是不会开发这么一个程序的,如果采用MFC、winform框架,工作量是相当的大,开发出来的效果肯定也比较low。本人用WPF,花了一天多的功夫,开发了这个小程序。程序的定位就功能简单,平时工作不碍事,用着的时候,一键截图!

 界面  执行程序下载地址:一键截图,点我下载。  获取最新版本和其他相关工具,可加入QQ群:920519255;

为了不影响视觉, 程序主界面非常小。程序会在所有界面最前端展示。

有两个按钮1)“快捷截图”:截图后,立即将截图复制到剪切板。2)“截图+编辑”:截图后,可以在图上标注箭头和文字。

程序展开时,效果:

截图后,可编辑:

新增保留历史记录功能,选中历史记录,复制到剪切板。

截图类型:
静态:截取按下按钮那一刻的屏幕图片,图片是静止的(比如 截取视频,视频内容是静止的)。
动态:截屏内容是动态的,如果桌面有视频,是可以看到视频播放内容的。

看似简单,对开发技巧要求很高。内行看门道!

开发思路

  常言道:看到的不一定是真实的。开发也要这样。程序叫截屏,你不要一股劲想着怎么截取别的窗口图案,肯定很费劲!思虑就是掩人耳目:先将整个屏幕复制,放到自己程序窗体中,窗体最大化,覆盖整个屏幕!用户看到还是整个屏幕,但是整个屏幕已被偷梁换柱!此后,你所有的操作都是在自己窗体上处理,当然可以随心所欲了!

截取整个屏幕

  1. public Bitmap GetScreenSnapshot()
  2. {
  3. System.Drawing.Rectangle rc = SystemInformation.VirtualScreen;
  4. var bitmap = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
  5.  
  6. using (Graphics memoryGrahics = Graphics.FromImage(bitmap))
  7. {
  8. memoryGrahics.CopyFromScreen(rc.X, rc.Y, , , rc.Size, CopyPixelOperation.SourceCopy);
  9. }
  10.  
  11. return bitmap;
  12. }

创建全屏窗体

注意窗体属性,这样才能全面覆盖整个屏幕。

图层布局

这个很有技巧!为了实现非截图区域阴影效果,费了一番心机!即使这样,感觉也比winform用起来得心应手!

注:我不是一直贬低winform,但是要承认,这两个东西不是一个时代产物。wpf设计思路比winform先进很多。只是wpf新概念多,用的人少,开发起来常常蒙圈!经过一段迷茫期,前途就会光明了!

窗口的布局,不多说了!直接上代码。我对代码做了注释!

  1. <Window.Resources>
  2. <ControlTemplate x:Key="templatePushButton" TargetType="RadioButton">
  3. <Border x:Name="Part_Border" BorderThickness="1" BorderBrush="Gray"
  4. Background="{TemplateBinding Background}"
  5. Margin="{TemplateBinding Margin}"
  6. Padding="{TemplateBinding Padding}">
  7. <ContentPresenter></ContentPresenter>
  8. </Border>
  9.  
  10. <ControlTemplate.Triggers >
  11. <Trigger Property="IsChecked" Value="True">
  12. <Setter TargetName="Part_Border" Property="BorderBrush" Value="Blue"></Setter>
  13. </Trigger>
  14. <Trigger Property="IsMouseOver" Value="True">
  15. <Setter TargetName="Part_Border" Property="Background" Value="#FFb2dff9"></Setter>
  16. </Trigger>
  17. </ControlTemplate.Triggers>
  18. </ControlTemplate>
  19.  
  20. <Style x:Key="stylePushButton" TargetType="RadioButton">
  21. <Setter Property="VerticalAlignment" Value="Center"></Setter>
  22. <Setter Property="Padding" Value="8,5,8,5"></Setter>
  23. <Setter Property="Template" Value="{StaticResource templatePushButton}"></Setter>
  24. </Style>
  25.  
  26. </Window.Resources>
  27. <Grid Background="Green" >
  28. <!-- 整个屏幕图像 -->
  29. <Image x:Name="imgScreen"
  30. MouseDown="ImgScreen_MouseDown"
  31. MouseUp="ImgScreen_MouseUp"
  32. Stretch="None"
  33. MouseMove="ImgScreen_MouseMove">
  34. </Image>
  35.  
  36. <!-- 覆盖一层黑色,半透明状 -->
  37. <Grid x:Name="gridCover" Visibility="Collapsed" Background="Black" Opacity="0.5">
  38. </Grid>
  39.  
  40. <Grid>
  41. <Grid.RowDefinitions>
  42. <RowDefinition Height="*"></RowDefinition>
  43. <RowDefinition Height="auto"></RowDefinition>
  44. </Grid.RowDefinitions>
  45. <!-- 前面覆盖了一层黑色,但是截取的图像不能覆盖,只能在这里再显示截取图像 -->
  46. <Grid x:Name="gridCutImg"
  47. MouseDown="ImgCut_MouseDown"
  48. MouseMove="ImgCut_MouseMove"
  49. MouseUp="ImgCut_MouseUp">
  50. <Image x:Name="imgCut" Grid.RowSpan="3" Stretch="None"
  51. HorizontalAlignment="Left" VerticalAlignment="Top"></Image>
  52. <!--用来画箭头和文字-->
  53. <Canvas x:Name="canvasEdit" HorizontalAlignment='Left'
  54. VerticalAlignment="Top" Background="Transparent">
  55.  
  56. </Canvas>
  57. </Grid>
  58.  
  59. <!--显示提示信息-->
  60. <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
  61. FontSize="22" Foreground="Yellow"
  62. Opacity="0.8" >滑动鼠标开始截屏 截图保存到剪切板 按ESC键退出</TextBlock>
  63.  
  64. <StackPanel Grid.RowSpan="3">
  65. <Grid >
  66. <Grid.ColumnDefinitions>
  67. <ColumnDefinition Width="auto"></ColumnDefinition>
  68. <ColumnDefinition Width="*"></ColumnDefinition>
  69. </Grid.ColumnDefinitions>
  70. </Grid>
  71. <!--截图指示框-->
  72. <Border x:Name="borderSelect"
  73. HorizontalAlignment="Left" VerticalAlignment="Top"
  74. BorderThickness="1" BorderBrush="Red"></Border>
  75. <!--宽和高指示-->
  76. <Grid HorizontalAlignment="Stretch" >
  77. <Grid.ColumnDefinitions>
  78. <ColumnDefinition Width="auto"></ColumnDefinition>
  79. <ColumnDefinition Width="auto"></ColumnDefinition>
  80. </Grid.ColumnDefinitions>
  81. <TextBlock x:Name="txtCutInfo" Padding="8,5,8,5"
  82. HorizontalAlignment="Left"
  83. Background="White" VerticalAlignment="Center">1</TextBlock>
  84. <StackPanel x:Name="stackEdit" Orientation="Horizontal" HorizontalAlignment="Right" Grid.Column="1" Margin="2">
  85. <RadioButton x:Name="radioArrow" GroupName="editType" Click="RadioArrow_Click" Foreground="Black" Padding="10,5,10,5" Style="{StaticResource stylePushButton}"></RadioButton>
  86. <RadioButton x:Name="radioText" GroupName="editType" Click="RadioText_Click" Foreground="Black" Style="{StaticResource stylePushButton}"></RadioButton>
  87. <RadioButton x:Name="radioClose" Click="RadioClose_Click" Foreground="Red" Style="{StaticResource stylePushButton}">X</RadioButton>
  88. </StackPanel>
  89. </Grid>
  90.  
  91. </StackPanel>
  92.  
  93. </Grid>
  94. </Grid>

当鼠标移动时,不断的计算选中区域,设置borderSelect属性。

  1. private void ImgScreen_MouseMove(object sender, MouseEventArgs e)
  2. {
  3. if (!_isMouseDown)
  4. return;
  5.  
  6. gridCover.Visibility = Visibility.Visible;
  7.  
  8. //计算鼠标选中区域
  9. Point currentPoint = e.GetPosition(imgScreen);
  10. Point borderPoint = e.GetPosition(borderSelect);
  11.  
  12. double xDelta = xDelta_BoderToImgScreen;
  13. double yDelta = yDelta_BoderToImgScreen;
  14.  
  15. _rectImgCut = ImageHelper.ToRect(currentPoint, _startPoint);
  16.  
  17. Rect rectBoderCut = ImageHelper.ToRect(new Point(currentPoint.X + xDelta, currentPoint.Y + yDelta),
  18. new Point(_startPoint.X + xDelta, _startPoint.Y + yDelta));
  19.  
  20. //设置方框位置和大小
  21. Thickness thickness = new Thickness(rectBoderCut.Left, rectBoderCut.Top, , );
  22. borderSelect.SetValue(FrameworkElement.MarginProperty, thickness);
  23. imgCut.SetValue(FrameworkElement.MarginProperty, thickness);
  24.  
  25. thickness = new Thickness(rectBoderCut.Left, , , );
  26. txtCutInfo.SetValue(FrameworkElement.MarginProperty, thickness);
  27.  
  28. borderSelect.Width = Math.Abs(_startPoint.X - currentPoint.X);
  29. borderSelect.Height = Math.Abs(_startPoint.Y - currentPoint.Y);
  30. borderSelect.Visibility = Visibility.Visible;
  31.  
  32. //为了防止整个图 变暗,鼠标选中区域图像抠图,再在上层图像上显示
  33. imgCut.Source = GetBitmapCut();
  34.  
  35. Int32Rect imgDestRect = GetCutRect();
  36. txtCutInfo.Text = string.Format($"宽:{imgDestRect.Width} 高:{imgDestRect.Height}");
  37. }

到此,程序主要逻辑处理完毕!麻雀虽小五脏俱全!这里用到不少wpf布局技巧。这些技巧与winform处理思虑差别还是很大的!wpf虽然苦涩难懂,感觉一入候门深似海!如果坚持下来,就会感到豁然开朗,也理解了微软的一片苦心!

程序运行效果与QQ截图很类似了。顺着这个思虑往前走,完全可以开发出与QQ截图一样的效果!

采用WPF开发截图程序,so easy!的更多相关文章

  1. 采用WPF技术开发截图程序

    前言  QQ.微信截图功能已很强大了,似乎没必要在开发一个截图程序了.但是有时QQ热键就是被占用,不能快速的开启截屏:有时,天天挂着QQ,领导也不乐意.既然是程序员,就要自己开发截屏工具,功能随心所欲 ...

  2. OFD电子证照模版制作工具 --(采用wpf开发)

    前言  ofd应用的范围非常广,电子证照是其中非常重要的一个应用.同一类电子证照具有相同的板式.元数据:所以电子证照非常适合用模版来制作.模版就是板式样式固定,每个具体的证照只是文字或图片内容不同.比 ...

  3. 采用WPF开发第二版OFD阅读器,持续完善中,敬请期待!

    本人研究OFD多年,采用C#和QT开发了一系列ofd相关软件.在这些产品中,阅读器始终占据着非常重要的位置.可以说,阅读器是直接面向最终客户的产品.是集OFD各类知识之大成的产品.市面上的阅读器产品林 ...

  4. pdf文件内容查看器 -- 采用wpf开发

    前言 pdf是一种应用非常广的版式文档格式,已成为事实上的国际标准.关于pdf格式的文章汗牛充栋,本文也是关于pdf格式的文章,但是本文不是纸上谈兵:本人这几周一直研究pdf格式内容,不但对pfd格式 ...

  5. OFD电子文档阅读器功能说明(采用WPF开发,永久免费)

    特别说明 ofd阅读器开发语言为c#,具有完全自主产权,没有使用第三方ofd开发包.可以根据你的需求快速定制开发.本阅读器还在开发完善阶段,如有任何问题,可以联系我QQ:13712486.博客:htt ...

  6. 采用WPF技术,开发OFD电子文档阅读器

    前言 OFD是国家标准版式文档格式,于2016年生效.OFD文档国家标准参见<电子文件存储与交换格式版式文档>.既然是国家标准,OFD随后肯定会首先在政务系统使用,并逐步推向社会各个方面. ...

  7. WPF 开发自动开机启动程序

    原文:WPF 开发自动开机启动程序 本文告诉大家如何在 WPF 开发一个可以自动启动的程序 本文使用的自动开机启动方法是通过快捷方式放在启动文件夹的方式. 创建快捷方式 /// <summary ...

  8. SharePoint采用BCS开发第一个应用程序(两)

    SharePoint采用BCS开发第一个应用程序(两) 创建外部数据源 在本章中,我们使用AdventureWorksLT2008 SQL Server数据库作为外部数据源.下图显示了表SalesLT ...

  9. WPF开发的彩票程序(练手好例子) 附源码

    前言 WPF是.NET最新的界面开发库,开发界面非常灵活!但是学习WPF难度也非常大. 应朋友之邀,编写了一个小程序.程序虽小,五脏俱全,WPF开发的灵活性可窥见一斑. 对于新手学习有很好的借鉴意义, ...

随机推荐

  1. springboot应用监控和管理

    spring boot应用监控和管理 Spring Boot 监控核心是 spring-boot-starter-actuator 依赖,增加依赖后, Spring Boot 会默认配置一些通用的监控 ...

  2. springCloud相关学习资料

    SpringCloud相关学习资料 SpringCloud资料参考: 1. 史上最简单的 SpringCloud 教程 | 终章 2. Spring Cloud基础教程 SpringCloud相关: ...

  3. 在eclipse中引入mybatis和spring的约束文件

    eclipse中引入mybatis约束文件步骤: 首先: config的key值 http://mybatis.org/dtd/mybatis-3-config.dtd mapper的key值 htt ...

  4. 爬取凤凰网站财经类的新闻,函数时编程,可全部实现,由于内容量大,需要时间太长,服务器会禁止,为了防止,可以将time.sleep()设置的时间长点

    import requests from selenium import webdriver import time def grasp(urlT): driver = webdriver.Chrom ...

  5. group by语法

    group by 用法解析 group by语法可以根据给定数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表. SELECT子句中的列名必须为分组列或列函数.列函数对于GROUP BY子 ...

  6. 关于样式style

    今天看到了一个bgcolor和以前看过的background-color,特意查了一下区别 百度是这么说的:background-color是标准CSS属性,bgcolor应该是IE扩展的html元素 ...

  7. 使用opencv训练分类器时,traincascade训练报错:Train dataset for temp stage can not be filled.解决方法

    opencv分类器训练中,出错一般都是路径出错,例如, 1.opencv_traincascade.exe路径 2.负样本路径文件,neg.dat中的样本前路径是否正确 3.移植到别的电脑并修改完路径 ...

  8. js 事件委托获取子元素下标

    html:部分 <ul> <li>第一个</li> <li>第二个</li> <li>第三个</li> <li ...

  9. CentOS7.2防火墙配置

    一.查看firewall以及firewall服务的状态. # 查看firewall服务状态 systemctl status firewalld # 查看firewall状态 firewall-cmd ...

  10. FourAndSix2 靶机渗透

    0x01 简介 FourAndSix2是易受攻击的一个靶机,主要任务是通过入侵进入到目标靶机系统然后提权,并在root目录中并读取flag.tx信息 FourAndSix2.镜像下载地址: https ...