Enabling Edit/Paste

Any programmer who has ever implemented Paste functionality in an application has gone through the rite of processing WM_INITMENUPOPUP and deciding whether to enable the Paste menu item depending on the formats available on the clipboard. This user interface does not change with OLE; what does change is the way you can implement it using data objects.

I want to stress the phrase "can implement" because OLE does not force you to use data objects for enabling paste or for performing a paste. OLE is simply a convenient way of doing it. The big advantage is that once you write a piece of code to enable pasting or to paste from a data object, that same code can be used in OLE Drag and Drop, which we'll cover in Chapter 13. By adding support for additional formats to your code, you expand the capabilities of both protocols to enable the pasting of things such as compound document objects and controls.

As you can see in the following code, the OLE method is only a matter of asking the data object to go through this sequence:

Call OleGetClipboard to retrieve an IDataObject pointer for the clipboard.

Call IDataObject::QueryGetData for each format you would pass to the Windows function IsClipboardFormatAvailable. If successful, enable the Edit/Paste menu item. If no formats are available, disable the item.

Call IDataObject::Release when finished.


BOOL CCosmoDoc::FQueryPaste(void)
{
LPDATAOBJECT pIDataObject;
BOOL fRet;

if (FAILED(OleGetClipboard(&pIDataObject)))
return FALSE;

fRet=FQueryPasteFromData(pIDataObject);
pIDataObject->Release();
return fRet;
}

BOOL CCosmoDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject)
{
FORMATETC fe;

SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
return (NOERROR==pIDataObject->QueryGetData(&fe));
}

Cosmo's CCosmoDoc::FQueryPaste function, which used to call IsClipboardFormatAvailable, now retrieves the clipboard's IDataObject and sends it to CCosmoDoc::FQueryPasteFromData, which determines whether it can be pasted with IDataObject::QueryGetData before releasing the pointer. I strongly encourage you to implement a function like FQueryPasteFromData. With such a function in place, you can pass any data object to it, whether you get the pointer from OleGetClipboard, from a drag-and-drop operation, or from some QueryInterface. A function like this gives you a single place to add new formats that you might support with additional OLE work.