A drop target must provide user feedback, that is, the visual indication to the user of how the window would respond to a drag-and-drop operation. For an application such as a word processor, this might consist of a shaded caret indicating where the dropped object would be inserted. For DRAWCLI, user feedback consists of a focus rectangle indicating the size and position of the object if it were to be dropped.
DRAWCLI declares some new member variables to manage this user feedback. The relevant declarations in CDrawView
are as follows:
CPoint m_dragPoint; // current position
CSize m_dragSize; // size of dragged object
CSize m_dragOffset; // offset of focus rect
DROPEFFECT m_prevDropEffect;
static CLIPFORMAT m_cfObjectDescriptor;
BOOL m_bDragDataAcceptable;
BOOL GetObjectInfo(COleDataObject* pDataObject,
CSize* pSize, CSize* pOffset);
Some of the member variables store the size and position of the focus rectangle. The m_bDragDataAcceptable
is a flag indicating whether usable data is available from the drag-and-drop operation. The GetObjectInfo
function is a helper function described below.
Two of the member variables must be initialized. One of them is m_prevDropEffect
, which gets initialized in the CDrawView
constructor:
m_prevDropEffect = DROPEFFECT_NONE;
The other one is m_cfObjectDescriptor
; this was declared as a static member, which means that it must be initialized at file scope, outside of the CDrawView
constructor:
CLIPFORMAT CDrawView::m_cfObjectDescriptor =
(CLIPFORMAT)::RegisterClipboardFormat(_T("Object Descriptor"));
DRAWCLI registers the string “Object Descriptor” so it can get the handle for the CF_OBJECTDESCRIPTOR Clipboard format defined by OLE. This handle is used below in the CDrawView::GetObjectInfo
helper function.
Before DRAWCLI can draw this focus rectangle, it needs to know the size of the object. This is the purpose of the GetObjectInfo
helper function; this function queries a data object for the CF_OBJECTDESCRIPTOR clipboard format:
BOOL CDrawView::GetObjectInfo(COleDataObject* pDataObject,
CSize* pSize, CSize* pOffset)
{
ASSERT(pSize != NULL);
// get object descriptor data
HGLOBAL hObjDesc =
pDataObject->GetGlobalData(m_cfObjectDescriptor);
if (hObjDesc == NULL)
{
if (pOffset != NULL)
*pOffset = CSize(0, 0); // fill in defaults instead
*pSize = CSize(0, 0);
return FALSE;
}
ASSERT(hObjDesc != NULL);
// else, got CF_OBJECTDESCRIPTOR. Lock it down and extract size.
LPOBJECTDESCRIPTOR pObjDesc =
(LPOBJECTDESCRIPTOR)GlobalLock(hObjDesc);
ASSERT(pObjDesc != NULL);
pSize->cx = (int)pObjDesc->sizel.cx;
pSize->cy = (int)pObjDesc->sizel.cy;
if (pOffset != NULL)
{
pOffset->cx = (int)pObjDesc->pointl.x;
pOffset->cy = (int)pObjDesc->pointl.y;
}
GlobalUnlock(hObjDesc);
GlobalFree(hObjDesc);
// successfully retrieved pSize & pOffset info
return TRUE;
}
This function calls COleDataObject::GetGlobalData and acquires the CF_OBJECTDESCRIPTOR data in a block of global memory. The function locks the memory down, reads the size attributes, and then unlocks and frees the block of memory. This function is used by OnDragEnter in the code samples in "Handling a Drag-and-Drop Operation."