Saving and obtaining custom objects to/from Windows Clipboard






4.92/5 (28 votes)
Aug 27, 2004
3 min read

127367

2
The code shows how to save (and restore) an instance of your own class to clipboard.
Introduction
This article shows, how to save an instance of a custom C#.NET class (any class) to a clipboard. It explains what requirements your class has to meet, so that you can save it to the clipboard.
Background
Surprisingly, but I've found a very few materials on this topic on the Internet. There are thousands of posts like "help, when I retrieve data from clipboard, it always returns null". Most of the answers I've found make contrary statements, some of them say that "you can't save a reference-type object to a clipboard", and other crap like this.
So, colleagues, let me save your time and provide you with some info.
Serialization
Basically, serialization is a process of "saving" an object to a form, that can be transported, copied to hard disk, sent by email etc. And vice versa, deserialization is making an instance of an object from this form (for example, from a byte stream). And this is the first and the only clipboard requirement for your class. Your class has to be serializable.
To make a class serializable, you can implement a ISerializable
interface, but the easiest way to make a class serializable is to mark it with the Serializable
attribute. Like this:
[Serializable]
public class Document
{
public int documentID = 0;
public string documentDescription = "";
}
// that was simple huh?
Important: please note, that if your class is derived from some base class, the base class also has to be marked as Serializable
. Like this:
[Serializable]
public class Document
{
public int documentID = 0;
public string documentDescription = "";
}
[Serializable]
public class EmailDocument : Document {
public string subject = "";
public string body = "";
}
Also note, that if your class has some complex private properties, that can't be serialized (or you don't want them to be serialized), you should mark such properties with [NonSerialized()]
attribute like this:
[Serializable]
public class Document
{
public int documentID = 0;
public string documentDescription = "";
[NonSerialized]
private System.Data.SqlClient.SqlCommand cmd;
[NonSerialized]
private System.Data.SqlClient.SqlConnection cn;
}
Determine if your object is serializable or not
To determine if your class is clipboard compatible, you can write a simple method IsSerializable(object obj)
(see listing below). It uses a BinaryFormatter
class to serialize your object to a MemoryStream
. This method requires some memory, so use it only for debugging purposes, remove it from your app when finished testing. Here it is:
using System.Runtime.Serialization.Formatters.Binary;
private static bool IsSerializable(object obj)
{
System.IO.MemoryStream mem = new System.IO.MemoryStream();
BinaryFormatter bin = new BinaryFormatter();
try
{
bin.Serialize(mem, obj);
return true;
}
catch(Exception ex)
{
MessageBox.Show("Your object cannot be serialized." +
" The reason is: " + ex.ToString());
return false;
}
}
Clipboard Formats
Other things we have to learn is data formats. Every application stores some data to the clipboard in some data format (or in multiple data formats). There are standard formats like Text, Image, Wave Audio, HTML text etc. These formats are pre-registered on every Windows-computer. Any application "knows", what formats it "understands", so an application "knows" if the data at the clipboard can be pasted to it. An application can store some data using one of these standard formats, or register its own data format.
.NET framework Clipboard class
Accessing the Clipboard and storing data there with a Windows application is made possible through the use of the SetDataObject()
method of a Clipboard
class, which stores the data on the Clipboard using the IDataObject
interface. Retrieving data from the Clipboard is also done through the IDataObject
interface.
Copy to clipboard
To save your custom object to a clipboard, you need to register your custom clipboard format (if it's not already registered), create an instance of a DataObject
filled with your data, and pass this instance to a ClipBoard.SetDataObject()
method. To register your own custom data format, all you have to do is to think up a name for your data format! And then call a static member DataFormats.GetFormat()
. Personally, I think that the best name for a new data format is a full name of its type.
Just look at the code. I've added CopyToClipboard()
method to my above Document
class:
[Serializable]
public class Document
{
public int documentID = 0;
public string documentDescription = "";
[NonSerialized]
private System.Data.SqlClient.SqlCommand cmd;
[NonSerialized]
private System.Data.SqlClient.SqlConnection cn;
public void CopyToClipboard()
{
//register my custom data format with Windows
//or get it if it's already registered
DataFormats.Format format =
DataFormats.GetFormat(typeof(Document).FullName);
//now copy to clipboard
IDataObject dataObj = new DataObject();
dataObj.SetData(format.Name, false, this);
Clipboard.SetDataObject(dataObj, false);
//that's it
}
}
Obtain data from clipboard
First of all, before getting some data from clipboard, you have to ensure that the data format in the clipboard is compatible with your app. To do this, call GetDataPresent()
method of a DataObject
instance. After that, you call a GetData()
method of a IDataObject
interface. Here's the code, where I get my Document
object from clipboard:
protected static Document GetFromClipboard()
{
Document doc = null;
IDataObject dataObj = Clipboard.GetDataObject();
string format = typeof(Document).FullName;
if(dataObj.GetDataPresent(format))
{
doc = dataObj.GetData(format) as Document;
}
return doc;
}