Click here to Skip to main content
Email Password   helpLost your password?

Introduction

The code uses Windows API calls to read and write into the clipboard.

It provides a ClipboardHelper, an easy to use API bridge, which offers, in addition, functions to serialize complex clipboard data to hard disk and restore them when you want, using the XmlSerializer, instead of the .NET Framework which can manage only CLR compliant data.

I tested it with Internet Explorer, Word, OpenOffice, including with image files.

Background

The .NET framework and the Windows.Forms.Clipboard class allows to manipulate only serializable data. So what happens if your clipboard contains data from a non-compliant application? Easy! The .NET Framework thinks that the clipboard is empty.

To read and manipulate these data, we need to call user32.dll and kernerl32.dll.

Using the code

The code includes two projects: the library ClipboardHelper, and the console application ClipboardTest.

The whole code is commented, to understand the API usage and the implemented saving process.

To use the library is really easy: it's a static class that exposes a static void ClipboardHelper.Serialize function to serialize the clipboard data to hard disk, and static void Deserialize to deserialize it and place it back into the clipboard, ready to be pasted.

    //Comment next line to end the demo mode

    //and backup your clipboard data.

    ClipboardHelper.Deserialize(demo);
    Console.WriteLine("restore the demo clipboard");

    //Open the clipboard and serialize into a directory

    ClipboardHelper.Serialize(fileName);
    Console.WriteLine("serialize clipboard to " + fileName);

    //Deserialize the clipboard and set data

    //to win clipboard ready to be pasted

    ClipboardHelper.Deserialize(fileName);
    Console.WriteLine("restore the clipboard " + fileName);

The test application shows an example of the ClipboardHelper in action. It deserializes the clipboard, after having copied some rows from Internet Explorer at the CodeProject homepage, backs it up, and deserializes it again, from the backup. After you run it, you have the clipboard backup in your own clipboard, ready to be pasted.

Inside the ClipboardHelper

Data returned by API calls are saved in [Serializable]DataClip objects. It allows to easily send the clipboard in a remoting context, and to save it via the XmlSerializer:

public static void SaveToFile(ReadOnlyCollection<DATACLIP> clipData, string clipName)
{
    IEnumerator<DATACLIP> cData = clipData.GetEnumerator();
    while (cData.MoveNext())
    {
        XmlSerializer xml = new XmlSerializer(typeof(DataClip));
        using (StreamWriter sw = new StreamWriter(di.FullName + 
                                 @"\" + i.ToString() + ".cli",false))
        {
            xml.Serialize(sw, cData.Current);
        }
    }
 }

Deep into the clipboard

The clipboard contains data in fragmented buffers. Each of them has a specific DataFormat that is used by the clipboard viewer and the software from which data has been copied, to recognize how to correctly render the buffer.

The function EnumClipboardFormats of user32.dll returns the array of DataFormats contained in the clipboard. For each DataFormat, we can call GetClipboardData. It returns the handle to the clipboard object. By calling GlobalSize and GlobalLock from kernel32.dll, we obtain the clipboard object properties (its length and the pointer to it), so we can copy the clipboard object into our buffer (a byte array) via the Marshal.Copy method.

To get the clipboard, first of all, check to open the clipboard:

Win32ClipboardAPI.OpenClipboard(IntPtr.Zero)

Then, we get all DataFormats; querying them we get the clipboard data buffer:

    //Init a list of ClipData,

    // which will contain each Clipboard Data

    List<DataClip> clipData = new List<DataClip>();
    //Loop for each clipboard data type

    uint format = 0;
    while ((format = Win32ClipboardAPI.EnumClipboardFormats(format)) != 0)
    {
        //Get the formatName

        StringBuilder formatName = new StringBuilder();
        Win32ClipboardAPI.GetClipboardFormatName(format, 
                                       formatName, 100);
        
        //Get the pointer for the current Clipboard Data 

        IntPtr pos = Win32ClipboardAPI.GetClipboardData(format);
        //Get the clipboard buffer data properties

        UIntPtr lenght = Win32MemoryAPI.GlobalSize(pos);
        IntPtr gLock = Win32MemoryAPI.GlobalLock(pos);
        byte[] buffer;
        //Init a buffer which will contain the clipboard data

        buffer = new byte[(int)lenght];
        int l = Convert.ToInt32(lenght.ToString());
        //Copy data from clipboard to our byte[] buffer

        Marshal.Copy(gLock, buffer, 0, l);
        //Create a ClipData object that 

        //represents the current clipboard data

        DataClip cd = new DataClip(format, 
                      formatName.ToString(), buffer);
        //Add current Clipboard Data to the list

        clipData.Add(cd);
}

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralOutlook problem
vice
9:44 12 Feb '07  
hi,

first, thanks for this great class.

but i have a problem in combination with outlook.
if you copy an attachment of a mail in outlook to the clipboard,
run your backup und restore function you can't paste the file anymore in a other mail
or somewhere else.

i have no idear what the problem is. i have also try it with this class http://www.codeproject.com/clipboard/cbbackup.asp

it's the same. Frown

idear?
thank you.
Thomas R.

GeneralClipboard application sometime working
nip90
9:38 14 Oct '06  
I'm using .NET 2.0 with VS 2005 on Windows XP Pro and I'm having problems with the clipboard.
I'm trying to copy the contents of a word document. The problem is that sometime it is working, and sometime not, using the same piece of code. I searched through the internet and implemented all recommendation including using API (as seen in this article). But nothing helps. It only works the first time I use the application and then I get null even though there is content in the clipboard.
Below is an excerpt from my code:

private static int Content()
{

// Some code
ClipboardData cd = new ClipboardData(doc); <= Passing Word.Document doc
string text = cd.S;

// some code
}

[Serializable]
public class ClipboardData
{
string s;
string fileName = @"tempClip";
public ClipboardData(Word.Document doc)
{
doc.ActiveWindow.Selection.WholeStory();
doc.ActiveWindow.Selection.Copy();

ClipboardHelper.Serialize(fileName);
ClipboardHelper.Deserialize(fileName);

IDataObject data = Clipboard.GetDataObject();
s = data.GetData(DataFormats.Text).ToString();
Clipboard.SetDataObject(string.Empty);
}
public string S
{
get
{
return s;
}
}
}

Any help will be highly appreciated as this drives me nuts.
GeneralRe: Clipboard application sometime working
Alessio Deiana
0:10 17 Oct '06  
I'm sure I did not focus enough on problems related to .net framework System.Windows.Forms.Clipboard class.
If I understood your message, you want to test my class using Microsoft Clipboard Class. You cannot! My ClipboardHelper wants to save the clipboard data, as they are saved on ram, an to restore them exactly as they were saved. ClipboardHelper.Deserialize deserilizes the file and restore immediatly it on the system clipboard, ready to be processed or pasted. So ClipboardHelper avoid problems related to the usage of System.Windows.Forms.Clipboard, but obviously you cannot use it properly using Microsoft Clipboard at the same time.
I hope I helped you.
Lemme know if my reply resolves your problem...
Alex
GeneralRe: Clipboard application sometime working
nip90
0:43 20 Oct '06  
Hi Alex,

Thank you for your reponse.
It seems that I'm missing something. I get the idea of serilaize and deserialize, but I can't seem to grasp how I'm going to take the desrialized data from the clipboard and assign it to a parameter of type string for further processing if I can't use clipboard.getdata().

Tzach.


Last Updated 20 Sep 2006 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010