Community Pick: Many members of our community have endorsed this article.
Editor's Choice: This article has been selected by our editors as an exceptional contribution.

How to Accept Drag-and-Drop URLs From a Web Browser

DanRollins
CERTIFIED EXPERT
Published:
If you have a program that accepts user-entered input of a URL, you really should give your user the ability to drag a hyperlink from a browser into your program.  Sure, the user can right-click and select "Copy Link Location" (FireFox) or "Copy Shortcut" (IE), but a well-written program does everything possible to save steps for the user.

It is very convenient to drag a URL and drop it.  Many programs can act as a drop-target for hyperlinks displayed in a web browser.  You can drag a hyperlink and drop it on the Windows Desktop, or onto another browser window, or into an edit box in another browser window, or on into a Word or Wordpad document... and the URL represented by that hyperlink is used or displayed.

This article describes how to make that happen in your own programs.
Drag From IE or FirefoxIn a previous article, we saw how to handle files dragged from Windows Explorer.  Although there is no "simple" version (as there is with file drops), the process for accepting dropped URLs uses a technique also described in that article.  

In brief, you create a COleDropTarget-derived object with a little bit of specialization.  You call the Register() function of that object, identifying, say, an edit box as the window that will accept the drops.
 
In the following example, we'll assume that you have a dialog box (or other window) containing a standard edit control, named m_ctlEdURL.
// file: MyEdDropTarget.h
                      //
                      class CMyEdDropTarget : public COleDropTarget
                      {
                      public:
                          CMyEdDropTarget::CMyEdDropTarget() { // CTOR
                              OleInitialize(0);
                              m_CF_URLA= RegisterClipboardFormat( _TEXT("UniformResourceLocator") );
                              m_CF_URLW= RegisterClipboardFormat( _TEXT("UniformResourceLocatorW") );
                          }
                          virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject,
                                      DWORD dwKeyState, CPoint point) 
                          {
                              STGMEDIUM rSM;
                              BOOL fRet= pDataObject->GetData( m_CF_URLA, &rSM ); 
                              if ( fRet ) {
                                  return( DROPEFFECT_LINK ); // "Drop OK"
                              }
                              return( DROPEFFECT_NONE ); //else, show the "Don't Drop" cursor
                          };
                          virtual BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject,
                                      DROPEFFECT dropEffect, CPoint point) 
                          {
                              STGMEDIUM rSM;
                              BOOL fRet= pDataObject->GetData( m_CF_URLA, &rSM ); 
                      
                              char* p= (char*)GlobalLock(rSM.hGlobal); 
                              CStringW sw( p );    // convert to UNICODE 
                              GlobalUnlock( rSM.hGlobal );
                      
                              CEdit* pEd= (CEdit*)pWnd;
                              pEd->SetSel(0,-1);
                              pEd->ReplaceSel( sw );
                      
                              return( 1 ); // success
                          };
                          UINT m_CF_URLA;
                          UINT m_CF_URLW;
                      };

Open in new window

Just #include that header at the top of your dialog code.  Now use the following code in your OnInitDialog() function:
CMyEdDropTarget gcMyEdDropTarget;  // make a global instance
                      
                      BOOL MyDlg::OnInitDialog()
                      {
                      ...
                      	BOOL fRet= gcMyEdDropTarget.Register( &m_ctlEdURL );
                      	return TRUE; 
                      }

Open in new window

That's all there is to it!  

Notes:
Both Internet Explorer and FireFox register the same two clipboard formats:
    "UniformResourceLocator"      (ANSI -- 8-bit characters)
    "UniformResourceLocatorW"   (UNICODE -- 16-bit characters)
...so the example code can accept drops from either browser.  I'd be surprised if other browsers don't follow the same convention, but I did not test them.
The CMyEdDropTarget obtains the clipboard format code for both the ANSI and UNICODE formats, but it only uses the ANSI (8-bit) version.
In line 28 of the MyEdDropTarget.h example, note the simple answer to a common question here at EE:  "How do I convert from ANSI to UNICODE?"  The program simply creates a CStringW (UNICODE) variable, assigning its initial value from a pointer to 8-bit text.
In addition to dragging a hyperlink from a browser, you can also drag the URL from the browser's Address Bar.  The trick is to click on and drag the icon that is just to the left of the URL text.

References:
How to Accept Drag-and-Drop Files from Windows Explorer

Handling Shell Data Transfer Scenarios
http://msdn.microsoft.com/en-gb/library/bb776904(VS.85).aspx

COleDropTarget Class (MFC)
http://msdn.microsoft.com/en-us/library/4w4z9dwh.aspx

Shell Clipboard Formats
http://msdn.microsoft.com/en-us/library/bb776902(VS.85).aspx

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
If you liked this article and want to see more from this author,  please click the Yes button near the:
      Was this article helpful?
label that is just below and to the right of this text.   Thanks!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=  
0
7,210 Views
DanRollins
CERTIFIED EXPERT

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.