[C# 开发技巧]实现属于自己的截图工具

一、引言

之前一直都是写一些C#基础知识的内容的,然而有些初学者可能看完了这些基础知识之后,会有这样一个疑惑的——我了解了这些基础知识之后,我想做一些工具怎么还是不会做的呢?那些基础知识到底有什么用的了?然而我刚开始写这个系列的初衷主要是我想系统地去研究下C#各个阶段的特性的,及时有些特性我知道它是怎么用的,但是每次遇到问题的时候确实百度可以可以解决很多问题,但是自己总是觉得有点“虚”,然而通过写完这个系列之后,我很多知识点都可以串起来了,可以做到一个举一反三的一个效果的,当我遇到实际问题的也不可能完全自己写出来,同样也会百度找解决方案,但是此时我却没有 “虚”的感觉,因为我知道这个东西,并且我也知道如何正确的百度这个问题。所以对于基础知识的学习还是很有必要的,因为系统学完之后,你可以更好地找到你遇到问题的答案,因为我有时候会看到一些朋友在QQ群中提到,遇到某个问题都不知道百度什么的,然而系统地学习基础完全可以帮助你快速地百度,(其实找答案也是一种能力),然而对于第一个疑惑的解答就是——系统学习完,确实刚开始的确开发工具不会做,但是实际写代码是很简单,并且现在大部分应用你百度下都可以找到的,所以代码并不是问题,主要是解决问题的思路,并且实际工具的开发也是对一个基础知识的巩固,从而对问题达到一个举一反三的效果。

上面说了这么多的(可能说的有点多),主要是让大家明白,系统学习C#基础知识是很有必要的,系统学习完C#基础知识之后就是代码量的积累了,也就是自己做一些小工具,积累到一定代码量之后,就可以尝试写写一些大的项目或开源项目等,所以在后面的系列中将会分享一些具体工具的开发,同时这也是我自己的一个学习的计划,这里分享给大家希望对一些迷茫的朋友有所帮助。如果你现在还没有明确或更好地目标,并且也是从事.NET工作或学习的朋友,那就和我一起静下心来学编程,下面是我的一个学习方向图(可能多少有点偏差,相信大致意图大家可以明白):

二、实现思路

啰嗦了这么多,下面就具体介绍下实现截图工具的实现思路。

为了让大家更清楚地知道如何去实现自己的截图工具,首先我来描述下截图的一个过程——我们使用QQ的截图工具和Windows 自带的截图工具都可以发现,当我们点击QQ窗体中的截图按钮时,此时我们将看到一个全屏图片,然后我们可以在其上截图,当鼠标左键按下时,即代表开始截图,并我们可以移动鼠标来改变截图的大小,鼠标弹起时即代表结束截图,此时我们可以双击矩形区域完全截图,并且可以通过粘贴操作把截取的图片粘贴到聊天窗口的发送区,鼠标右键点击则是退出截图。这样我们截图的过程描述就是这样的,从这个描述中我们就可以抽象出实现我们截图工具的思路来:

  1. 从 “此时我们将看到一个全屏图片”这句话描述我们应该抽象为——对于QQ截图工具的实现来说,我们看到的这个全屏图片其实并不是一张“图片”(这里最好不要钻空子),而是一个窗体,这个窗体我们命名为 “截图窗体”,只是把窗体的背景图片设置为全屏图片。说到这里,一些没有研究过QQ截图工具的人开始有疑问了——我们看到的是窗体?那为什么边框的,即没有最大化按钮,最下化按钮的呢?(对于这点的解释就是,程序中可以设置Form的BorderStyle属性为none的方式来隐藏掉边框)。
  2. 既然要设置窗体的背景图片为全屏图片,我们知道设置背景图片只需要设置窗体的BackgroundImage属性就好了,但是全屏图片怎么获取呢?既然是全屏图片,自然我就应该使窗体最大化话了,不然我们看到只是一个没有边框的“小图片”了,而不是一个全屏的图片。下面是具体实现这个分析的代码:
            // 通过Graphics的CopyFromScreen方法把全屏图片的拷贝到我们定义好的一个和屏幕大小相同的空白图片中,
// 拷贝完成之后,CatchBmp就是全屏图片的拷贝了,然后指定为截图窗体背景图片就好了。
// 新建一个和屏幕大小相同的图片
Bitmap CatchBmp = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height); // 创建一个画板,让我们可以在画板上画图
// 这个画板也就是和屏幕大小一样大的图片
// 我们可以通过Graphics这个类在这个空白图片上画图
Graphics g = Graphics.FromImage(CatchBmp); // 把屏幕图片拷贝到我们创建的空白图片 CatchBmp中
g.CopyFromScreen(new Point(0, 0), new Point(0, 0), new Size(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height)); // 创建截图窗体
cutter = new Cutter(); // 指示窗体的背景图片为屏幕图片
cutter.BackgroundImage = CatchBmp;

  3. 从 “然后我们可以在其上截图”这句话中我们抽象为——其实我们截图操作,从程序角度来说就是我们在这个最大化的窗体中画图,可能这个对一些不了解GDI+画图的朋友有些难理解,这里做个比喻——我们会拿笔在纸上画图,我们可以用比画三角形,矩形已经各种图形,此时纸就是我们一个画板,笔是用来画图图形的,同时笔也是有颜色和粗细的,我们可以用红色水笔画,画出来的图就是红色的了,也可以用黑色水笔画,自然画出来的就是黑色的了,同样,在GDI+也就是Graphics Device Interface Plus也就是图形设备接口,在.NET 中也提供了一些这样的类来让我们实现对图像的访问,也就是我们可以使用.NET中提供的类来进行 “画画”,要画画当然必须要有画板吧(我们开始比喻中纸就是画板),在.NET 类中Graphics类就是对画板的抽象,画板可以由三种方式创建:(1)从图片或继承自图像对象中创建;(2)从窗体或控件的Paint事件中创建;(3)利用窗体或控件的CreateGraphics方法创建。有了画板之后,当然就需要笔来画画了,在.NET 中Pen类就是起到笔的作用,在构造函数中可以指定笔的颜色和粗细,有了笔之后就是开始画图了,在.NET中也同样提供了一些方法来完成画图,如DrawRectangle方法——画矩形

  4. 从 “当鼠标左键按下时,即代表开始截图,并我们可以移动鼠标来改变截图的大小,鼠标弹起时即代表结束截图,此时我们可以双击矩形区域完全截图,并且可以通过粘贴操作把截取的图片粘贴到聊天窗口的发送区,鼠标右键点击则是退出截图”这些描述中可以抽象为——鼠标的移动,按下,弹起等操作,在程序角度来说,也就是实现截图窗体的MouseMove事件(对应于鼠标移动),MouseDown事件(对应于鼠标左键按下),MouseClick事件(对应于鼠标右键结束截图)、MouseUp(对应于鼠标弹起结束截图)和MouseDoubleClick(鼠标双击矩形区域完全截图,并可以通过粘贴操作把截取的图片粘贴到聊天窗口的发送区,既然可以进行粘贴操作来获得截取图片,所以必须在该事件中对剪切板设置截图图片),3和4的分析过程也是截图功能的核心实现,对应于下面的代码(代码中有详细解释,并且大家理解的时候可以结合3和4的分析):

 

  5 到第4点为止,截图的功能已经分析完了,之后就是当我们使用QQ截图的时候,我们除了可以点击聊天窗口中的截图按钮来进行截图外,还可以通过按下Alt+Ctrl+A来进行截图,要实现这个功能的思路也很简单——即当聊天窗体加载的时候对热键(程序中我定义的热键是“Alt+Ctrl+C”)进行注册(此时调用了Win32中RegisterHotKey方法来完成热键的注册),当聊天窗体关闭时进行对热键的卸载,防止对热键进行多次注册,此时调用Win32中的UnregisterHotKey方法来完成,具体的实现代码为:

 /// <summary>
