开发者

C# Backing Up And Restoring Clipboard

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.


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


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.

C# Backing Up And Restoring Clipboard

C# Backing Up And Restoring Clipboard

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


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


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


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.)


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; }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