C# 中的剪贴板备份






4.38/5 (14投票s)
2006 年 8 月 25 日
2分钟阅读

96635

3727
使用 C# 和 Windows API 调用备份剪贴板,以避免 C# 对剪贴板管理的限制。
引言
该代码使用 Windows API 调用来读取和写入剪贴板。
它提供了一个 ClipboardHelper,一个易于使用的 API 桥接器,它还提供了使用 XmlSerializer
将复杂的剪贴板数据序列化到硬盘并在需要时恢复的功能,而不是 .NET Framework,后者只能管理符合 CLR 的数据。
我在 Internet Explorer、Word、OpenOffice(包括图像文件)中测试了它。
背景
.NET framework 和 Windows.Forms.Clipboard
类只允许操作可序列化的数据。那么,如果您的剪贴板包含来自不兼容应用程序的数据会发生什么?很简单!.NET Framework 认为剪贴板是空的。
要读取和操作这些数据,我们需要调用user32.dll和kernerl32.dll。
使用代码
该代码包括两个项目:库 ClipboardHelper 和控制台应用程序 ClipboardTest。
整个代码都添加了注释,以理解 API 的使用和实现的保存过程。
使用该库非常容易:它是一个静态类,公开了一个static void ClipboardHelper.Serialize
函数,用于将剪贴板数据序列化到硬盘,以及static void Deserialize
用于反序列化它并将其放回剪贴板,准备好粘贴。
//Comment next line to end the demo mode
//and backup your clipboard data.
ClipboardHelper.Deserialize(demo);
Console.WriteLine("restore the demo clipboard");
//Open the clipboard and serialize into a directory
ClipboardHelper.Serialize(fileName);
Console.WriteLine("serialize clipboard to " + fileName);
//Deserialize the clipboard and set data
//to win clipboard ready to be pasted
ClipboardHelper.Deserialize(fileName);
Console.WriteLine("restore the clipboard " + fileName);
测试应用程序展示了 ClipboardHelper
的一个实际例子。 它在从 CodeProject 主页上的 Internet Explorer 复制了一些行后,反序列化剪贴板,备份它,然后再次从备份中反序列化它。运行它之后,您的剪贴板中就有剪贴板备份,可以粘贴。
ClipboardHelper 内部
API 调用返回的数据保存在 [Serializable]DataClip
对象中。 它允许轻松地在远程处理上下文中发送剪贴板,并通过 XmlSerializer
保存它。
public static void SaveToFile(ReadOnlyCollection<DATACLIP> clipData, string clipName)
{
IEnumerator<DATACLIP> cData = clipData.GetEnumerator();
while (cData.MoveNext())
{
XmlSerializer xml = new XmlSerializer(typeof(DataClip));
using (StreamWriter sw = new StreamWriter(di.FullName +
@"\" + i.ToString() + ".cli",false))
{
xml.Serialize(sw, cData.Current);
}
}
}
深入剪贴板
剪贴板包含碎片缓冲区中的数据。 它们中的每一个都有一个特定的 DataFormat
,供剪贴板查看器和从中复制数据的软件使用,以识别如何正确呈现缓冲区。
EnumClipboardFormats
返回剪贴板中包含的 DataFormat
数组。 对于每个 DataFormat
,我们可以调用 GetClipboardData
。 它返回剪贴板对象的句柄。 通过调用 kernel32.dll 的 GlobalSize
和 GlobalLock
,我们获得剪贴板对象的属性(它的长度和指向它的指针),因此我们可以通过 Marshal.Copy
方法将剪贴板对象复制到我们的缓冲区(一个byte
数组)。
要获取剪贴板,首先要检查是否打开了剪贴板
Win32ClipboardAPI.OpenClipboard(IntPtr.Zero)
然后,我们获取所有 DataFormat
;查询它们,我们得到剪贴板数据缓冲区
//Init a list of ClipData,
// which will contain each Clipboard Data
List<DataClip> clipData = new List<DataClip>();
//Loop for each clipboard data type
uint format = 0;
while ((format = Win32ClipboardAPI.EnumClipboardFormats(format)) != 0)
{
//Get the formatName
StringBuilder formatName = new StringBuilder();
Win32ClipboardAPI.GetClipboardFormatName(format,
formatName, 100);
//Get the pointer for the current Clipboard Data
IntPtr pos = Win32ClipboardAPI.GetClipboardData(format);
//Get the clipboard buffer data properties
UIntPtr lenght = Win32MemoryAPI.GlobalSize(pos);
IntPtr gLock = Win32MemoryAPI.GlobalLock(pos);
byte[] buffer;
//Init a buffer which will contain the clipboard data
buffer = new byte[(int)lenght];
int l = Convert.ToInt32(lenght.ToString());
//Copy data from clipboard to our byte[] buffer
Marshal.Copy(gLock, buffer, 0, l);
//Create a ClipData object that
//represents the current clipboard data
DataClip cd = new DataClip(format,
formatName.ToString(), buffer);
//Add current Clipboard Data to the list
clipData.Add(cd);
}
历史
- 2006/08/23 - 初始版本。
- 2006/08/29 - 整个保存系统都已更改,实现了
XmlSerializer
。 它工作得更好,解决了写入文件过程中的错误。