/// 窗体加载事件处理
/// 在窗体加载时注册热键
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 聊天窗体_Load(object sender, EventArgs e)
{
uint ctrlHotKey = (uint)(KeyModifiers.Alt|KeyModifiers.Ctrl);
// 注册热键为Alt+Ctrl+C, "100"为唯一标识热键
HotKey.RegisterHotKey(Handle, 100, ctrlHotKey, Keys.C);
} /// <summary>
/// 窗体关闭时处理程序
/// 窗体关闭时取消热键注册
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 聊天窗体_FormClosing(object sender, FormClosingEventArgs e)
{
// 卸载热键
HotKey.UnregisterHotKey(Handle, 100);
} #endregion // 热键按下执行的方法
private void GlobalKeyProcess()
{
this.WindowState = FormWindowState.Minimized;
// 窗口最小化也需要一定时间
Thread.Sleep(200);
btnCutter.PerformClick();
} /// <summary>
/// 重写WndProc()方法,通过监视系统消息,来调用过程
/// 监视Windows消息
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
{
//如果m.Msg的值为0x0312那么表示用户按下了热键
const int WM_HOTKEY = 0x0312;
switch (m.Msg)
{
case WM_HOTKEY:
if (m.WParam.ToString() == "100")
{
GlobalKeyProcess();
} break;
} // 将系统消息传递自父类的WndProc
base.WndProc(ref m);
}

三、实现效果

上面已经介绍了实现QQ截图的一个思路的,朋友们是不是迫不及待想看看该程序的一个效果了?下面就通过一个动画来让大家更形象地看到程序的运行效果的:

四、总结

到这里QQ截图的介绍部分就到这里了,本工具的实现自认为讲解的非常通俗易懂的,希望大家可以这样觉得并且可以更清晰地明白QQ截图的实现思路的,下面附上本专题的所有源码和一个高仿QQ截图的文章:

本专题源码:http://files.cnblogs.com/zhili/QQ%E6%88%AA%E5%9B%BE%E5%B7%A5%E5%85%B7.zip

高仿腾讯QQ实现:http://blog.csdn.net/crystal_lz/article/details/8274277

