Providing Target Feedback

HomeOverviewHow Do I

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."