When you put data into the clipboard, you generally make a copy of the data and give the clipboard a handle to a global memory block that contains the copy. For very large data items, this approach can waste memory. If the user never pastes that data into another program, it will continue to occupy memory space until it is replaced by something else.
You can avoid this problem by using a technique called ”delayed rendering,“ in which your program doesn't actually supply the data until another program needs it. Rather than give Windows a handle to the data, you simply use a NULL in the SetClipboardData call:
OpenClipboard (hwnd) ;
EmptyClipboard () ;
SetClipboardData (wFormat, NULL) ;
CloseClipboard () ;
You can have multiple SetClipboardData calls using different values of wFormat. You can use NULL parameters with some of them and real handles with others.
That's simple enough, but now the process gets a little more complex. When another program calls GetClipboardData, Windows will check to see if the handle for that format is NULL. If it is, Windows will send a message to the ”clipboard owner“ (your program) asking for a real handle to the data. Your program must then supply this handle.
More specifically, the ”clipboard owner“ is the last window that put data into the clipboard. Windows can identify the clipboard owner, because the OpenClipboard call requires a window handle. (Because programs can also call OpenClipboard when reading data from the clipboard or enumerating clipboard formats, it's really the EmptyClipboard call that establishes this window handle as the clipboard owner.)
A program that uses delayed rendering has to process three messages in its window procedure: WM_RENDERFORMAT, WM_RENDERALLFORMATS, and WM_DESTROY- CLIPBOARD. Windows sends your window procedure a WM_RENDERFORMAT message when another program calls GetClipboardData. The value of wParam is the format requested. When you process the WM_RENDERFORMAT message, don't open and empty the clipboard. Simply create a global memory block for the format given by wParam, transfer the data to it, and call SetClipboardData with the correct format and the global handle. Obviously, you'll need to retain information in your program in order to construct this data properly when processing WM_RENDERFORMAT. When another program calls EmptyClipboard, Windows sends your program a WM_DESTROYCLIPBOARD message. This tells you that the information to construct the clipboard data is no longer needed. You are no longer the clipboard owner.
If your program terminates while it is still the clipboard owner, and the clipboard still contains NULL data handles that your program set with SetClipboardData, you'll receive a WM_RENDERALLFORMATS message. You should open the clipboard, empty it, put the data in global memory blocks, and call SetClipboardData for each format. Then close the clipboard. The WM_RENDERALLFORMATS message is one of the last messages your window procedure receives. It is followed by a WM_DESTROYCLIPBOARD message (because you've rendered all the data) and then the normal WM_DESTROY.
If your program can transfer only one format of data to the clipboard (text, for instance), you can combine the WM_RENDERALLFORMATS and WM_RENDERFORMAT processing. The code will look something like this:
case WM_RENDERALLFORMATS :
OpenClipboard (hwnd) ;
EmptyClipboard () ;
// fall through
case WM_RENDERFORMAT :
[put text into global memory block]
SetClipboardData (CF_TEXT, hMem) ;
if (iMessage == WM_RENDERALLFORMATS)
CloseClipboard () ;
return 0 ;
If your program uses several clipboard formats, then you will want to process the WM_RENDERFORMAT message only for the format requested by wParam. You don't need to process the WM_DESTROYCLIPBOARD message unless it is burdensome for your program to retain the information necessary to construct the data.