Clipboards
Tutorial


by Itay Sagui

Mostly used in all kind of editors, like notepad/Word/Photoshop, the clipboard is a very powerful tool, if you know how to use it properly.

An application can place more than one object on the clipboard, in several different formats. Let's look at the different formats that can be used:

1. Standart formats:

CF_BITMAP - A handle to a bitmap (HBITMAP).
CF_DIB - A memory object containing aBITMAPINFO structure followed by the bitmap bits.
CF_DIBV5 - Windows NT 5.0: A memory object containing aBITMAPV5HEADER structure followed by the bitmap color space information and the bitmap bits.
CF_DIF - Software Arts' Data Interchange Format.
CF_ENHMETAFILE - A handle of an enhanced metafile (HENHMETAFILE).
CF_HDROP - A handle of type HDROP that identifies a list of files.
CF_METAFILEPICT - Handle of a metafile picture format as defined by the METAFILEPICT structure.
CF_OEMTEXT - Text format containing characters in the OEM character set. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data.
CF_PALETTE - Handle of a color palette. Whenever an application places data in the clipboard that depends on or assumes a color palette, it should place the palette on the clipboard as well.
CF_RIFF - Represents audio data more complex than can be represented in a CF_WAVE standard wave format.
CF_TEXT - Text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data. Use this format for ANSI text.
CF_WAVE - Represents audio data in one of the standard wave formats, such as 11 kHz or 22 kHz pulse code modulation (PCM).
CF_TIFF - Tagged-image file format.
CF_UNICODETEXT - Windows NT: Unicode text format. Each line ends with a carriage return/linefeed (CR-LF) combination. A null character signals the end of the data.


2. Registered Formats

The system allows you to register custom formats, to be used in your application, in case the standart formats are not enough. An example to these formats is the RTF format, that allows the clipboard to hold formatted text. in order to register a new format, you should use the RegisterClipboardFormat API, by passing it the new format's name, and get back the new format's ID. You can always retrieve the format's name using the GetClipboardFormatName API and passing it the format's ID. Here are the declarations of these APIs:


Private Declare Function RegisterClipboardFormat Lib "user32" Alias "RegisterClipboardFormatA" (ByVal
lpString As String) As Long Private Declare Function GetClipboardFormatName Lib "user32" Alias "GetClipboardFormatNameA" (ByVal
wFormat As Long, ByVal lpString As String, ByVal nMaxCount As Long) As Long


3. Multiple Formats

This is not exactly a format, but a way of using the formats. When putting information on the clipboard, you should put as much formats as you can, all placed from the most descriptive, to the least. For example, when copying formatted text, you should put data on a registered format, such as RTF, and then put the test in the CF_TEXT format. The reason for doing that is that when enumerating the data in the clipboard, the data appear in the order that it was put in. And since an application uses the first format it recognized, this is the best method to transfer the data.

4. Synthesized Formats

Again, this is more a feature, than a format. The system automaticaly convert from certain formats to other, in case it does not find the reqested data in the requested format. For example, if your application request data in the CF_DIB format, and it is not found, but data is available in the CF_BITMAP format, the system will provide the translated format instead. Of course, if the system can automaticaly convert from one format to another, there's no need to put the data in the clipboard yourself. Here's the conversion table from the MSDN:


Clipboard Format 	Conversion Format 		Platform Support 
---------------------------------------------------------------------------------------------
CF_BITMAP 		CF_DIB 				Windows NT, Windows 95, Windows 98 
CF_BITMAP 		CF_DIBV5 			Windows NT 5.0 
CF_DIB 			CF_BITMAP 			Windows NT, Windows 95, Windows 98 
CF_DIB 			CF_PALETTE 			Windows NT, Windows 95, Windows 98 
CF_DIB 			CF_DIBV5 			Windows NT 5.0 
CF_DIBV5 		CF_BITMAP 			Windows NT 5.0 
CF_DIBV5 		CF_DIB 				Windows NT 5.0 
CF_DIBV5 		CF_PALETTE 			Windows NT 5.0 
CF_ENHMETAFILE 		CF_METAFILEPICT 		Windows NT, Windows 95, Windows 98 
CF_METAFILEPICT 	CF_ENHMETAFILE 			Windows NT, Windows 95, Windows 98 
CF_OEMTEXT 		CF_TEXT 			Windows NT, Windows 95, Windows 98 
CF_OEMTEXT 		CF_UNICODETEXT 			Windows NT 
CF_TEXT 		CF_OEMTEXT 			Windows NT, Windows 95, Windows 98 
CF_TEXT 		CF_UNICODETEXT 			Windows NT 
CF_UNICODETEXT 		CF_OEMTEXT 			Windows NT 
CF_UNICODETEXT 		CF_TEXT 			Windows NT 



That's it for the different clipboard formats. There are a few more standart formats, that I chose to ignore in this article.

An application should put data on the clipboard when cutting and copying, and retrieving data from the clipboard when pasting. In order to use the clipboard, you must first open it, using the OpenClipboard API, and then close it, using the CloseClipboard API. Only one application can have access to the clipboard at each moment, which means that you should close it, whenever you finished whatever you're doing with it.


Private Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function CloseClipboard Lib "user32" () As Long



The OpenClipboard function needs the hwnd of the window that called it. You can send it a Null value, but this is not recommended.

When placing data in the clipboard, you have to empty it first. Use the EmptyClipboard to do so:


Private Declare Function EmptyClipboard Lib "user32" () As Long



For each format that you wish to place on the clipboard, you have to call the SetClipboardData function. The first parameter that the function accept is the data format. This can be any of the standart formats, or the ID you got for a registered format. The second parameter is the handle of the data.


Private Declare Function SetClipboardData Lib "user32" (ByVal wFormat As Long, ByVal hMem As Long) As Long



To retrieve data from the clipboard, the application has 2 options. The first one is to enumerate the different available formats, and use the first one it recognize. The second one is identify the best available format. Here are 3 functions that you can use:


Private Declare Function EnumClipboardFormats Lib "user32" (ByVal wFormat As Long) As Long

Private Declare Function GetPriorityClipboardFormat Lib "user32" (lpPriorityList As Long, 
ByVal nCount As Long) As Long Private Declare Function IsClipboardFormatAvailable Lib "user32" (ByVal wFormat As Long) As Long


The first function returns the next format after the one that you specify. The second one accept an empty array, and the number of items it has, and in return, fills the array with the available formats, ordered by priority. The last function allows you to determinate if a certain format is available, which is very useful is you application supports only one format.

After you've decided which format you want, you should use the GetClipboardData function to retrieve the data itself. This function receive the desired format, and returned the address of the data. Here's how you use it:


Private Const CF_TEXT = 1
Private Declare Function GetClipboardData Lib "user32" (ByVal wFormat As Long) As Long
Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As
Long, ByVal ByteLen As Long) hStrPtr = GetClipboardData(CF_TEXT) If hStrPtr <> 0 Then lLength = lstrlen(hStrPtr) If lLength > 0 Then sBuffer = Space$(lLength) CopyMemory ByVal sBuffer, ByVal hStrPtr, lLength MsgBox sBuffer, vbInformation End If End If


As you can see, using the clipboard is simple, once you get a grip of it. I strongly recommend you to read the MSDN documentation on clipboards, since there you'll be able to find information about the other formats that I left out of this article, and on other nice features, like the ability to send the data to the clipboard only when it was requested, something that is called "Delayed Rendering"