代码之家  ›  专栏  ›  技术社区  ›  Martin Harris

剪贴板访问的奇怪之处

  •  6
  • Martin Harris  · 技术社区  · 15 年前

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

    我遇到的问题是恢复状态。如果在运行应用程序之前从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 回复  |  直到 15 年前
        1
  •  5
  •   Rosco    15 年前

    Windows剪贴板一次只包含一个对象。但是这个对象有多种可用格式(例如RTF、文本、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();
    
        2
  •  1
  •   TheVillageIdiot    15 年前

    马丁,我试过你的密码。我有 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) 用新对象覆盖旧对象是正常行为,而不是正常行为。如果您正在构建多条目剪贴板之类的东西,那么您需要截获复制和粘贴系统调用,并将对象保存在程序的内存或磁盘中。不能依赖默认剪贴板。