采用WPF开发截图程序,so easy!
前言 QQ、微信截图功能已很强大了,似乎没必要在开发一个截图程序了。但是有时QQ热键就是被占用,不能快速的开启截屏;有时,天天挂着QQ,领导也不乐意。既然是程序员,就要自己开发截屏工具,功能随心所欲,岂不快哉。
再强调一点:工具就是生产力!没有掌握WPF之前,我是不会开发这么一个程序的,如果采用MFC、winform框架,工作量是相当的大,开发出来的效果肯定也比较low。本人用WPF,花了一天多的功夫,开发了这个小程序。程序的定位就功能简单,平时工作不碍事,用着的时候,一键截图!
界面 执行程序下载地址:一键截图,点我下载。 获取最新版本和其他相关工具,可加入QQ群:920519255;

为了不影响视觉, 程序主界面非常小。程序会在所有界面最前端展示。
有两个按钮1)“快捷截图”:截图后,立即将截图复制到剪切板。2)“截图+编辑”:截图后,可以在图上标注箭头和文字。
程序展开时,效果:


截图后,可编辑:

新增保留历史记录功能,选中历史记录,复制到剪切板。
截图类型:
静态:截取按下按钮那一刻的屏幕图片,图片是静止的(比如 截取视频,视频内容是静止的)。
动态:截屏内容是动态的,如果桌面有视频,是可以看到视频播放内容的。
看似简单,对开发技巧要求很高。内行看门道!
开发思路
常言道:看到的不一定是真实的。开发也要这样。程序叫截屏,你不要一股劲想着怎么截取别的窗口图案,肯定很费劲!思虑就是掩人耳目:先将整个屏幕复制,放到自己程序窗体中,窗体最大化,覆盖整个屏幕!用户看到还是整个屏幕,但是整个屏幕已被偷梁换柱!此后,你所有的操作都是在自己窗体上处理,当然可以随心所欲了!
截取整个屏幕
public Bitmap GetScreenSnapshot()
{
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;
}
创建全屏窗体

