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;
}