Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C#
Article

Clipboard handling with .NET - Part II

Rate me:
Please Sign up or sign in to vote.
4.71/5 (12 votes)
3 Jun 20025 min read 200.9K   2.6K   54   31
Builds on part 1, showing how to use custom/multiple formats

Screenshot of the demo application

Formats that are available after clicking Copy All

Introduction

At the end of April 2002, Nish and I were trying to figure out some of .NET's clipboard capabilities. When we had finished the conversation we decided on writing a two part article, Nish doing part one on the basics then I would do part two on some more advanced topics. I was going to write it as soon as the screensaver competition was over, needless to say I forgot....until now that is.

In this article I hope to cover multiple data formats, and creating your own custom data formats.

Multiple data formats

Placing multiple data formats on the clipboard is incredibly easy; once you know the trick :-)

The first tric...er step is to figure out what data formats you will be using. Later I'll discuss custom formats so ignore those for now. To help you in your search the DataFormats class has a list of commonly used formats stored as static string fields; refer to MSDN for the specifics on each format listed there.

Now that you know the formats you will use, create a instance of a class that implements IDataObject, the only such class is (appropriately) named DataObject.

C#
IDataObject ido = new DataObject();

With the IDataObject interface in hand we can begin to use it. The purpose of the IDataObject is to "[Provide] a format-independent mechanism for transferring data" (MSDN, IDataObject interface). Those familiar with COM will know this object well. It can store one object of each format that you pass in. Thus if you need to store 3 Text formatted objects, you'll need to wrap them into a custom format which I'll explain later.

C#
ido.SetData(DataFormats.Text, true, myString);

That line of code adds a new Text formatted object with the value of myString to the DataObject, and allows it to be converted to other types as well. This will be a key point that you find in Win32 using the Clipboard. Data is often in multiple formats to allow it to be used in a multitude of programs. Typically data will be stored in a custom format, as text, and possibly a bitmap if it represents something graphical. This allows for pasting into many applications and into itself in a native format.

Adding multiple, additional, formats is as easy as additional calls to SetData with differing formats.

C#
Clipboard.SetDataObject(ido, true);

This line finally places the data on the clipboard where it can be read by any program. The true argument tells the Clipboard to make the data available even after the program quits. Later I'll introduce another important point about the second parameter, which isn't mentioned by MSDN.

With the data copied to the Clipboard you can now paste it as you did before; check for the proper data format then retrieve it if it exists.

C#
IDataObject ido = Clipboard.GetDataObject();

if(ido.GetDataPresent(DataFormats.Text))
{
    // Text data is present on the clipboard
    textBox1.Text = (string) ido.GetData(DataFormats.Text);
}

Custom data formats

A custom data format can be anything; whether a special text formatting such as HTML or XML or it can be an instance of a class. To use a custom format, first you register it with Windows. In the demo application you will find that I register the type with Windows in the static constructor for the custom type class, CustomData.

C#
static CustomData
{
    format = DataFormats.GetFormat(
        typeof(CustomData).FullName
    );
}

The code typeof(CustomData).FullName merely retreives the full name of the type; since I needed to choose a unique name I figured that would do. GetFormat returns an instance of the DataFormats.Format class which I store for use as a static property to access the Name and ID of the format. The name doesn't have to be relevant just unique, Windows registers a Format17 which it uses for screenshots.

The only unique part about creating a custom format that uses a class is that the class must be serializable, that is it needs to have the Serializable attribute applied to it.

C#
[Serializable()]
public class CustomData
.....

To use it on the clipboard you do so as you would any other format.

C#
IDataObject ido = new DataObject();
CustomData cd = new CustomData(myImage, myString);

ido.SetData(CustomData.Format.Name, false, cd);

Retrieving data from it is done the same as before.

C#
IDataObject ido = Clipboard.GetDataObject();

if( ido.GetDataPresent(CustomData.Format.Name) )
{
    // Do something interesting with the data
    CustomData cd = (CustomData) 
        ido.GetData(CustomData.Format.Name);
}

Persisting data on the clipboard, ie the 2nd parameter to SetDataObject

According to MSDN the second parameter tells the Clipboard object whether the data inside should be persisted when the application exits. BUT that isn't the full story. What it actually does is delay the serialization of the data until when the data is actually needed.

