剪贴板访问的奇怪性

时间:2009-09-03 16:40:33

标签: c# clipboard

我正在尝试编写一个需要使用剪贴板来实现某些功能的小应用程序。由于我不想覆盖当前在剪贴板中的用户数据,我决定将其保存到内存中,完成我的工作然后将其写回。下面的代码是一个控制台应用程序,它是我正在尝试做的一个准确的例子。

我遇到的问题是恢复状态。如果我在运行应用程序之前从Visual Studio将某些内容复制到剪贴板,则剪贴板中总共有六个对象(各种字符串格式和一个区域设置)都将放入缓存中。一旦我恢复它们,虽然只有区域设置在剪贴板中,并且每次调用SetData()都会覆盖最后一个。 (顺便说一下,SetDataObject似乎不是GetDataObject的反转,所以我不能只使用它)

任何想法如何存储剪贴板状态并在以后恢复它?

    [STAThread]
    static void Main(string[] args)
    {
        //Store the old clipboard data
        Dictionary<string, object> clipboardCache = new Dictionary<string, object>();

        IDataObject clipboardData = Clipboard.GetDataObject();

        foreach (string format in clipboardData.GetFormats())
        {
            clipboardCache.Add(format, clipboardData.GetData(format));
        }

        Clipboard.SetText("Hello world!");

        string value = Clipboard.GetText();

        Console.WriteLine(value);

        //Clear the clipboard again and restore old data
        Clipboard.Clear();

        foreach (KeyValuePair<string, object> valuePair in clipboardCache)
        {
            Clipboard.SetData(valuePair.Key, valuePair.Value);
            Thread.Sleep(100);
        }

        Console.ReadLine();
    }

2 个答案:

答案 0 :(得分:5)

Windows剪贴板一次只有一个对象。但是,有一种对象可以使用多种格式(例如RTF,Text,HTML)。我认为你太复杂了,你的代码应该是这样的:

//Store the old clipboard data
IDataObject clipboardData = Clipboard.GetDataObject();

Clipboard.SetText("Hello world!");

string value = Clipboard.GetText();
Console.WriteLine(value);

//Clear the clipboard again and restore old data
Clipboard.Clear();
Clipboard.SetDataObject(clipboardData);

Console.ReadLine();

答案 1 :(得分:1)

Martin我已经尝试过你的代码了。我在我的系统上安装了ClipX。当我运行你的代码时运行它我得到的数量与ClipX的缓存一样多。但是调用Clipboard.GetDataObject()只返回最新的对象。那么当你调用这个循环时会发生什么:

foreach (string format in clipboardData.GetFormats())
{
    clipboardCache.Add(format, clipboardData.GetData(format));
}

它返回ClipX中所有对象的格式并转换

返回的数据
IDataObject clipboardData = Clipboard.GetDataObject();

所以实际上当你执行这个循环时

foreach (KeyValuePair<string, object> valuePair in clipboardCache)
{
    Clipboard.SetData(valuePair.Key, valuePair.Value);
    Thread.Sleep(100);
}

您只有一个对象被设置为剪贴板。

其次,当使用Clipboard.SetData(format,object)覆盖旧对象时,新对象是正常行为而不是正常行为。如果要构建多个条目剪贴板,则需要拦截复制和粘贴系统调用,并将对象保留在程序的内存或磁盘中。您不能依赖默认剪贴板。