| Tenouk C & C++ | MFC Home | Uniform Data Transfer & OLE 4 | Structured Storage 1 | Download | Site Index |


 

 

 

 

 

Uniform Data Transfer:

-Clipboard Transfer and OLE Drag and Drop 5-

 

 

 

 

 

Program examples compiled using Visual C++ 6.0 compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this tutorial are listed below. Don’t forget to read Tenouk’s small disclaimer. The supplementary notes for this tutorial are cdib.h, cdib.cpp, formatetc and IDataObject.

  1. The Story

  2. The CMymfc30bDoc Class

  3. The CMymfc30bView Class

  4. Windows Applications and Drag and Drop: Dobjview

  5. Conclusion

 

 

Add code to the implementation file mymfc30bView.cpp.

CMymfc30bView::CMymfc30bView() : m_sizeTotal(800, 1050), // 8-by-10.5 inches when printed

    m_rectTracker(50, 50, 250, 250),

    m_dragOffset(0, 0),

    m_rectTrackerEnter(50, 50, 250, 250)

{    }

 

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 5.

 

void CMymfc30bView::OnDraw(CDC* pDC)

{

    CDib& dib = GetDocument()->m_dib;

    m_tracker.m_rect = m_rectTracker;

    pDC->LPtoDP(m_tracker.m_rect);  // tracker wants device coords

    m_tracker.Draw(pDC);

    dib.UsePalette(pDC);

    dib.Draw(pDC, m_rectTracker.TopLeft(), m_rectTracker.Size());

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 6.

 

void CMymfc30bView::OnInitialUpdate()

{

    m_dropTarget.Register(this); // IMPORTANT

    SetScrollSizes(MM_TEXT, m_sizeTotal);

    m_tracker.m_nStyle = CRectTracker::solidLine | CRectTracker::resizeOutside;

    CScrollView::OnInitialUpdate();

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 7.

 

BOOL CMymfc30bView::DoPasteDib(COleDataObject *pDataObject)

{

    // update command UI should keep us out of here if not CF_DIB

    if (!pDataObject->IsDataAvailable(CF_DIB))

    {

      TRACE("CF_DIB format is unavailable\n");

      return FALSE;

    }

    CMymfc30bDoc* pDoc = GetDocument();

    // seems to be MOVEABLE memory, so we must use GlobalLock!

    //  (hDib != lpDib) GetGlobalData copies the memory, so we can

    //  hang onto it until we delete the CDib

    HGLOBAL hDib = pDataObject->GetGlobalData(CF_DIB);

    ASSERT(hDib != NULL);

    LPVOID lpDib = ::GlobalLock(hDib);

    ASSERT(lpDib != NULL);

    pDoc->m_dib.AttachMemory(lpDib, TRUE, hDib);

    GetDocument()->SetModifiedFlag();

    pDoc->UpdateAllViews(NULL);

    return TRUE;

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 8.

 

COleDataSource* CMymfc30bView::SaveDib()

{

      CDib& dib = GetDocument()->m_dib;

      if (dib.GetSizeImage() > 0) {

      COleDataSource* pSource = new COleDataSource();

      int nHeaderSize =  dib.GetSizeHeader();

      int nImageSize = dib.GetSizeImage();

      HGLOBAL hHeader = ::GlobalAlloc(GMEM_SHARE, nHeaderSize + nImageSize);

      LPVOID pHeader = ::GlobalLock(hHeader);

      ASSERT(pHeader != NULL);

      LPVOID pImage = (LPBYTE) pHeader + nHeaderSize;

      memcpy(pHeader, dib.m_lpBMIH, nHeaderSize);

      memcpy(pImage, dib.m_lpImage, nImageSize);

      // receiver is supposed to free the global memory

      ::GlobalUnlock(hHeader);

      pSource->CacheGlobalData(CF_DIB, hHeader);

      return pSource;

    }

    return NULL;

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 9.

 

void CMymfc30bView::MoveTrackRect(CPoint point)

{

    CClientDC dc(this);

    OnPrepareDC(&dc);

    dc.DrawFocusRect(m_rectTracker);

    dc.LPtoDP(m_rectTracker);

    CSize sizeTrack = m_rectTracker.Size();

    CPoint newTopleft = point - m_dragOffset;  // still device

    m_rectTracker = CRect(newTopleft, sizeTrack);

    m_tracker.m_rect = m_rectTracker;

    dc.DPtoLP(m_rectTracker);

    dc.DrawFocusRect(m_rectTracker);

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 10.

 

DROPEFFECT CMymfc30bView::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)

{

    // TODO: Add your specialized code here and/or call the base class

    TRACE("Entering CMymfc30bView::OnDragEnter, point = (%d, %d)\n", point.x, point.y);

 

    m_rectTrackerEnter = m_rectTracker; // Save original coordinates

                                        // for cursor leaving rectangle

    CClientDC dc(this);

    OnPrepareDC(&dc);

    dc.DrawFocusRect(m_rectTracker); // will be erased in OnDragOver

    return OnDragOver(pDataObject, dwKeyState, point);

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 11.

 

void CMymfc30bView::OnDragLeave()

{

    // TODO: Add your specialized code here and/or call the base class

    TRACE("Entering CMymfc30bView::OnDragLeave\n");

    CClientDC dc(this);

    OnPrepareDC(&dc);

    dc.DrawFocusRect(m_rectTracker);

    m_rectTracker = m_rectTrackerEnter; // Forget it ever happened

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 12.

 

DROPEFFECT CMymfc30bView::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)

{

   // TODO: Add your specialized code here and/or call the base class

   if (!pDataObject->IsDataAvailable(CF_DIB))

   { return DROPEFFECT_NONE; }

    MoveTrackRect(point);

    if((dwKeyState & MK_CONTROL) == MK_CONTROL)

    { return DROPEFFECT_COPY; }

    // Check for force move

    if ((dwKeyState & MK_ALT) == MK_ALT)

    { return DROPEFFECT_MOVE; }

    // default -- recommended action is move

    return DROPEFFECT_MOVE;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 13.

 

BOOL CMymfc30bView::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)

{

    // TODO: Add your specialized code here and/or call the base class

    TRACE("Entering CMymfc30bView::OnDrop -- dropEffect = %d\n", dropEffect);

    BOOL bRet;

    CMymfc30bDoc* pDoc = GetDocument();

    MoveTrackRect(point);

    if(pDoc->m_bDragHere)

    {

        pDoc->m_bDragHere = FALSE;

        bRet = TRUE;

    }

    else

    { bRet = DoPasteDib(pDataObject); }

    return bRet;

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 14.

 

void CMymfc30bView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)

{

    // TODO: Add your specialized code here and/or call the base class

    // custom MM_LOENGLISH with positive y down

    if(pDC->IsPrinting()) {

        int nHsize = pDC->GetDeviceCaps(HORZSIZE) * 1000 / 254;

        int nVsize = pDC->GetDeviceCaps(VERTSIZE) * 1000 / 254;

        pDC->SetMapMode(MM_ANISOTROPIC);

        pDC->SetWindowExt(nHsize, nVsize);

        pDC->SetViewportExt(pDC->GetDeviceCaps(HORZRES),

                            pDC->GetDeviceCaps(VERTRES));

    }

    else

    { CScrollView::OnPrepareDC(pDC, pInfo); }

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 15.

 

void CMymfc30bView::OnLButtonDown(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default

      CMymfc30bDoc* pDoc = GetDocument();

      if(m_tracker.HitTest(point) == CRectTracker::hitMiddle)

      {

        COleDataSource* pSource = SaveDib();

        if(pSource)

        {

            // DoDragDrop returns only after drop is complete

            CClientDC dc(this);

            OnPrepareDC(&dc);

            CPoint topleft = m_rectTracker.TopLeft();

            dc.LPtoDP(&topleft);

            // 'point' here is not the same as the point parameter in

            //  OnDragEnter, so we use this one to compute the offset

            m_dragOffset = point - topleft;  // device coordinates

            pDoc->m_bDragHere = TRUE;

            DROPEFFECT dropEffect = pSource->DoDragDrop(

                DROPEFFECT_MOVE|DROPEFFECT_COPY, CRect(0, 0, 0, 0));

            TRACE("after DoDragDrop -- dropEffect = %ld\n", dropEffect);

            if (dropEffect == DROPEFFECT_MOVE && pDoc->m_bDragHere)

            { pDoc->OnEditClearAll(); }

            pDoc->m_bDragHere = FALSE;

            delete pSource;

        }

    }

    else

    {

        if(m_tracker.Track(this, point, FALSE, NULL))

        {

            CClientDC dc(this);

            OnPrepareDC(&dc);

            // should have some way to prevent it going out of bounds

            m_rectTracker = m_tracker.m_rect;

            dc.DPtoLP(m_rectTracker); // Update logical coords

        }

    }

    Invalidate();

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 16.

 

BOOL CMymfc30bView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)

{

      // TODO: Add your message handler code here and/or call default

      if(m_tracker.SetCursor(pWnd, nHitTest))

      { return TRUE; }

      else

      { return CScrollView::OnSetCursor(pWnd, nHitTest, message); }

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 17.

 

void CMymfc30bView::OnEditCopy()

{

      // TODO: Add your command handler code here

      COleDataSource* pSource = SaveDib();

      if(pSource)

      { pSource->SetClipboard(); } // OLE deletes data source

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 18.

 

void CMymfc30bView::OnUpdateEditCopy(CCmdUI* pCmdUI)

{

      // TODO: Add your command update UI handler code here

      // serves Copy, Cut, and Copy To

    CDib& dib = GetDocument()->m_dib;

    pCmdUI->Enable(dib.GetSizeImage() > 0L);

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 19.

 

void CMymfc30bView::OnEditCopyto()

{

    // TODO: Add your command handler code here

    CDib& dib = GetDocument()->m_dib;

    CFileDialog dlg(FALSE, "bmp", "*.bmp");

    if(dlg.DoModal() != IDOK) return;

 

    BeginWaitCursor();

    dib.CopyToMapFile(dlg.GetPathName());

    EndWaitCursor();

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 20.

 

void CMymfc30bView::OnEditCut()

{

    // TODO: Add your command handler code here

    OnEditCopy();

    GetDocument()->OnEditClearAll();

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

------------------------------------------------------------------------------------------------

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 21.

 

 

void CMymfc30bView::OnEditPaste()

{

    // TODO: Add your command handler code here

    CMymfc30bDoc* pDoc = GetDocument();

    COleDataObject dataObject;

    VERIFY(dataObject.AttachClipboard());

    DoPasteDib(&dataObject);

    pDoc->SetModifiedFlag();

    pDoc->UpdateAllViews(NULL);

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 22.

 

void CMymfc30bView::OnUpdateEditPaste(CCmdUI* pCmdUI)

{

    // TODO: Add your command update UI handler code here

    COleDataObject dataObject;

    BOOL bAvail = dataObject.AttachClipboard() && dataObject.IsDataAvailable(CF_DIB);

    pCmdUI->Enable(bAvail);

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 23.

 

void CMymfc30bView::OnEditPastefrom()

{

    // TODO: Add your command handler code here

    CMymfc30bDoc* pDoc = GetDocument();

    CFileDialog dlg(TRUE, "bmp", "*.bmp");

    if(dlg.DoModal() != IDOK)

       return;

    if(pDoc->m_dib.AttachMapFile(dlg.GetPathName(), TRUE))

    { // share

          CClientDC dc(this);

        pDoc->m_dib.SetSystemPalette(&dc);

        pDoc->SetModifiedFlag();

        pDoc->UpdateAllViews(NULL);

    }

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 24.

 

Add the #include statement in Mymfc30bView.cpp and Mymfc30bDoc.cpp. Both files have similar headers.

 

#include "cdib.h"

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 25.

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 26.

 

Add DeleteContents() message handler to the CMymfc30bDoc class.

 

Figure 23: Adding DeleteContents() message handler to CMymfc30bDoc class.

 

Figure 23: Adding DeleteContents() message handler to CMymfc30bDoc class.

 

Then, add command and update command for ID_EDIT_CLEAR_ALL to the CMymfc30bDoc class.

 

Figure 24: Adding command and update command for ID_EDIT_CLEAR_ALL.

 

Figure 24: Adding command and update command for ID_EDIT_CLEAR_ALL.

 

Change the protected to public for the generated message map functions in mymfc30bDoc.h (or you can use friend keyword).

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 27.

 

Add the following public member variables to CMymfc30bDoc class.

 

public:

    CDib m_dib;

    BOOL m_bDragHere; // for drags between two wins linked to this doc

 

Figure 25: Adding m_dib member variable.

 

Figure 25: Adding m_dib member variable.

 

Figure 26: Adding m_bDragHere member variable.

 

Figure 26: Adding m_bDragHere member variable.

 

Add/edit the codes to the implementation file, mymfc30bDoc.cpp as shown below.

 

CMymfc30bDoc::CMymfc30bDoc()

{

    m_bDragHere = FALSE;

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 28.

 

void CMymfc30bDoc::Serialize(CArchive& ar)

{

      m_dib.Serialize(ar);

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 28.

 

void CMymfc30bDoc::DeleteContents()

{

      // TODO: Add your specialized code here and/or call the base class

      m_dib.Empty();

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 30.

 

void CMymfc30bDoc::OnEditClearAll()

{

    // TODO: Add your command handler code here

    DeleteContents();

    UpdateAllViews(NULL);

    SetModifiedFlag();

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 31.

 

void CMymfc30bDoc::OnUpdateEditClearAll(CCmdUI* pCmdUI)

{

      // TODO: Add your command update UI handler code here

      pCmdUI->Enable(m_dib.GetSizeImage() > 0);

}

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 32.

 

Finally add the following line in your StdAfx.h file for automation support.

 

#include <afxole.h>

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 33.

 

Then, add the following call at the start of the application's (mymfc30b.cpp) InitInstance() function.

 

AfxOleInit();

 

C++ code snippet - Uniform data transfer: OLE drag/drop and clipboard transfer

 

Listing 34.

 

Build and run MYMFC30B. First of all, select the Paste From menu. Select any bitmap sample, for example, under the Windows system directory (these bitmaps normally used for Windows wallpaper).

 

 

Figure 27: MYMFC30B output - testing the Paste From menu.

 

Figure 27: MYMFC30B output - testing the Paste From menu.

 

Figure 28: MYMFC30B output – displaying bitmap.

 

Figure 28: MYMFC30B output – displaying bitmap.

 

Figure 29: MYMFC30B output - testing the Clear All menu.

 

Figure 29: MYMFC30B output - testing the Clear All menu.

 

Try dragging and dropping the bitmap in the client area. Also try resizing the bitmap.

 

Figure 30: MYMFC30B - drag-and-drop functionality in the same client area.

 

Figure 30: MYMFC30B - drag-and-drop functionality in the same client area.

 

Next, display bitmap as previously done, open another window by clicking the File New menu or the New icon. Arrange the windows side-by-side for viewing convenience. Drag the bitmap from one window and drop it in another window. The following Figure shows how the bitmap has been dragged from the left window and then dropped to the right window.

 

Figure 31: MYMFC30B - drag-and-drop functionality in the different client area.

 

Figure 31: MYMFC30B - drag-and-drop functionality in the different client area.

 

Finally, launch two MYMFC30B programs. Open a sample bitmap in the first program and then drag and drop it in another MYMFC30B program as shown below.

 

Figure 32: MYMFC30B - drag-and-drop functionality in different client area and different MYMFC30B program.

 

Figure 32: MYMFC30B - drag-and-drop functionality in different client area and different MYMFC30B program.

 

The Story

 

The CMymfc30bDoc Class

 

This class is just like the MYMFC30A version except for an added flag data member, m_bDragHere. This flag is TRUE when a drag-and-drop operation is in progress for this document. The flag is in the document and not in the view because it is possible to have multiple views attached to the same document. It doesn't make sense to drag a DIB from one view to another when both views reflect the document's m_dib member.

 

The CMymfc30bView Class

 

To start with, this class has three additional data members and a constructor that initializes all the data members, as shown here:

 

CRect m_rectTrackerEnter; // original logical coordinates

COleDropTarget m_dropTarget;

CSize m_dragOffset; // device coordinates

 

CMymfc30bView::CMymfc30bView() : m_sizeTotal(800, 1050), // 8-by-10.5 inches when printed

    m_rectTracker(50, 50, 250, 250),

    m_dragOffset(0, 0),

    m_rectTrackerEnter(50, 50, 250, 250)

{

}

 

The OnInitialUpdate() function needs one additional line to register the drop target:

 

m_dropTarget.Register(this);

 

Following are the drag-and-drop virtual override functions. Note that OnDrop() replaces the DIB only if the document's m_bDragHere flag is TRUE, so if the user drops the DIB in the same window or in another window connected to the same document, nothing happens.

 

DROPEFFECT CMymfc30bView::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)

{

    TRACE("Entering CMymfc30bView::OnDragEnter, point = (%d, %d)\n",

        point.x, point.y);

    m_rectTrackerEnter = m_rectTracker; // save original coordinates

                                        // for cursor leaving rectangle

    CClientDC dc(this);

    OnPrepareDC(&dc);

    dc.DrawFocusRect(m_rectTracker);  // will be erased in OnDragOver

    return OnDragOver(pDataObject, dwKeyState, point);

}

 

DROPEFFECT CMymfc30bView::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point)

{

    if (!pDataObject->IsDataAvailable(CF_DIB))

    { return DROPEFFECT_NONE; }

    MoveTrackRect(point);

    if ((dwKeyState & MK_CONTROL) == MK_CONTROL)

    { return DROPEFFECT_COPY; }

    // Check for force move

    if ((dwKeyState & MK_ALT) == MK_ALT)

    { return DROPEFFECT_MOVE; }

    // default -- recommended action is move

    return DROPEFFECT_MOVE;

}

 

void CMymfc30bView::OnDragLeave()

{

    TRACE("Entering CMymfc30bView::OnDragLeave\n");

    CClientDC dc(this);

    OnPrepareDC(&dc);

    dc.DrawFocusRect(m_rectTracker);

    // Forget it ever happened

    m_rectTracker = m_rectTrackerEnter;

}

 

BOOL CMymfc30bView::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point)

{

    TRACE("Entering CMymfc30bView::OnDrop -- dropEffect = %d\n", dropEffect);

    BOOL bRet;

    CMymfc30bDoc* pDoc = GetDocument();

    MoveTrackRect(point);

    if (pDoc->m_bDragHere)

    {

        pDoc->m_bDragHere = FALSE;

        bRet = TRUE;

    }

    else

    { bRet = DoPasteDib(pDataObject); }

    return bRet;

}

 

The handler for the WM_LBUTTONDOWN message needs substantial overhaul. It must call DoDragDrop() if the cursor is inside the rectangle and Track() if it is on the rectangle border. The revised code is shown here:

 

void CMymfc30bView::OnLButtonDown(UINT nFlags, CPoint point)

{

    CMymfc30bDoc* pDoc = GetDocument();

    if (m_tracker.HitTest(point) == CRectTracker::hitMiddle)

    {

        COleDataSource* pSource = SaveDib();

        if (pSource)

        {

            // DoDragDrop returns only after drop is complete

            CClientDC dc(this);

            OnPrepareDC(&dc);

            CPoint topleft = m_rectTracker.TopLeft();

            dc.LPtoDP(&topleft);

            // 'point' here is not the same as the point parameter in

            //   OnDragEnter, so we use this one to compute the offset

            m_dragOffset = point - topleft;  // device coordinates

            pDoc->m_bDragHere = TRUE;

            DROPEFFECT dropEffect = pSource->DoDragDrop(

                DROPEFFECT_MOVE | DROPEFFECT_COPY, CRect(0, 0, 0, 0));

            TRACE("after DoDragDrop -- dropEffect = %ld\n", dropEffect);

            if (dropEffect == DROPEFFECT_MOVE && pDoc->m_bDragHere)

            {

                pDoc>OnEditClearAll();

            }

            pDoc->m_bDragHere = FALSE;

            delete pSource;

        }

    }

    else

    {

        if (m_tracker.Track(this, point, FALSE, NULL))

        {

            CClientDC dc(this);

            OnPrepareDC(&dc);

            // should have some way to prevent it going out of bounds

            m_rectTracker = m_tracker.m_rect;

            // update logical coordinates

            dc.DPtoLP(m_rectTracker);

        }

    }

    Invalidate();

}

 

Finally, the new MoveTrackRect() helper function, shown here, moves the tracker's focus rectangle each time the OnDragOver() function is called. This job was done by CRectTracker::Track in the MYMFC30A example.

 

void CMymfc30bView::MoveTrackRect(CPoint point)

{

    CClientDC dc(this);

    OnPrepareDC(&dc);

    dc.DrawFocusRect(m_rectTracker);

    dc.LPtoDP(m_rectTracker);

    CSize sizeTrack = m_rectTracker.Size();

    CPoint newTopleft = point - m_dragOffset;  // still device

    m_rectTracker = CRect(newTopleft, sizeTrack);

    m_tracker.m_rect = m_rectTracker;

    dc.DPtoLP(m_rectTracker);

    dc.DrawFocusRect(m_rectTracker);

}

 

Windows Applications and Drag and Drop: Dobjview

 

I tested MYMFC30B with the Microsoft Office 2003 suite. I tried both drag-and-drop and clipboard transfers, with the results shown in the following table.

 

MYMFC30B

Word

Excel

PowerPoint

FrontPage

Sends clipboard data to

x

x (no palettes)

x

x

Accepts clipboard data from

x

 

x

x

Sends drag-drop data to

x

 

x

x

Accepts drag-drop data from

x

 

 

x

 

Table 4.

 

When I started to investigate why these programs were so uncooperative, I discovered a useful OLE utility called Dobjview (DataObject viewer).

 

Figure 33: Invoking DataObject Viewer.

 

Figure 33: Invoking DataObject Viewer.

 

I could use Dobjview to examine a data object on the clipboard, and I could drag objects to the Dobjview window. Here's what I got when I dragged a picture from Microsoft Excel.

 

Figure 34: Testing MYMFC30B’s drag and drop functionality among Microsoft Office applications.

 

Figure 34: Testing MYMFC30B’s drag and drop functionality among Microsoft Office applications.

 

No CF_DIB format is present. If you want pictures from Excel, you must enhance MYMFC30B to process metafiles. Another alternative is to rewrite the program with compound document support as described in Module 27. The OLE libraries contain code to display bitmaps and metafiles.

 

Conclusion

 

As you can see, MFC makes clipboard and drag-and-drop data transfer pretty easy. While you can always write all the code necessary to implement the interfaces (IDataObject, IDropTarget, and IDropSource), using MFC's implementations is much more convenient. While we've looked only at clipboard and drag and drop transfers through IDataObject in this Module, everything you learn about the IDataObject interface will carry forward to your study of compound documents in the next Module.

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

  1. DCOM at MSDN.

  2. COM+ at MSDN.

  3. COM at MSDN.

  4. Win32 process, thread and synchronization story can be found starting from Module R.

  5. MSDN MFC 7.0 class library online documentation.

  6. MSDN MFC 9.0 class library online documentation - latest version.

  7. MSDN Library

  8. Windows data type.

  9. Win32 programming Tutorial.

  10. The best of C/C++, MFC, Windows and other related books.

  11. Unicode and Multibyte character set: Story and program examples.

 

 


 

| Tenouk C & C++ | MFC Home | Uniform Data Transfer & OLE 4 | Structured Storage 1 | Download | Site Index |