DRAGGING ICONS

My application involves dragging icons from a property page in a modeless property sheet dialogue onto a view window. I am having trouble implementing this - currently I can only drag the icon around the original property page (use begindrag, mousemove and lbuttonup functions) and have problems when I try to drag it out this window.
Can anyone outline a procedure for this - ie dragging an icon between different windows.
rangers99Asked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
jim_pettinatoConnect With a Mentor Commented:
My CView derived code has been drag/drop enabled for either text or a custom object derived from CButton. It should not be to difficult to modify the custom object handling to handle a bitmap or icon. All I am really doing is passing a pointer to the original object, which I use to make a new copy and duplicate at the drop location.

The trick is twofold... define a new clipboard format type and
handle objects of that type dragged into your view.

Add the following members to your CView derived class:

   COleDropTarget m_dropTarget;
   UINT m_nClipFormat;

In your target view's OnCreate member, define a new clipboard format like this: (my view is derived from CScrollView)

int CMyView::OnCreate(LPCREATESTRUCT *lpCreateStruct)
{
   if (CScrollView::OnCreate(lpCreateStruct) == -1)
      return -1;

   m_dropTarget.Register(this);
   m_nClipFormat = RegisterClipboardFormat("MyItemEntry");
   ASSERT((m_nClipFormat >= 0xC000) && (m_nClipFormat <= 0xFFFF));
   return 0;
}


Now in the dragged object's OnLButtonDown method, do the following:

void CMyItem::OnLButtonDown(UINT nFlags, CPoint point)
{
     STGMEDIUM stgMyItem;
     CMyItem *rec = this;
     stgRptItem.tymed = TYMED_HGLOBAL;
     stgRptItem.hGlobal = ::GlobalAlloc(GMEM_SHARE, sizeof(rec));
     memcpy(stgRptItem.hGlobal, &rec, sizeof(rec));

     COleDataSource src;
     src.CacheData((BYTE)m_nClipFormat, &stgRptItem);
     src.DoDragDrop();
     ::GlobalFree(stgText.hGlobal);
     ::GlobalFree(stgRptItem.hGlobal);

     CButton::OnLButtonDown(nFlags, point);
}

Then, in the target view, override the following 3 functions:

DROPEFFECT CMyView::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
{
  // don't need any special initial handling for my object types
   return OnDragOver(pDataObject, dwKeyState, point);
}

DROPEFFECT CMyView::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)
{
       if (ChildWindowFromPoint(point) != this)  // is mouse  over another child item?
          return DROPEFFECT_NONE;  

       if ((pDataObject->IsDataAvailable(CF_TEXT))
       ||  (pDataObject->IsDataAvailable((BYTE)m_nClipFormat)) )
       {
          // we allow copying or moving of text or custom format, depending on the state
          if (dwKeyState & MK_CONTROL) {
             return DROPEFFECT_COPY;
          }
          else {
             return DROPEFFECT_MOVE;
          }
       }

       // unknown format: reject
       return DROPEFFECT_NONE;
}


BOOL CReportView::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)
{
   ReportItem *item;
   BOOL bResult = FALSE;

   if (pDataObject->IsDataAvailable((BYTE)m_nClipFormat))
     {
        STGMEDIUM stg;
        if (pDataObject->GetData((BYTE)m_nClipFormat, &stg))
          {
             CMyItem* pRec=(CMyItem*)::GlobalLock(stg.hGlobal);
             RECT rect;
             rect.left = point.x;
             rect.top = point.y;
             CString text = pRec->text;
             rect.right = rect.left + text.GetLength()*m_textDims.cx + 2;
             rect.bottom = rect.top + m_textDims.cy + 2;
             if (dropEffect == DROPEFFECT_MOVE)
               pRec->Move(point, this);
             else
               {
                 item  = new CMyItem(point, pRec->item, this);
                 // add item to document list
                 GetDocument()->m_list.AddTail(item);
                 GetDocument()->SetModifiedFlag();
               }
             bResult = TRUE;
             ::GlobalUnlock(stg.hGlobal);
          }
     }
   else if (pDataObject->IsDataAvailable(CF_TEXT))
     {
        STGMEDIUM stg;
        if (pDataObject->GetData(CF_TEXT, &stg))
          {
             char* pszText = (char*) ::GlobalLock(stg.hGlobal);
             item = new MyObject(point,
                                    pszText, this);
             item->type = ReportItem::USERTEXT;
             // Add the Object to the document
             GetDocument()->m_list.AddTail(item);
             GetDocument()->SetModifiedFlag();
             bResult = TRUE;
             ::GlobalUnlock(stg.hGlobal);
          }
     }
   return bResult;
}

You will notice that I added constructors and a Move method to
my CButton derived CMyItem class that simplified moving/ copying objects to a drop location. This makes the view's code quite a bit more straightforward.

Good Luck!
0
 
rangers99Author Commented:
Adjusted points to 400
0
 
jim_pettinatoCommented:
I left out one thing: the m_nClipFormat variable in the drop targed CView must be available to the source item (in my case, the CButton-derived CMyItem). I did this by creating a public static m_nClipFormat member in the CMyItem class and assigning it once the CView-derived class has the format registered. This variable appears in the CMyItem::OnLButtonDown, but I forgot to show you that I added this member to the CMyItem class and assigned it (I think I assigned it in the view's OnInitialUpdate() method, I don't know why, I could have done it in the OnCreate as soon as I had the format registered).
0
 
rangers99Author Commented:
Cheers. I should be able to modify this to work with icons.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.