Delayed Rendering of Clipboard Data
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."));
}

Comments
Why OnRenderFormat( ) be done when I copy string.
Posted by bo60503 on 01/07/2006 02:26amWhen I copy string to the edit. The Message of 'Data send to the clipboard' apear. In the message_map have two function, I cann't understand. ON_WM_RENDERFORMAT() ON_WM_RENDERALLFORMATS()
-
Reply
ReplyWhy OnRenderFormat( ) be done when I copy string
Posted by logan on 01/07/2006 02:15pmBE CAREFUL WITH THIS CODE
Posted by hollebeek on 01/04/2006 04:24pmThis is *not* the way delayed rendering should be implemented, as it has a serious race condition. Image the sequence (1) copy, (2) modify edit box, (3) paste old copied text into notepad. A correct implementation will paste the copied text, but this version will paste the modified text. Beware of "optimizations" that break your application's behavior. WHENEVER you are using caching or delayed computation, ALWAYS think about race conditions and make sure your debug version has ASSERTs that guarantee the results are the same as the "straightforward" implementation.
ReplyNice one
Posted by kirants on 01/03/2006 03:07pm