自己编写的一个截图工具
Posted crystal_lz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自己编写的一个截图工具相关的知识,希望对你有一定的参考价值。
http://blog.csdn.net/crystal_lz/article/details/9200859
上面是以前写的 不过现在重写了 增加了一些功能
源代码下载地址:http://download.csdn.net/detail/crystal_lz/9556929
第一次运行 会弹出此窗口进行快捷键的设置
因为需要修改注册表开机启动 所以需要使用管理员权限运行
启动截图的时候 [W,A,S,D] 微距移动鼠标
按下 V -> 自动框选的时候是否 只获取可见窗体
按下 T -> 是否获取透明窗体
按下 H -> 是否对webbrowser进行spy
在自动框选的时候 按下ctrl 的同时点击左键 弹出SpyTool
在自动框选的时候 按下 alt 的同时点击左键 将目标窗体设置为GIF截图窗体
这些快捷键都可以自己试一下
上面是对webbrowser进行spy的效果 是酷狗播放器
比起以前增加了 多显示器截图 其实要多显示器 很简单
/// <summary>
/// 获取整个屏幕的矩形区域
/// </summary>
/// <returns>矩形区域</returns>
public static Rectangle GetDesktopRect()
Rectangle rect = new Rectangle();
rect.X = Win32.GetSystemMetrics(Win32.SM_XVIRTUALSCREEN);
rect.Y = Win32.GetSystemMetrics(Win32.SM_YVIRTUALSCREEN);
rect.Width = Win32.GetSystemMetrics(Win32.SM_CXVIRTUALSCREEN);
rect.Height = Win32.GetSystemMetrics(Win32.SM_CYVIRTUALSCREEN);
return rect;
但是需要注意的是 截图窗体是全屏运行的 正常情况下鼠标在窗体上的坐标就是 鼠标的屏幕坐标 但是 多显示器上不一定
假设我现在是两个显示器 左边一个 右边一个分辨率都是 1920 * 1080 如果说 我右边的显示器是主显示器 那么 左边显示器的坐标是(-1920,0)开始的 所以在写代码的时候 窗体坐标到屏幕坐标的时候 需要注意
这次 程序增加了插件功能
插件可以自己编写 不过我想一般也没有去搞
namespace IPlugins
public interface IFilter
/// <summary>
/// 获取插件显示的名字
/// </summary>
/// <returns>插件名字</returns>
string GetPluginName();
/// <summary>
/// 获取插件在菜单上显示的图标 若不需要显示则返回null
/// </summary>
/// <returns>图标 否则 null</returns>
Image GetPluginIcon();
/// <summary>
/// 用于加载插件时候初始化调用
/// </summary>
/// <param name="strStarPath">主程序启动路径</param>
void InitPlugin(string strStarPath);
ResultInfo ExecFilter(Image imgSrc);
接口很简单 新建一个dll工程 然后引入我的IPlugins.dll文件继承实现 IFilter接口即可
一个Dll里面可以编写多个插件 不过到时候加载到右键菜单上面 会以dll名字作为分组 否则只有一个插件的话就没有子菜单
比如我上面演示的插件 工程是这样的
Gray中写了两个插件 那么到时候右键菜单中就会用Gray(Gray.dll)的名字作为分组 而如果dll中只有一个插件 那么就不用进行分组了
插件返回类型(悲剧的解决方案中忘了给这个类写注释了)
namespace IPlugins
public class ResultInfo : IDisposable
private Image _ResultImage;
/// <summary>
/// 获取插件处理后的图像
/// </summary>
public Image ResultImage
get return _ResultImage;
private bool _IsModified;
/// <summary>
/// 告知程序图片是否被编辑 如果false 则忽略插件操作 如果true 则取出ResultImage作为结果
/// </summary>
public bool IsModified
get return _IsModified;
private bool _IsClose;
/// <summary>
/// 如果true则截图窗体关闭 比如编写一个图片编辑器插件
/// 插件得到图片后想独占编辑 则可以在插件中Show一个窗体出来 然后返回一个ResultInfo
/// 并将IsClose设置为true则 截图窗体就关闭了 剩下的操作就可以在自己编写的编辑器中进行
/// </summary>
public bool IsClose
get return _IsClose;
public ResultInfo(Image imgResult, bool bModified, bool bClose)
this._ResultImage = imgResult;
this._IsModified = bModified;
this._IsClose = bClose;
public void Dispose()
if (this._ResultImage != null) this._ResultImage.Dispose();
//调用插件
private void item_Click(object sender, EventArgs e)
try
var result = ((sender as ToolStripMenuItem).Tag as IPlugins.IFilter).ExecFilter(m_imgLastLayer.Clone() as Bitmap);
if (result.IsClose) this.Close();//如果插件需要关闭窗体(则插件里面可以自己show一个窗体出来 而不是ShowDialog)
if (!result.IsModified) return;//如果图片没有被编辑 则忽略操作
m_imgCurrentLayer = result.ResultImage;
imageCroppingBox1.Invalidate(imageCroppingBox1.SelectedRectangle);
this.SetHistoryLayer();
imageCroppingBox1.IsLockSelected = true;
catch (Exception ex)
MessageBox.Show(ex.Message);
可以自己整理一下逻辑
这是上面二值化插件弹出来的窗体 反正插件要怎么写 随便自己 可以不用弹出 比如上面的 黑白处理 和 反色处理 就不需要弹出窗体来进行一些参数设置
这个是上面插件的代码:
namespace Gray
public class PluginBinary : IFilter
public string GetPluginName()
return "二值化";
public System.Drawing.Image GetPluginIcon()
return Properties.Resources.icon_binary;
public void InitPlugin(string strStarPath)
public ResultInfo ExecFilter(System.Drawing.Image imgSrc)
Form1 frm = new Form1(imgSrc);
if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
return new ResultInfo(frm.ResultImage, true, false);
return new ResultInfo(null, false, false);
是不是感觉很简单
IPlugins.Dll里面有些自己写的控件 可以用 不过里面只写了我需要用到的控件 没几个
还有就是 由于平时经常用到打码 所以直接截图也内置了
选择 填充 和 马赛克 模式 反正就是自己尝试
如果不勾选马赛克 那么就是普通按照选择的颜色进行填充
不过这里注意 如果选择的是 绘制 和 马赛克 模式 你可能会感觉到绘制没有效果 这不是bug而是设定上就是这样的
只要勾选马赛克模式 无论画刷还是画笔都是以马赛克方式呈现的
如果画笔大小放大一点就能看到是什么效果了
GIF录制也经常用到 所以也内置了这个功能
GIF录制有两种模式 一种是窗体录制 一种是选择区域录制
选择区域录制就是上面截图看到的 选择一个区域右键菜单 -> 设置为GIF录制区域 这个很好理解
窗体录制是 只启动截图在自动框选的时候还没有确定区域的时候 按住ALT键然后点击鼠标左键 则会把自动框出来的窗体作为录制目标 和区域录制唯一的不同是
区域录制只会录制指定区域 而窗体录制则会跟踪窗体位置 比如窗体从屏幕左边移动到了右边依然会录制该窗体 而区域录制则办不到
GIF录制的时候 托盘图标右下角会变成绿色暂停录制是红色 否则显示正常图标
启动了录制gif切记 你正则录制 不然你忘了就悲剧了 就等着内存被沾满 然后蹦了吧
上面是录制的效果 可以选择高质量和低质量 可以点击复制 能直接将图片粘贴到QQ聊天窗体中去 为此我还分析了一下QQ的剪切板数据
string[10]
[0]: "QQ_Unicode_RichEdit_Format" //MemoryStream 是一段xml
[1]: "QQ_RichEdit_Format" //MemoryStream 同上(和上面的可以粘贴到聊天窗口)
[2]: "DeviceIndependentBitmap" //直接使用Image类型即可(进行普通粘贴)
[3]: "FileDrop" //string[] 文件路径(复制文件)
[4]: "FileNameW" //string[] 同上
[5]: "FileName" //同上
[6]: "html Format"
[7]: "System.String"
[8]: "UnicodeText"
[9]: "Text"
这是我的代码
private void btn_copy_Click(object sender, EventArgs e)
if (!System.IO.Directory.Exists("./temp")) System.IO.Directory.CreateDirectory("./temp");
string strTempFile = "./temp/DevCap_"/*Developer Capture*/ + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".gif";
strTempFile = System.IO.Path.GetFullPath(strTempFile);
pictureBox1.Image.Save(strTempFile);
var i = new DataObject();
byte[] byData = Encoding.UTF8.GetBytes("<QQRichEditFormat><Info version=\\"1001\\"></Info><EditElement type=\\"1\\" filepath=\\"" + strTempFile + "\\" shortcut=\\"\\"></EditElement><EditElement type=\\"0\\"><![CDATA[]]></EditElement></QQRichEditFormat>");
i.SetData("QQ_Unicode_RichEdit_Format", new System.IO.MemoryStream(byData));
i.SetData("QQ_RichEdit_Format", new System.IO.MemoryStream(byData));
i.SetData("FileDrop", new string[] strTempFile );
i.SetData("FileNameW", new string[] strTempFile );
i.SetData("FileName", new string[] strTempFile );
i.SetData("DeviceIndependentBitmap", pictureBox1.Image);
Clipboard.SetDataObject(i, true);
其他的还是自己看代码吧 关键注释已经很详细了
最后说明一下 虽然源代码开放 但是我实在是不希望看到那种 只改一个标题然后就重新发布说是自己写的那种情况 不是说不让用我的代码
只是说如果仅仅是使用或者在这个基础上修改代码 请保留代码一些原有的信息 比如我的ID:Crystal_lz (本想在每个类开头写个注释头的 估计写了也没用)
开放代码的目的是希望大家一起交流学习 顺便装个逼 而不是把东西送给你 对于我写的代码我完全可以选择开放或者不开放代码 但是既然我开放出来了 就希望别 “据为己有” 随便改改就说是你自己写的 即使你要这样做 请保留我的ID也好让我能继续装逼
如果有BUG请记得反馈
以上是关于自己编写的一个截图工具的主要内容,如果未能解决你的问题,请参考以下文章