C# 备份和恢复剪贴板

发布于 2024-11-14 08:50:19 字数 369 浏览 3 评论 0 原文

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

这是我的代码:

IDataObject temp = Clipboard.GetDataObject();

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

Clipboard.SetDataObject(temp);

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

注意:我无法使用 Clipboard.Contains,因为我想完全保留剪贴板以前的样子,即使用户复制了文件。

I have a program that uses clipboard but I want to restore the clipboard to its former state after I am done with it.

This is my code :

IDataObject temp = Clipboard.GetDataObject();

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

Clipboard.SetDataObject(temp);

But it if I copy a text, and run this code, I get nothing on notepad.

NOTE : I can't use Clipboard.Contains because I want to preserve the Clipboard EXACLY how it was before, even if the user copied a file.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

木有鱼丸 2024-11-21 08:50:19

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

请阅读此处: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);

I cannot confirm whether this will work, but I see no reason why you shouldn't be able to back up the data using the longer approach of actually reading the data and restoring it afterwards.

Read here: http://msdn.microsoft.com/en-us/library/system.windows.forms.idataobject.aspx

You would do something like (pseudo-code)

//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);
凑诗 2024-11-21 08:50:19

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

// 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);

I tested the pseudocode from Lukas and found out doesn't work always, this works in all my tests:

// 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);
禾厶谷欠 2024-11-21 08:50:19

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

假设它是一个Win Form应用程序。 (虽然不确定它在wpf中是如何工作的)
您可以使用 Clipboard.SetDataObject 的其他重载版本之一,

public static void SetDataObject(object data, bool copy) 

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

例如:在您的情况下,删除文本内容后,您可以调用 Clipboard.SetDataObject(iDataObject, true);

EDIT:2

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

编辑:1

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

还有另一种方法 - 源代码单步执行框架代码 - Clipboard.cs
根据 VS 版本和 .NET 框架,它可能会有所不同(我无法获得 .NET 4 的源代码步进工作,因为信息是具有源代码支持的符号尚未发布)。我正在尝试从 此处(.NET 版本 4)手动下载它,

如果您正在运行 VS 2008 和旧版本的 .NET,那么以下步骤应该适合您。

源符号设置

常规调试设置

更多详细信息是此处

Is your application exiting after resetting the clipboard?

Assuming it is a Win Form app. (not sure how it works in wpf though)
You could use one of the other overloaded version of Clipboard.SetDataObject

public static void SetDataObject(object data, bool copy) 

which preserves the data even after your app exits.

ex: in your case after removing the text content you could call Clipboard.SetDataObject(iDataObject, true);

EDIT:2

I Could source step through Clipboard.cs .NET Frameword 4 / VS 2010.
Download the .NET Framework 4 from here http://referencesource.microsoft.com/netframework.aspx.
Follow the below steps and if it asks for the source (Clipboard.cs) it would be in the Source sub-dir of the installation dir.

EDIT:1

Not sure why the same code doesn't work.
Cannot be a security/permission issue as the code doesn't throw an exception as you say.

There is another approach - source stepping into Framework code - Clipboard.cs
Based on the VS version and .NET framework it may vary ( I couldn't get the source stepping work for .NET 4 as the info is that the symbols with source support haven't yet been released). I'm trying my luck by downloading it manually from here (.NET Version 4)

If you are running VS 2008 and older version of .NET then the below steps should work for you.

Source Symbol Setting

General Debugging Settings

More details are here. For .NET Framework 4 - here

廻憶裏菂餘溫 2024-11-21 08:50:19

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

如何备份和恢复C# 中的系统剪贴板?

此外,我怀疑您想要备份/恢复剪贴板的动机是因为您想将其用作移动数据的拐杖,而无需用户知情或同意。请阅读:
http://www.clipboardextender。 com/developing-clipboard-aware-programs-for-windows/common-general-clipboard-mistakes

http://www.flounder.com/badprogram.htm#clipboard

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

“如果没有用户的明确指示,程序不应将数据从剪贴板传输到我们的系统中。” — Charles Petzold,《Windows 3.1 编程》,微软出版社,1992 年

This cannot be done. You cannot backup/restore the clipboard without causing unintended consequences.
Please see my post on a similar question. My answer is the one that starts with "It's folly to try to do this".

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

Furthermore, I suspect that your motivation for wanting to backup/restore the clipboard is because you want to use it as a crutch to move data, without the user's knowledge or consent. Please read:
http://www.clipboardextender.com/developing-clipboard-aware-programs-for-windows/common-general-clipboard-mistakes
and
http://www.flounder.com/badprogram.htm#clipboard

Lastly, please read and understand this quote:

“Programs should not transfer data into our out of the clipboard without an explicit instruction from the user.” — Charles Petzold, Programming Windows 3.1, Microsoft Press, 1992

你的背包 2024-11-21 08:50:19

我在这方面取得了成功。

...在某种程度上。

我目前失败的地方是尝试复制和恢复不同大小的位图。
我可以成功复制和恢复较小尺寸的位图。

然后,我尝试对一个庞大的 Excel 工作表执行相同的操作(正如预先警告的 Chris Thornton 所建议的那样),该工作表包含数千个单元格数据以及图表上的两组数据,位于同一个工作表上。

我发现数据复制和恢复没有问题。在这种情况下,它失败的地方是允许使用工作表副本的两组图。

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

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

大约两周前我就做到了这一点,并将其搁置以解决更紧迫的问题。

我想把它放在那里,让其他人尝试做同样的事情,看起来是可以做到的。 (在计算机科学中任何事情都可以做。任何事情。)

I have had success with this.

...to a certain degree.

Where I am currently falling down is trying to copy and restore Bitmaps of varying size.
I can successfully copy and restore a Bitmap of smallish size.

I then tried to do the same for (as the fore-warning Chris Thornton suggested) a gargantuan Excel worksheet with both thousands of cell data, as well as two sets of data on a graph, lying on the same worksheet.

I have found that the data copies and restores without problem. Where it falls down in this instance is allowing the 2-set graph with the worksheet copy.

If any of you have had a problem in copying and restoring Bitmaps, let me suggest what worked for me: when attempting to restore the Clipboard, iterate through the list of formats in reverse order and set each data object that way. (i.e. It seems that a Clipboard must be set in reverse order that it was copied in)

Regarding the case of the gargantuan Excel worksheet and accompanying graph, I also hit another stumbling block: I could not successfully copy the data object whose format was "Meta Data File". That could be the reason why Copy/Restore doesn't work in this case.

I got this far about two weeks ago, and tabled it for more pressing issues.

I wanted to put this out there to let anyone else trying to do the same that it seems like it can be done. (anything can be done in computer science. anything.)

俯瞰星空 2024-11-21 08:50:19

我编译了这段代码,它似乎对我有用。我坚持通过与 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; }
    }
}

I compiled this code and it seems to work for me. I am persisting via converting to and from json. (Note. It will not do steams so adapt if you need it to)

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; }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文