C#备份和恢复剪贴板

时间:2011-06-07 08:21:56

标签: c# winforms clipboard

我有一个使用剪贴板的程序,但我希望在完成后将剪贴板恢复到以前的状态。

这是我的代码:

IDataObject temp = Clipboard.GetDataObject();

//Some stuff that change Cliboard here
Clipboard.SetText("Hello");
//Some stuff that change Cliboard here

Clipboard.SetDataObject(temp);

但如果我复制文本并运行此代码,我在记事本上什么也得不到。

注意:我不能使用Clipboard.Contains,因为我想保留剪贴板EXACLY之前的状态,即使用户复制了一个文件。

6 个答案:

答案 0 :(得分:3)

我无法确认这是否有效,但我认为没有理由不使用实际读取数据的较长方法并在之后恢复数据来备份数据。

请在此处阅读:http://msdn.microsoft.com/en-us/library/system.windows.forms.idataobject.aspx

你会做类似(伪代码)

的事情
//Backup
var lBackup = new Dictionary<string, object>();
var lDataObject = Clipboard.GetDataObject();
var lFormats = lDataObject.GetFormats(false);
foreach(var lFormat in lFormats)
{
  lBackup.Add(lFormat, lDataObject.GetData(lFormat, false));
}

//Set test data
Clipboard.SetText("asd");

//Would be interesting to check the contents of lDataObject here

//Restore data
foreach(var lFormat in lFormats)
{
  lDataObject.SetData(lBackup[lFormat]);
}
//This might be unnecessary
Clipboard.SetDataObject(lDataObject);

答案 1 :(得分:1)

重置剪贴板后,您的应用程序是否已退出?

假设它是一个Win Form应用程序。 (不知道它在wpf中是如何工作的) 您可以使用Clipboard.SetDataObject

的其他重载版本之一
public static void SetDataObject(object data, bool copy) 

即使在您的应用退出后也会保留数据。

例如:在删除文字内容后,您可以拨打Clipboard.SetDataObject(iDataObject, true);

修改:2

我可以通过Clipboard.cs .NET Frameword 4 / VS 2010获取步骤。 从此处http://referencesource.microsoft.com/netframework.aspx下载.NET Framework 4。 按照以下步骤,如果它要求源(Clipboard.cs),它将在安装目录的Source子目录中。

修改:1

不确定为什么相同的代码不起作用。 不能是安全/权限问题,因为代码不会像你说的那样抛出异常。

还有另一种方法 - 源代码插入框架代码 - Clipboard.cs 基于VS版本和.NET框架,它可能会有所不同(我无法获得.NET 4的源步进工作,因为信息是源代码支持的符号尚未发布)。我是通过从here(.NET版本4)

手动下载来试试我的运气

如果您运行的是VS 2008及更早版本的.NET,则以下步骤适用于您。

Source Symbol Setting

General Debugging Settings

更多细节是here。对于.NET Framework 4 - here

答案 2 :(得分:1)

我测试了Lukas的伪代码,发现它并不总是有效,这在我所有的测试中都有效:

// Backup clipboard 
lBackup = new Dictionary<string, object>();
lDataObject = Clipboard.GetDataObject();
lFormats = lDataObject.GetFormats(false);
foreach (var lFormat in lFormats)
{
    lBackup.Add(lFormat, lDataObject.GetData(lFormat, false));
}

//Set test data
Clipboard.SetText("asd");

//Restore clipboard
lDataObject = new DataObject();
foreach (var lFormat in lFormats)
{
    lDataObject.SetData(lFormat, lBackup[lFormat]);
}
//This might be unnecessary
Clipboard.SetDataObject(lDataObject);

答案 3 :(得分:0)

这不可能。您无法备份/恢复剪贴板而不会导致意外后果。 请在类似问题上查看我的帖子。我的答案是以“尝试这样做是愚蠢的”开头的。

How do I backup and restore the system clipboard in C#?

此外,我怀疑你想要备份/恢复剪贴板的动机是因为你想在没有用户知情或同意的情况下将它用作移动数据的拐杖。请阅读: http://www.clipboardextender.com/developing-clipboard-aware-programs-for-windows/common-general-clipboard-mistakeshttp://www.flounder.com/badprogram.htm#clipboard

最后,请阅读并理解这句话:

“程序不应在没有用户明确指示的情况下将数据传输到剪贴板中。” - Charles Petzold,编程Windows 3.1,Microsoft Press,1992

答案 4 :(得分:0)

我已经成功了。

......在某种程度上。

我目前正在倒下的地方是尝试复制和恢复不同大小的位图。 我可以成功复制和恢复小尺寸的位图。

然后我尝试做同样的事情(正如预警Chris Thornton建议的那样)一个巨大的Excel工作表,其中包含数千个单元格数据,以及位于同一工作表上的两组数据。 / p>

我发现数据的复制和恢复没有问题。在这种情况下它落在哪里是允许带有工作表副本的2组图。

如果您有任何人在复制和恢复位图时遇到问题,请让我建议一下对我有用的方法:尝试恢复剪贴板时,按相反的顺序遍历格式列表并以这种方式设置每个数据对象。 (即似乎必须按照复制的相反顺序设置剪贴板)

关于庞大的Excel工作表和附图的情况,我还遇到了另一个绊脚石:我无法成功复制格式为“元数据文件”的数据对象。这可能是复制/恢复在这种情况下不起作用的原因。

我在两周前就已经做到了这一点,并提出了更紧迫的问题。

我想把它放在那里让其他人试图做同样的事情似乎可以做到。 (任何事情都可以在计算机科学中完成。任何东西。)

答案 5 :(得分:0)

我编译了这段代码,它似乎对我有用。我坚持通过与json相互转换。 (注意。它不会产生蒸汽,因此如果需要可以适应)

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace Clipboard
{
    class Program
    {
        static void Main(string[] args)
        {                                    
            Execute(() =>
            {
                var backup = Backup();
                System.Windows.Forms.Clipboard.SetText("text"); //just to change clipboard
                Restore(backup);
            });                
        }

        private static void Execute(Action action)
        {
            var thread = new Thread(() => action());
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            thread.Join();
        }

        private static List<ClipboardItem> Backup()
        {
            var backup = new List<ClipboardItem>();
            var data = System.Windows.Forms.Clipboard.GetDataObject();
            System.Windows.Forms.Clipboard.SetDataObject(data, copy: true); //This seems to be needed to be able to serialize data later.
            data = System.Windows.Forms.Clipboard.GetDataObject();
            var formats = data.GetFormats(false).ToList();
            formats.ForEach(f =>
            {
                if (data.GetData(f, false) != null && !(data.GetData(f, false) is Stream))
                {                    
                    backup.Add(new ClipboardItem()
                    {
                        Format = f,
                        ObjectType = data.GetData(f, false).GetType(),
                        ObjectJson = JsonConvert.SerializeObject(data.GetData(f, false))
                    });
                }                
            });            
            return backup;
        }

        private static void Restore(List<ClipboardItem> backup)
        {
            var data = new System.Windows.Forms.DataObject();
            backup.ForEach(item =>
            {               
                data.SetData(item.Format, JsonConvert.DeserializeObject(item.ObjectJson, item.ObjectType));
            });
            System.Windows.Forms.Clipboard.SetDataObject(data, copy: true);
        }
    }    

    public class ClipboardItem
    {
        public string Format { get; set; }
        public Type ObjectType { get; set; }
        public string ObjectJson { get; set; }
    }
}