Delayed Rendering of Clipboard Data

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Programs such as Word use multiple Clipboard formats and copying them all to the Clipboard whenever copy or cut options are selected will be a waste as it’s unlikely that all of them would be used at once.

Windows provides an intelligent alternative to simply copy all the data on the Clipboard. An application sending data to the Clipboard can register the Clipboard format without passing any data. This is done by passing null as the handle to the data block when SetClipboardData () is called. The effect of passing a null handle is that the Clipboard doesn’t recieve any data but it records that it will be provided with the data when it’s needed.

For an example, you can set the null data handle for a CF_TEXT clipboard format:

OpenClipboard ();
EmptyClipboard ();
SetClipboardData (CF_TEXT, NULL);
CloseClipboard ();

When you need to paste that data into, say, Notepad, Windows recognizes that the CF_TEXT data needs to be loaded and it sends a WM_RENDERFORMAT message to the window that called SetClipboardData () with a null handle. The program then calls SetClipboardData () again, but this time passes a handle to a memory block containing the data. And then, Windows pastes the data into Notepad.

There is one situation that pops up when an application uses delayed rendering. That is what will happen when the application that’s to supply the data is terminated before the Clipboard data is requested. In such a situation, the supplying program recieves a WM_RENDERALLFORMATS message before it terminates. The result is that the data is put in the Clipboard before the program terminates and is available to all other programs.

In the included project, the application displays a message when the Clipboard asks for the data to be copied to it. To see it, type some text in the edit box on the dialog box then click copy to Clipboard. Then, open Notepad and press Ctrl + V; at this time, the application will display a message.

The following code from the included project will make things clearer.

void CDelayedrenderingDlg::OnCopy()
{
   //Open the Clipboard and then clear its contents
   OpenClipboard ();
   EmptyClipboard ();

   //Now, instead of the memory handle we pass NULL;
   //this indicates that the data will be made available
   //when the user requests it.
   SetClipboardData (CF_TEXT, NULL);
   CloseClipboard ();
}

void CDelayedrenderingDlg::OnRenderFormat (UINT nFormat)
{
   //Check whether the requested data is of type text
   if (nFormat == CF_TEXT)
   {
      //Get the data from the edit control and put it on the
      //Clipboard because the user has requested it
      CString strEditText;
      HANDLE hClipboard;
      LPTSTR lpszBuffer;

      (GetDlgItem (IDC_EDIT))->GetWindowText (strEditText);

      hClipboard = GlobalAlloc (GPTR, strEditText.GetLength () + 1);
      lpszBuffer = (LPTSTR) GlobalLock (hClipboard);
      _tcscpy (lpszBuffer, strEditText);
      GlobalUnlock (hClipboard);

      //Note that we don't open the Clipboard here because it's
      //already opened by the application that needs the data
      SetClipboardData (CF_TEXT, hClipboard);
      CloseClipboard ();
   }
   AfxMessageBox (_T("Data send to the clipboard"));
}

void CDelayedrenderingDlg::OnRenderAllFormats ()
{
   //The application recieves this message before it quits so
   //that the data could be put on the Clipboard

   //Get the data from the edit control and put it on the
   //Clipboard because the user has requested it
   CString strEditText;
   HANDLE hClipboard;
   LPTSTR lpszBuffer;

   //This time we need to open the Clipboard
   OpenClipboard ();
   EmptyClipboard ();

   (GetDlgItem (IDC_EDIT))->GetWindowText (strEditText);

   hClipboard = GlobalAlloc (GPTR, strEditText.GetLength () + 1);
   lpszBuffer = (LPTSTR) GlobalLock (hClipboard);
   _tcscpy (lpszBuffer, strEditText);
   GlobalUnlock (hClipboard);

   //Set the text on the Clipboard and then close it
   SetClipboardData (CF_TEXT, hClipboard);
   CloseClipboard ();
   AfxMessageBox (_T("Application terminating, so data copied to
                      Clipboard."));
}

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read