Click here to Skip to main content
Click here to Skip to main content

Implementing a drag source

By , 9 Nov 2000
 

This article is part of the drag and drop interface samples.

  1. Serializing ASCII Data
  2. Modeless child dialog
  3. Modeless sibling dialog
  4. The drag source
  5. The MFC drop target
  6. The TBTextTarget class

Data is going abroad... implementing the drag source

Again, the implementation of this idea is in two different versions.

Version one uses user-defined data and may better fit your needs.

As we are dealing here with a list control, it may be considerable to use a standard format instead with version two. As a side-effect, you can now drag the contents of your list control to Word, Excel, Visual Studio, or any other drop-enabled texteditor - do I see you smile?

Both versions are very similar. To implement both of them with my application, I made use of the registry settings. Use the menu items at "Clipboard format" or the HKEY_CURRENT_USER\Software\Codeguru\Interface\DragDrop\Clipformat string to specify either the default of "Common" or the string "Private". Any other value will cause an error message and the assumption of the Common type.

Follow these steps:

  1. To the view, add a member-variable of type UINT:
    UINT m_DragDropFormat;
  2. In the constructor of the view, initialize it for private data exchange with:
    m_DragDropFormat = 
        ::RegisterClipboardFormat("YourInterfaceClipboardFormat");

    and for the common format just use:

    m_DragDorpFormat = CF_TEXT;

    Do the same to your drop target. In our case, it’s either of the modal dialogs created in step one.

  3. Add the following lines to stdafx.h:
    #include <afxdisp.h>
    #include <afxole.h>

    In your application’s InitInstance function, make a call to AfxOleInit() before creating the document template

  4. #include <afxadv.h> in your drag-source-class source file (or in stdafx.h, its for CSharedFile used in Step 5).
  5. (Private data) Use the Class Wizard to add a message handler to your view, which responds to the LVN_BEGINDRAG message of the list control. Here is the function OnBeginDragList1 for the private-data-version:
    void CInterfaceView::OnBeginDragList1(NMHDR* pNMHDR, LRESULT* pResult) 
    {
            NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
            *pResult = 0;
    
           // Create the drag&drop source and data objects
            COleDropSource *pDropSource = new COleDropSource;
            COleDataSource *pDataSource = new COleDataSource;
    
            // now determine which rows are selected
            // copy from the CListCtrl section
            int idx = GetSelectedItem(); 
    
            if (idx == -1 || !m_DragDropFormat) 
            {
                // nothing selected (must be for dragging)
                // or error while registering the clipboard format
                ASSERT(FALSE);
                return;
            }
    
            // now grab the data (here: the count and text)
            // and serialize (hoho!)  it into an clipboard archive
            CString Data;
            // getting the column count, thanks Zafir!
            CHeaderCtrl* pHeader = (CHeaderCtrl*)m_Table.GetDlgItem(0);
            int number = m_Table.GetSelectedCount(),
                colCou = pHeader?pHeader->GetItemCount():0;
    
            TRY
            {
                CSharedFile file(GMEM_ZEROINIT|GMEM_DDESHARE|GMEM_MOVEABLE);
                TRY
                {
                    CArchive ar(&file, CArchive::store);
                    TRY
                    {
                // Write the number of items and columns
                ar << number;
                        ar << colCou
                        do 
                        {
                for (int i=0; i<colCou; i++)
                {
                    Data = m_Table.GetItemText(idx, i);
                    ar << Data ;
                }
                idx = GetSelectedItem(idx); 
                } while (idx != -1);
                ar.Close();
                    }
                    CATCH_ALL(eInner)
                    {
                // exception while writing into or closing the archive
                ASSERT(FALSE);
                    }
                    END_CATCH_ALL;
                }
                CATCH_ALL(eMiddle)
                {
                    // exception in the destructor of ar
                    ASSERT(FALSE);
                }
                END_CATCH_ALL;
    
                // put the file object into the data object
                pDataSource->CacheGlobalData(m_DragDropFormat, file.Detach());
                pDataSource->DoDragDrop(DROPEFFECT_MOVE|DROPEFFECT_COPY, 
                                                        NULL, pDropSource);
            }
            CATCH_ALL(eOuter)
            {
                // exception while destructing the file
                ASSERT(FALSE);
            }
            END_CATCH_ALL;
        
            delete pDropSource;
            delete pDataSource;
        }

    Here is the function OnBeginDragList1 for the common-data-version. It even allows you to drag your data to Excel! (common data)

        //... the same until
        CSharedFile file;
        TRY
            {
                CArchive ar(&file, CArchive::store);
                TRY
                {
                    // for CF_TEXT use a flat ASCII-stream
                    // using tabs as delimiter will cause Excel and others to
                    // understand us that we have a table
                    CString number;
                    number.Format("%i\n", m_Table.GetSelectedCount());
                    ar.WriteString(number);
                    do 
                    {
                           Data.Empty();
                           for (int i=0; i<colCou; i++)
                               Data += m_Table.GetItemText(idx, i) + "\t";
                           ar.WriteString(Data + "\n");
                           idx = GetSelectedItem(idx); 
                    } while (idx != -1);
        
                    ar.Close();
                }
                CATCH_ALL(eInner)
                    // and do the rest as above ...

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Thomas Blenkers
Web Developer
Germany Germany
Member
PhD Chemist,
programming with MSVC & MFC since 1996

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Questiondrag sourcememberKeith Meredith16 Feb '12 - 7:00 
you guys are good!
GeneralDebugging drag-fropmemberrajas20 Apr '03 - 5:48 
Can someone tell me how I can debug my drag-drop implementation? Obviously i cannot step through my code - and usually I just manage to 'hang' either my application or MSVC6.
Secondarily, I have drag-drop working between different windows in my application; but I am not able to drag items on to other applications (say MSWord). However, I can use the clipboard! I use the same code to create the datasource (am using COleDataSource ) - in one instance it is SetClipboard and in another it is DoDragDrop. This has been rather frustrating.
Generalwhy do drag n drop examples only have CF_Text implementationsmemberShoki22 Apr '02 - 6:59 
i just can't seem to understand that there r so many drag n drop examples on CF_Text and not a single one on CF_Bitmap, i am really frustrated
 
Ashok Singh

GeneralMultiple Drag FormatsmemberErnesto Perales Soto1 Aug '01 - 10:27 
Hi Thomas,
 
I'm wondering if it is possible to write a drag source that serializes both formats to clipboard at the same time?
GeneralCorrection: InterfaceView.obj : error LNK2001: unresolved external ...memberThomas Blenkers3 Jun '01 - 11:41 
Steps 2 and 3 of my example code refers to an class only needed with step 1.
 
I have corrected that and put a new interface.zip file on my
website at http://www.blenkers.de/interface/interface.zip
 
You may download it from there or do the following modifcations
1. Remove the #include "otherdropdialog.h" from *.cpp
2. Remove the function CInterfaceView::OnFileOthermodeless() using the
context menu in the class view. (This will remove the function declaration
and message map entries as well)
 
Sorry,
Thomas

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 10 Nov 2000
Article Copyright 2000 by Thomas Blenkers
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid