C#Winform+WindowsAPI做个剪贴板无缝自动保存器(视频截图利器)
(本文最新代码已上传到GitHub,地址在(https://github.com/bitzhuwei/ClipboardImageSaver))
利用C#和Window API做了个自动保存剪贴板内的图片的工具,用在给视频截图上是最好不过的了。共享之。
点击Start按钮,就会在剪贴板内容发生变化时自动把保存到指定位置(保存为jpg格式的图片),并且以指定的字符串作为文件的前缀,后面跟上序号。所以这个工具是和PrtSc截屏键紧密结合使用的,按一次PrtSc,就保存一张图片。就算一直按着不放,也能把每个截屏命令都执行到。
另外,Distinct按钮可以把Path文件夹所在的所有文件检查一遍,自动删掉内容完全一样的文件。这个很实用吧。
源码在此:http://files.cnblogs.com/bitzhuwei/bitzhuwei.Clipboard.Winform.zip
release版程序在此:http://files.cnblogs.com/bitzhuwei/bitzhuwei.Clipboard.Winform-release.zip
1. 将剪贴板内的图片保存到文件
代码如下。
1: void SaveClipboardImage()
2: {
3: var data = System.Windows.Forms.Clipboard.GetDataObject();
4: var bmap = (Image)(data.GetData(typeof(System.Drawing.Bitmap)));
5: if (bmap != null)
6: {
7: bmap.Save("bitzhuwei.cnblogs.com.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
8: bmap.Dispose();
9: }
10: }
2. 监听剪贴板变化的事件
override掉主窗体的WndProc事件,这样就能够实现当且仅当剪贴板内容发生变化时执行一次保存动作了。


override掉在主窗口的WindProc事件 const int WM_DRAWCLIPBOARD = 0x308;const int WM_CHANGECBCHAIN = 0x030D;protected override void WndProc(ref Message m){if (nextClipboardViewer == null)nextClipboardViewer = (IntPtr)SetClipboardViewer((int)this.Handle);switch (m.Msg){case WM_CHANGECBCHAIN:if (m.WParam == nextClipboardViewer) { nextClipboardViewer = m.LParam; }else { SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam); }break;case WM_DRAWCLIPBOARD:SaveClipboardImage();//将WM_DRAWCLIPBOARD 消息传递到下一个观察链中的窗口SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);//将WM_DRAWCLIPBOARD 消息传递到下一个观察链中的窗口 break;default:base.WndProc(ref m);break;}}
3. 文件雷同判别
用文件流一个字节一个字节的判断即可。大部分不同的文件,判断不了多少次就会出现字节不一样了,所以我对这个方法的效率还是有信心的。自己也试验过,对视频截图得到的1000多张图片(全屏的截图1280*800的图片),2分钟就把重复的文件都删掉了。


删掉指定文件夹下所有内容相同的冗余文件 private void DeleteRedundancyFiles(string directory){var files = (new DirectoryInfo(directory)).GetFiles("*.jpg");for (int i = 0; i < files.Length; i++){for (int j = i + 1; j < files.Length; j++){if (File.Exists(files[i].FullName) && File.Exists(files[j].FullName)){bool removeJ = IsSameContent(files, i, j);if (removeJ){try{File.Delete(files[j].FullName);}catch (Exception){ }}}}}}private static bool IsSameContent(FileInfo[] files, int i, int j){var result = true;using (FileStream fsi = new FileStream(files[i].FullName, FileMode.Open)){using (FileStream fsj = new FileStream(files[j].FullName, FileMode.Open)){var counti = 0;var countj = 0;do{const int length = 100;var bytesi = new byte[length];var bytesj = new byte[length];counti = fsi.Read(bytesi, 0, length);countj = fsj.Read(bytesj, 0, length);if (counti != countj){result = false;}else{for (int k = 0; k < counti; k++){if (bytesi[k] != bytesj[k]){result = false;break;}}}} while (result && counti > 0 && countj > 0);}}return result;}