Solved

DRAGGING ICONS

Posted on 1998-12-15
4
321 Views
Last Modified: 2010-04-02
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.
0
Comment
Question by:rangers99
  • 2
  • 2
4 Comments
 

Author Comment

by:rangers99
ID: 1180251
Adjusted points to 400
0
 
LVL 1

Accepted Solution

by:
jim_pettinato earned 400 total points
ID: 1180252
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
 
LVL 1

Expert Comment

by:jim_pettinato
ID: 1180253
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
 

Author Comment

by:rangers99
ID: 1180254
Cheers. I should be able to modify this to work with icons.
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

861 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question