作者:Learning Hard
提示:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
 
如果对文章有任何问题,都可以再评论中留言,我会尽可能的答复您,谢谢你的阅读
 

[C# 开发技巧]实现属于自己的截图工具的更多相关文章

  1. Android开发技巧——大图裁剪

    本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使 ...

  2. 【全面解禁!真正的Expression Blend实战开发技巧】第十章 FluidMoveBehavior完全解析之三飞出ListBox吧

    原文:[全面解禁!真正的Expression Blend实战开发技巧]第十章 FluidMoveBehavior完全解析之三飞出ListBox吧 刚才有人说我的标题很给力,哈哈.那这个标题肯定更给力了 ...

  3. 【全面解禁!真正的Expression Blend实战开发技巧】序章

    原文:[全面解禁!真正的Expression Blend实战开发技巧]序章 从silverlight2开始我也和大家一样一直在跟随微软的脚步,从sl2~sl4一步一步过来,总结了不少心得体会.由于各种 ...

  4. SQL开发技巧(二)

    本系列文章旨在收集在开发过程中遇到的一些常用的SQL语句,然后整理归档,本系列文章基于SQLServer系列,且版本为SQLServer2005及以上-- 文章系列目录 SQL开发技巧(一) SQL开 ...

  5. DelphiXE2 DataSnap开发技巧收集

    DelphiXE2 DataSnap开发技巧收集 作者:  2012-08-07 09:12:52     分类:Delphi     标签: 作为DelphiXE2 DataSnap开发的私家锦囊, ...

  6. delphi XE5下安卓开发技巧

    delphi XE5下安卓开发技巧 一.手机快捷方式显示中文名称 project->options->Version Info-label(改成需要显示的中文名即可),但是需要安装到安卓手 ...

  7. 经典收藏 50个jQuery Mobile开发技巧集萃

    http://www.cnblogs.com/chu888chu888/archive/2011/11/10/2244181.html 1.Backbone移动实例 这是在Safari中运行的一款Ba ...

  8. 移动 Web 开发技巧之(后续)

    昨天的<移动 Web 开发技巧>的这篇文章,大家反响不错,因为这些问题在大家日常写移动端的页面时经常遇到的.所以那个文章还是超级实用的,那么我们今天继续来分享一下移动端的web开发技巧吧, ...

  9. Maven 安装以及一些开发技巧

    解压 apache-maven-3.2.5 在conf ->sites中配置repository 的路径. Eclipse 配置 maven 2. 3. 一些小BUG 或开发技巧 eclipse ...

随机推荐

  1. ExtJs--15--Ext.is*各种类型推断的方法,简单看源代码就能够明确了

    /** * Returns true if the passed value is empty, false otherwise. The value is deemed to be empty if ...

  2. session什么时候被创建

    一个常见的错误是以为 session 在有客户端访问时就被创建,然而事实是直到某 server 端程序(如 Servlet )调用HttpServletRequest.getSession(true) ...

  3. HTML静态分页(形如:首页,上一页,下一页,尾页)

    在HTML中有时候我们会用到静态分页,一次拿回一定量的数据结果条目,我们会以形如:第2页,共12页  首页 上一页 下一页 尾页 的方式进行静态分页,以下是该种静态分页的代码,供兄弟姐妹们参考. &l ...

  4. HDU 1983 BFS&amp;&amp;DFS

    大多数刚需封锁4区域可以,DFS地区封锁.BFS无论是通过 #include "stdio.h" #include "string.h" #include &q ...

  5. win7 wifi 无Internet訪问权限或者有限的訪问权限

    自己家的无线路由器,手机和笔记本都使用正常,可是一台新笔记本连上之后总是提示"有限的訪问权限",无法连公网. 网上的非常多办法都无论用,什么设置静态IP或者重新启动路由,基本都是瞎 ...

  6. 纯CSS隔行换色

    原文:纯CSS隔行换色 <head> <meta http-equiv="Content-Type" content="text/html; chars ...

  7. 让IE6支持position:fixed的方法,CSS expression与JavaScript eval讲解

    做吸顶效果或是固定效果时,使用position:fixed无非是最方便的,可是万恶的IE6是没有fixed这个属性值的,而我们要使IE6能够像fixed一样固定在浏览器中的某个位置,使用onscrol ...

  8. PDF解决方案(2)--文件转PDF

    相关专题链接: PDF解决方案(1)--文件上传 PDF解决方案(2)--文件转PDF PDF解决方案(3)--PDF转SWF PDF解决方案(4)--在线浏览 前言:上一篇中讲到的文件上传,文件上传 ...

  9. TRIGGER的使用(修改SP自动触发)

    CREATE TRIGGER [trg_save_change_SP] ON DATABASE FOR CREATE_PROCEDURE, ALTER_PROCEDURE,DROP_PROCEDURE ...

  10. Entity Framework,TransactionScope 混合使用的问题讨论

    using (var ts = new TransactionScope()) { string connStr = "Data Source=.;Initial Catalog=Test; ...