Drag and Drop

Win32 subsystem facilitates files and object transfer between two applications using drag and drop. Drag and drop is a mouse operation. User clicks on some file(s) in file explorer or some OLE object in application like Word and moves mouse cursor to other application window with out realising left mouse button. This operation is called drag. Now releaseing left mouse button in the other application window is called drop operation. When drag and drop operations are made in conjunction, a drag-n-drop operation happens. This creates a visual effect and object seems moves between two windows and mouse cursor changes. An application should prepare its window to accept drop operations.

There are Win32 APIs to enble this operation and Windows sends event when drop operation is performed. drag-n-drop is mainly with two types -

  1. file/folder drag and drom from windows exploler or other file manager applications.
  2. OLE objects like simple text, rich edit text, html, bitmaps, pictures etc drag and drop from other aplications.

We are discussing file drag and drop events here. Before going the the demo aplication we should know the Win32 APIs and Windows attributes related to drag and drop.

WS_EX_ACCEPTFILES

WS_EX_ACCEPTFILES is the extended windows style to pass the parameter in CreateWindowEx() to give the capability of accepting dropped files from windows explorer or file manager applications. An active and visible window receives the file drop event (WM_DROPFILES) when this extended style is applied.

Accept files

Extended Window/Dialog style Accept files

While create a dialog in resource editor, WS_EX_ACCEPTFILES can be applied by selecting "Accept files" checkbox.

DragAcceptFiles

Registers whether a window accepts dropped files nor not. DragAcceptFiles function call changes windows style/capability of WS_EX_ACCEPTFILES at runtime.

VOID DragAcceptFiles(
   HWND hWnd,
   BOOL fAccept
);
Parameters hWnd - Handle to the window fAccept- TRUE to accept dropped files or FALSE to discontinue accepting dropped files. Return value No return value. Remarks DragAcceptFiles() can be called with FALSE to disable file drop operation.

WM_DROPFILES

Window receives this event during drag-n-drop operation. Windows with WS_EX_ACCEPTFILES can only receives this event. Windows explorer and file manager applications are sender and our demo application is the receiver part of this message. File manager application detects the mouse drag even and calls PostMessage() with message id WM_DROPFILES and one or more file path information as a handle in wParam papameter.

PostMessage(
    (HWND) hWndControl,   // handle to destination control
    (UINT) WM_DROPFILES,  // message ID
    (WPARAM) wParam,      // = (WPARAM) (HDROP) hDrop;
    (LPARAM) lParam       // = 0; not used, must be zero 
);

Parameters

hWndControl - Handle to the target control msgID - WM_DROPFILES hDrop - A handle to an internal structure describing the dropped files. Pass this handle DragFinish, DragQueryFile, or DragQueryPoint to retrieve information about the dropped files. lParam - ust be zero.

Return value

An application should return zero if it processes this message.

Remarks

The HDROP handle is declared in Shellapi.h. You must include this header in your build to use WM_DROPFILES. For further discussion of how to use drag-and-drop to transfer Shell data, see Transferring Shell Dat

DragQueryFile function

Retrieves the names of dropped files that result from a successful drag-and-drop operation.

UINT DragQueryFile(
  HDROP  hDrop,
  UINT   iFile,
  LPTSTR lpszFile,
  UINT   cch
);

Parameters

  • hDrop - Handle of the structure that contains the file names of the dropped files.
  • iFile - Index of the file to query. If the value of this parameter is 0xFFFFFFFF, DragQueryFile returns a count of the files dropped. If the value of this parameter is between zero and the total number of files dropped, DragQueryFile copies the file name with the corresponding value to the buffer pointed to by the lpszFile parameter.
  • lpszFile- The address of a buffer that receives the file name of a dropped file when the function returns. This file name is a null-terminated string.
  • If this parameter is NULL, DragQueryFile returns the required size, in characters, of this buffer.
  • cch - The size of the lpszFile buffer.

Return value

A nonzero value indicates a successful call.

  • Returns number of dropped files - Pass iFile as 0xFFFFFFFF to know how many files are dropped to this window.
  • Returns length of the file path - Pass lpszFile as NULL to index as iFile to know the size of the buffer needed.
  • Returns file path string in lpszFile - Pass iFile index between 0 to count -1 and lpszFile as a pointer to a buffer and cch as the length of the buffer.

DragFinish function

Releases memory that the system allocated for use in transferring file names to the application.

VOID DragFinish(
   HDROP hDrop
);

Parameters

  • hDrop- Handle that describes dropped files. This handle is retrieved from the wParam parameter of the WM_DROPFILES message.
class CDragNDropDlg : public CDialog
{

public:
  CDragNDropDlg(CWnd* pParent = NULL);  /* standard constructor */

  enum { IDD = IDD_DRAGNDROP_DIALOG };
  CListBox  m_List;

  protected:
  virtual void DoDataExchange(CDataExchange* pDX);

protected:

  virtual BOOL OnInitDialog();

  /* Event handler for ON_WM_DROPFILES */
  afx_msg void OnDropFiles(HDROP hDropInfo);

  DECLARE_MESSAGE_MAP()
};
BEGIN_MESSAGE_MAP(CDragNDropDlg, CDialog)
  ON_WM_DROPFILES()
END_MESSAGE_MAP()

  
BOOL CDragNDropDlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  /* Enable Window to accept drop files */
  DragAcceptFiles(TRUE);

  return TRUE;
}

void CDragNDropDlg::DoDataExchange(CDataExchange* pDX)
{
  CDialog::DoDataExchange(pDX);
  DDX_Control(pDX, IDC_LIST1, m_List);
}
/* MFC Event handler for ON_WM_DROPFILES */
void CDialogsDlg::OnDropFiles(HDROP hDropInfo)
{
  TCHAR buffer[MAX_PATH + 1];
  /* Get the number of files dropped */
  UINT nCount = ::DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
  m_List.ResetContent();
  for (UINT index = 0; index < nCount; index++)
  {
    /* Get the path of file #n */
    ::DragQueryFile(hDropInfo, index, buffer, MAX_PATH + 1);
    /* Add the string in list box */
    m_List.AddString(buffer);
  }
  CDialog::OnDropFiles(hDropInfo);
  /* Free buffer and close handle */
  ::DragFinish(hDropInfo);
}

Program output

During drag from windows explorer

Files dragged from Windows explorer

After files are dropped to dialog

List of files after drop

About our authors: Team EQA

Further readings

Where is WinMain() function in MFC application ?

MFC hides WinMain in its framework and includes source file on WinMain(). This explains how framework calls global CWinApp::Initinstance() from entry WinMain.

What is the utility of CWinApp class?

This is constructed during global C++ objects are constructed and is already available when Windows calls the WinMain function, which is supplied by the ...

Basic steps in Win32 GUI Application with source code.

Define a custom Window class structure, Register the class name, CreateWindow, Show windows and write message get and dispatch loop statements. Define the Window CallBack procedure and write the handlers.

What is a Window CallBack procedure and what is its utility?

DispatchMessage() is a API which indirectly triggers the Window CallBack procedure. Message structure members from this function are passed to the CallBack procedure. CallBack procedure should implement event handlers depending on the need of the application.

What are LPARAM and WPARAM in window proc function?

LPARAM and WPARAM are the two parameters in Window CallBack procedure. They signifies parameters of various events. They are used in handing individual events.

What are the basic steps of a typical MFC based application?

We need to write WinMain and need to follow all these in a Win32 application. However we need not to write much if we are writing an application with MFC ...

#