注意窗体属性,这样才能全面覆盖整个屏幕。
图层布局
这个很有技巧!为了实现非截图区域阴影效果,费了一番心机!即使这样,感觉也比winform用起来得心应手!
注:我不是一直贬低winform,但是要承认,这两个东西不是一个时代产物。wpf设计思路比winform先进很多。只是wpf新概念多,用的人少,开发起来常常蒙圈!经过一段迷茫期,前途就会光明了!
窗口的布局,不多说了!直接上代码。我对代码做了注释!
<Window.Resources>
<ControlTemplate x:Key="templatePushButton" TargetType="RadioButton">
<Border x:Name="Part_Border" BorderThickness="1" BorderBrush="Gray"
Background="{TemplateBinding Background}"
Margin="{TemplateBinding Margin}"
Padding="{TemplateBinding Padding}">
<ContentPresenter></ContentPresenter>
</Border> <ControlTemplate.Triggers >
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Part_Border" Property="BorderBrush" Value="Blue"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Part_Border" Property="Background" Value="#FFb2dff9"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate> <Style x:Key="stylePushButton" TargetType="RadioButton">
<Setter Property="VerticalAlignment" Value="Center"></Setter>
<Setter Property="Padding" Value="8,5,8,5"></Setter>
<Setter Property="Template" Value="{StaticResource templatePushButton}"></Setter>
</Style> </Window.Resources>
<Grid Background="Green" >
<!-- 整个屏幕图像 -->
<Image x:Name="imgScreen"
MouseDown="ImgScreen_MouseDown"
MouseUp="ImgScreen_MouseUp"
Stretch="None"
MouseMove="ImgScreen_MouseMove">
</Image> <!-- 覆盖一层黑色,半透明状 -->
<Grid x:Name="gridCover" Visibility="Collapsed" Background="Black" Opacity="0.5">
</Grid> <Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<!-- 前面覆盖了一层黑色,但是截取的图像不能覆盖,只能在这里再显示截取图像 -->
<Grid x:Name="gridCutImg"
MouseDown="ImgCut_MouseDown"
MouseMove="ImgCut_MouseMove"
MouseUp="ImgCut_MouseUp">
<Image x:Name="imgCut" Grid.RowSpan="3" Stretch="None"
HorizontalAlignment="Left" VerticalAlignment="Top"></Image>
<!--用来画箭头和文字-->
<Canvas x:Name="canvasEdit" HorizontalAlignment='Left'
VerticalAlignment="Top" Background="Transparent"> </Canvas>
</Grid> <!--显示提示信息-->
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="22" Foreground="Yellow"
Opacity="0.8" >滑动鼠标开始截屏 截图保存到剪切板 按ESC键退出</TextBlock> <StackPanel Grid.RowSpan="3">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
</Grid>
<!--截图指示框-->
<Border x:Name="borderSelect"
HorizontalAlignment="Left" VerticalAlignment="Top"
BorderThickness="1" BorderBrush="Red"></Border>
<!--宽和高指示-->
<Grid HorizontalAlignment="Stretch" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock x:Name="txtCutInfo" Padding="8,5,8,5"
HorizontalAlignment="Left"
Background="White" VerticalAlignment="Center">1</TextBlock>
<StackPanel x:Name="stackEdit" Orientation="Horizontal" HorizontalAlignment="Right" Grid.Column="1" Margin="2">
<RadioButton x:Name="radioArrow" GroupName="editType" Click="RadioArrow_Click" Foreground="Black" Padding="10,5,10,5" Style="{StaticResource stylePushButton}">↑</RadioButton>
<RadioButton x:Name="radioText" GroupName="editType" Click="RadioText_Click" Foreground="Black" Style="{StaticResource stylePushButton}">文</RadioButton>
<RadioButton x:Name="radioClose" Click="RadioClose_Click" Foreground="Red" Style="{StaticResource stylePushButton}">X</RadioButton>
</StackPanel>
</Grid> </StackPanel> </Grid>
</Grid>
当鼠标移动时,不断的计算选中区域,设置borderSelect属性。
private void ImgScreen_MouseMove(object sender, MouseEventArgs e)
{
if (!_isMouseDown)
return; gridCover.Visibility = Visibility.Visible; //计算鼠标选中区域
Point currentPoint = e.GetPosition(imgScreen);
Point borderPoint = e.GetPosition(borderSelect); double xDelta = xDelta_BoderToImgScreen;
double yDelta = yDelta_BoderToImgScreen; _rectImgCut = ImageHelper.ToRect(currentPoint, _startPoint); Rect rectBoderCut = ImageHelper.ToRect(new Point(currentPoint.X + xDelta, currentPoint.Y + yDelta),
new Point(_startPoint.X + xDelta, _startPoint.Y + yDelta)); //设置方框位置和大小
Thickness thickness = new Thickness(rectBoderCut.Left, rectBoderCut.Top, , );
borderSelect.SetValue(FrameworkElement.MarginProperty, thickness);
imgCut.SetValue(FrameworkElement.MarginProperty, thickness); thickness = new Thickness(rectBoderCut.Left, , , );
txtCutInfo.SetValue(FrameworkElement.MarginProperty, thickness); borderSelect.Width = Math.Abs(_startPoint.X - currentPoint.X);
borderSelect.Height = Math.Abs(_startPoint.Y - currentPoint.Y);
borderSelect.Visibility = Visibility.Visible; //为了防止整个图 变暗,鼠标选中区域图像抠图,再在上层图像上显示
imgCut.Source = GetBitmapCut(); Int32Rect imgDestRect = GetCutRect();
txtCutInfo.Text = string.Format($"宽:{imgDestRect.Width} 高:{imgDestRect.Height}");
}
到此,程序主要逻辑处理完毕!麻雀虽小五脏俱全!这里用到不少wpf布局技巧。这些技巧与winform处理思虑差别还是很大的!wpf虽然苦涩难懂,感觉一入候门深似海!如果坚持下来,就会感到豁然开朗,也理解了微软的一片苦心!
程序运行效果与QQ截图很类似了。顺着这个思虑往前走,完全可以开发出与QQ截图一样的效果!
采用WPF开发截图程序,so easy!的更多相关文章
- 采用WPF技术开发截图程序
前言 QQ.微信截图功能已很强大了,似乎没必要在开发一个截图程序了.但是有时QQ热键就是被占用,不能快速的开启截屏:有时,天天挂着QQ,领导也不乐意.既然是程序员,就要自己开发截屏工具,功能随心所欲 ...
- OFD电子证照模版制作工具 --(采用wpf开发)
前言 ofd应用的范围非常广,电子证照是其中非常重要的一个应用.同一类电子证照具有相同的板式.元数据:所以电子证照非常适合用模版来制作.模版就是板式样式固定,每个具体的证照只是文字或图片内容不同.比 ...
- 采用WPF开发第二版OFD阅读器,持续完善中,敬请期待!
本人研究OFD多年,采用C#和QT开发了一系列ofd相关软件.在这些产品中,阅读器始终占据着非常重要的位置.可以说,阅读器是直接面向最终客户的产品.是集OFD各类知识之大成的产品.市面上的阅读器产品林 ...
- pdf文件内容查看器 -- 采用wpf开发
前言 pdf是一种应用非常广的版式文档格式,已成为事实上的国际标准.关于pdf格式的文章汗牛充栋,本文也是关于pdf格式的文章,但是本文不是纸上谈兵:本人这几周一直研究pdf格式内容,不但对pfd格式 ...
- OFD电子文档阅读器功能说明(采用WPF开发,永久免费)
特别说明 ofd阅读器开发语言为c#,具有完全自主产权,没有使用第三方ofd开发包.可以根据你的需求快速定制开发.本阅读器还在开发完善阶段,如有任何问题,可以联系我QQ:13712486.博客:htt ...
- 采用WPF技术,开发OFD电子文档阅读器
前言 OFD是国家标准版式文档格式,于2016年生效.OFD文档国家标准参见<电子文件存储与交换格式版式文档>.既然是国家标准,OFD随后肯定会首先在政务系统使用,并逐步推向社会各个方面. ...
- WPF 开发自动开机启动程序
原文:WPF 开发自动开机启动程序 本文告诉大家如何在 WPF 开发一个可以自动启动的程序 本文使用的自动开机启动方法是通过快捷方式放在启动文件夹的方式. 创建快捷方式 /// <summary ...
- SharePoint采用BCS开发第一个应用程序(两)
SharePoint采用BCS开发第一个应用程序(两) 创建外部数据源 在本章中,我们使用AdventureWorksLT2008 SQL Server数据库作为外部数据源.下图显示了表SalesLT ...
- WPF开发的彩票程序(练手好例子) 附源码
前言 WPF是.NET最新的界面开发库,开发界面非常灵活!但是学习WPF难度也非常大. 应朋友之邀,编写了一个小程序.程序虽小,五脏俱全,WPF开发的灵活性可窥见一斑. 对于新手学习有很好的借鉴意义, ...
随机推荐
- 'mvn' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
一定要发现自己的问题不要盲目从众 1.把maven的安装包解压 2.配置环境变量 3.配置path路径 4.在dos下测试一下 结果出现:'mvn' 不是内部或外部命令,也不是可运行的程序 或批处理文 ...
- 4.cache每个参数的意义和作用以及工作原理?
在程序开发过程中,适当使用 Cache 缓存能有效提高程序执行效率.比如一些常常调用的系统公共变量,把它们缓存到 Cache 中,当需要使用它们时,直接从 Cache 中读取,不必每次都从数据库或文件 ...
- FreeSql (一)入门
FreeSql 是一个功能强大的对象关系映射程序(O/RM),支持 .NETCore 2.1+ 或 .NETFramework 4.5+(QQ群:4336577) FreeSql采用MIT开源协议托管 ...
- 64位linux编译32位程序
昨天接到的任务,编译64位和32位两个版本的.so动态库给其他部门,我的ubuntu虚拟机是64位的,编译32位时遇到了问题: /usr/bin/ld: cannot find -lstdc++ 最后 ...
- JDK13,不如温习下Java8
JDK13于9月17号正式GA,版本新特性可参考: https://www.oschina.net/news/109934/jdk-13-released 虽然JDK更新迅速,但开发者貌似并不买账,据 ...
- 装系统 ------ 使用微PE 做系统盘
1.什么是PE系统 pe系统是一种装系统的系统,也就是预装系统的系统,它是一种系统预装环境和工具. 可以放在U盘或光盘里随身携带,可以用来给电脑装系统 2.常见的制作pe 系统的工具 大白菜,U启动, ...
- Vue-学习笔记0-独立项目搭建
前言 搭建Vue+Webpack项目,使用vue-cli搭建项目. 准备 vue独立项目依赖node的npm包管理器,所以需要先安装node. 相关的npm常用命令文章: Npm-常用命令,点击访问 ...
- Mybatis源码解析,一步一步从浅入深(六):映射代理类的获取
在文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码中我们提到了两个问题: 1,为什么在以前的代码流程中从来没有addMapper,而这里却有getMapper? 2,UserDao ...
- SpringBoot数据聚合(spring-boot-data-aggregator-starter)
背景 接口开发是后端开发中最常见的场景, 可能是RESTFul接口, 也可能是RPC接口. 接口开发往往是从各处捞出数据, 然后组装成结果, 特别是那些偏业务的接口. 例如, 我现在需要实现一个接口, ...
- Angular template ng-template/container/content
1. ng-template 形式:<ng-template>...</ng-template> 默认ng-template中的内容会隐藏; 可通过[ngIf]来控制内容显示隐 ...