To see this in action run the included ClipboardTest2 application, uncheck "Persist Data"; then proceed to Draw, Copy, and Paste, then Draw and Paste. You'll see that even though the data was copied only once the new data is shown.

The reason for this lies in that I continue to operate on the same object that was passed into the IDataObject's SetData method, since we told the Clipboard object NOT to serialize the data until needed, that is what it did. On top of that it will reserialize the data everytime the data is requested. Oddly though it only updates the format specified, none of the auto-converted formats are touched once the initial serialization of the format occurs.

To demonstrate this open up the ClipboardTest2 application, again uncheck "Persist Data"; and then Draw, Copy, and Paste. Proceed to Draw and Paste, then open up your favorite image editing software; MSpaint will do. Now Paste the bitmap there; do some more Draw and Pastes then Paste again in another copy of MSPaint. You'll see the same bitmap was pasted in both MSPaint's.

This seems like a bug, but really it is a bug in my use. Once you place an object on the clipboard the intended result is that object stays the same; not to change it like I did. This means the optimal solution is to create a copy and cache it somewhere until it is needed by the Clipboard object.

If you choose to not persist data to the clipboard, upon exiting the application you should re-place the data on the clipboard and persist it; so that the contents are still there for the user to use.

Conclusion

There you have it folks, the Clipboard in all its glory. Hope I didn't bore you too much. As always leave questions or comments below; and please e-mail me any bugs you find.

For those interested in the Visual Style I used in the screen shots, I got it from themexp.org; you'll also need StyleXP or the free update to uxtheme.dll from the same site.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) InfoPlanIT, LLC
United States United States
James has been programming in C/C++ since 1998, and grew fond of databases in 1999. His latest interest has been in C# and .NET where he has been having fun writing code starting when .NET v1.0 was in its first beta.

He is currently a senior developer and consultant for InfoPlanIT, a small international consulting company that focuses on custom solutions and business intelligence applications.

He was previously employed by ComponentOne where he was a Product Manager for the ActiveReports, Data Dynamics Reports, and ActiveAnalysis products.

Code contained in articles where he is the sole author is licensed via the new BSD license.

Comments and Discussions

 
Generalcustom formats - DataRow Pin
mike melchi11-Oct-02 8:10
mike melchi11-Oct-02 8:10 
GeneralHow I handled this issue Pin
Mike_in_Paradise10-Feb-04 13:06
Mike_in_Paradise10-Feb-04 13:06 
GeneralGood one Pin
18-Jun-02 8:33
suss18-Jun-02 8:33 
GeneralRe: Good one Pin
James T. Johnson18-Jun-02 18:30
James T. Johnson18-Jun-02 18:30 
GeneralCopy metafile to the clipboard Pin
9-Jun-02 20:10
suss9-Jun-02 20:10 
GeneralRe: Copy metafile to the clipboard Pin
James T. Johnson18-Jun-02 18:27
James T. Johnson18-Jun-02 18:27 
GeneralRe: Copy metafile to the clipboard Pin
wout de zeeuw26-Jul-04 9:57
wout de zeeuw26-Jul-04 9:57 
GeneralCool ! Pin
Mauricio Ritter4-Jun-02 3:46
Mauricio Ritter4-Jun-02 3:46 
Congrats James... cool article. Are those "types" stored in the clipboard the same as the mime type (the ones at windows registry) ? I didn´t download the source yet (I don´t have VS.NET at work).

Mauricio Ritter - Brazil
Sonorking now: 100.13560 Trank

Beer | [beer] The alcohol is one of the greatest enemys of man, but a man who flee from his enemys is a coward. Beer | [beer]
GeneralRe: Cool ! Pin
James T. Johnson4-Jun-02 8:18
James T. Johnson4-Jun-02 8:18 
QuestionFinally, huh James? Pin
Nish Nishant3-Jun-02 22:52
sitebuilderNish Nishant3-Jun-02 22:52 
AnswerRe: Finally, huh James? Pin
James T. Johnson4-Jun-02 8:18
James T. Johnson4-Jun-02 8:18 
GeneralRe: Finally, huh James? Pin
Nish Nishant4-Jun-02 15:26
sitebuilderNish Nishant4-Jun-02 15:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.