Using the Clipboard

Using the Clipboard

You’ve no doubt written programs or at least parts of programs using the copy and paste approach, and so you know that the clipboard is a helpful feature for getting data from one place or application to another. That’s what the clipboard is all about—easy and fast data transfer between applications.

Although you could create an internal clipboard handling mechanism for your own application only, users expect that when they execute a cut or copy command in one application, they can then paste that data into another application. Providing clipboard support is essential, and the following subsections show you how to use the clipboard effectively.

Copying to the Clipboard

All work related to the clipboard is performed using the Clipboard class. The Clipboard class isn’t large—it supports only three methods, two to copy data to the clipboard and one to get at data on the clipboard. The two methods for putting data on the clipboard are shown in the following code. (The third method is discussed in the next section.)

 public static void SetDataObject(object);
 public static void SetDataObject(object, bool);

When you use the first method, data put on the clipboard is nonpermanent, which means that when your application closes, the last content you put on the clipboard is removed. The second method gives you a choice: setting the second Boolean parameter to true allows the data to remain on the clipboard even after your application quits, whereas setting it to false leads to the same behavior as the first method call—the data is removed on exit.

Any data you place on the clipboard replaces the data that was on the clipboard previously. For example, the following code replaces the contents of the clipboard with the string Hello World:

string strText = "Hello World";
Clipboard.SetDataObject(strText, true);

The data is copied to the clipboard; no object reference is kept to the original data. Therefore, the following code would be valid as well:

Clipboard.SetDataObject("Hello World", true);

As you know from other applications, you can copy various data formats, such as bitmaps, to the clipboard. This can be done in Visual C# too, as shown here:

Bitmap bmp2Clipboard = new Bitmap("pinz.jpg");
Clipboard.SetDataObject(bmp2Clipboard, true);

You can now go to your favorite paint program and paste the clipboard contents. The clipboard formats are well-defined (more on clipboard formats later in this chapter, in the section “Exploring Clipboard Formats”), and thus data can be retrieved by any application that uses the clipboard and accepts the format of the data that was put on the clipboard.

Retrieving Data from the Clipboard

Now that we’ve looked at copying data to the clipboard, let’s look at how to retrieve data from the clipboard. For this job, we’ll use the Clipboard class’s third method, as follows:

public static IDataObject GetDataObject();

This method returns a data object (or to be more correct, an interface of type IDataObject) that represents the data waiting on the clipboard. To retrieve data from the clipboard, you’ll use the following IDataObject methods (and their overloads) most often:

bool GetDataPresent(Type);
object GetData(Type);

When dealing with the clipboard, you always start by checking whether the data on the clipboard can be consumed by your application. For example, if you write a simple Notepad replacement, you want to paste text only, as shown here:

IDataObject data = Clipboard.GetDataObject();
if (data.GetDataPresent(typeof(string)))
{
    
    

}

After you’ve determined that the format on the clipboard can be accepted by your application, you get at the data by calling GetData. The following code snippet first checks for bitmap data format, then gets the bitmap from the clipboard, and then simply saves the result to disk:

IDataObject data = Clipboard.GetDataObject();
if (data.GetDataPresent(typeof(Bitmap)))
{
    Bitmap bmp = (Bitmap)data.GetData(typeof(Bitmap));
    bmp.Save(@"c:\cliptest.bmp");
    MessageBox.Show("Saved to c:\\cliptest.bmp");
}
else
{
    MessageBox.Show("Data not retrievable as bitmap");
}

Retrieving text from the clipboard is equally simple, as shown here:

IDataObject data = Clipboard.GetDataObject();
if (data.GetDataPresent(typeof(string)))
{
    string strData = (string)data.GetData(typeof(string));
    // Do processing.
    
    

}

The text and bitmap formats aren’t the only clipboard formats available. In the next section, we’ll examine the various clipboard formats in more detail.

Exploring Clipboard Formats

As mentioned, the clipboard isn’t limited to sharing only textual or bitmap data. It can provide interchange for many more formats; these formats are fields from the DataFormats class. Table 17-3 lists the field names and their string values (used by the Win32 API).

Having 21 formats at your disposal isn’t bad. (There are more, but these are the formats supported by the .NET Framework at this time.) But why are there so many formats dealing with textual data? The reason is that each of these formats is needed under different conditions. For example, Unicode came to the Windows scene a little later than standard ANSI text. If an application copies a Unicode string to the clipboard, you don’t want an ANSI application to then paste the Unicode string. That’s why the clipboard offers not only the format that was put on the clipboard, but also any applicable conversions.

To demonstrate that clipboard data can exist in various formats, the sample application ClipboardFormatsAvailable, on the companion CD, enumerates the formats that are available for pasting. Figure 17-9 shows the application enumerating formats for a string that was placed on the clipboard beforehand.

Figure 17-9.
Viewing available clipboard formats.

The code for getting at the formats isn’t complicated, as you can see:

private void cmdCheckClipboard_Click(object sender, System.EventArgs e)
{
    lbFormats.Items.Clear();
    IDataObject data = Clipboard.GetDataObject();
    
    string[] astrFormats = data.GetFormats(false);
    for (int i=0; i < astrFormats.Length; i++)
        lbFormats.Items.Add(astrFormats[i]);
}

All you need to do is call GetFormats. The Boolean parameter does make quite a difference, however. If you pass a value of false, as in this code, you get only formats that were put into the clipboard by the application, whereas passing true lets you also see the formats for which the clipboard can offer an automatic conversion. In this example, the native formats are System.String, UnicodeText, and Text; the additional convertible formats are Locale and OEMText. The native formats displayed include those that are put into the clipboard explicitly by the application that calls SetDataObject.

If you’re interested in an application that automatically checks the clipboard for updates (the sample requires a button click to check for new data), take a look at the article “Tool for Viewing Drag and Drop and Clipboard Formats,” located at http://www.codeproject.com/csharp/clipboardformatviewer.asp. This article shows you how to hook into the clipboard events, a feature that is currently not directly supported in the .NET Framework.

Your application can choose which data format it wants to retrieve by specifying the format string in the GetData call, as shown in the following code:

string strData = (string)Clipboard.GetData("Text", false)

Be sure to specify the second parameter, however. This parameter indicates whether your application will accept a converted format (true) or only a native format (false).

Storing the Same Data in Multiple Formats on the Clipboard

As you saw earlier in this chapter, in the section “Copying to the Clipboard,” the clipboard can hold only one item at a time. So how do you store the same data in multiple formats on the clipboard? The answer lies in the DataObject class, which implements the IDataObject interface. Aside from the constructors, DataObject offers four interesting implementations of SetData, as shown here:

void SetData(object data);
void SetData(string format, object data);
void SetData(Type type, object data);
void SetData(string format, bool autoConvert, object data);

The interesting part is that you can call SetData multiple times with different formats specified and then put the DataObject on the clipboard, as shown in the following example. The ClipboardSetDataObject application, on the companion CD, contains the complete code listing.

string strText = "Hello World";
string strHtml = "<h1>Hello World</h1>";
DataObject data = new DataObject();
data.SetData(strText);
data.SetData(DataFormats.Html, strHtml);
data.SetData("My.Internal.Format","Some internal data");
Clipboard.SetDataObject(data, true);

Using this technique, you can choose to paste either text or HTML data; you probably won’t use the custom format My.Internal.Format. Putting multiple formats on the clipboard is a cooperative approach, and it allows you to keep your custom formats on the clipboard too.



Part III: Programming Windows Forms