Drag, drop, cut, copy and paste operations on lists of files using MFC
Posted by KAKA | Posted in | Posted on 7:54 AM
Introduction
In the given article practically all operations on moving group of files from one application to another are described. I have considered both reception of files by the given application and transfer of files from the given application in other programs. In the article the operations drag and drop, cut, copy, paste are described. The technique is shown using the demonstration project.
Developing the program Mp3 Music Explorer I have confronted the fact that in the documentation from Microsoft, and also on the known sites devoted to development of the software there is no example, in which all necessary operations on moving files would be presented. Therefore I have created the demonstration project FilesDragDrop. It is based on the MFC SDI project. For the files display the class CListView
is used.
Receiving the Drop of the list of files in the application is possible by two ways: using the message WM_DROPFILES
and using the OLE mechanism. Both ways, as well as transfer of a file through Clip Board, use one structure of file description DROPFILES
. For dragging of a file from the application only the mechanism Ole is used. Therefore all operations of moving files I implemented using the OLE technology.
Initialization
The realization of moving of files is possible without such concepts as OLE Server and OLE Client. They are excessive for this task. It is possible to use the usual MFC project. But for the necessary OLE classes to work we need to initialize OLE library. For this purpose the following lines are inserted into the function CFilesDragDropApp:: InitInstance ()
:
// Initialize OLE 2.0 libraries
if (!AfxOleInit())
{
AfxMessageBox("AfxOleInit Error!");
return FALSE;
}
Receiving the files in the application
For receiving files using Drag&Drop technology I used OnDragOver
and OnDrop
notifications. In the OnDragOver
function I determine if the list of files or something else is carried above a window and I return assumed result of the operation. If it is not the files - the returned value is DROPEFFECT_NONE
. It allows the system to establish the correct cursor of the mouse. In the OnDrop
function the extraction of files and the clearing of the buffer are made. For these functions to work the window should be registered as handler of the operation Drag&Drop. For the registration the object such as COleDropTarget
is used as follows:
void CFilesDragDropView::OnInitialUpdate()
{
...
VERIFY( m_DropTarget.Register(this) );
...
}
Clip Board and Drag&Drop use the same structure for data transfer. In processing the messages OnPaste
and OnDrop
there is an extraction of the list of files from the object COleDataObject
:
void CFilesDragDropView::OnEditPaste()
{
COleDataObject DataObject;
if( DataObject.AttachClipboard() )
{
DataObjectToList(&DataObject);
}
}
BOOL CFilesDragDropView::OnDrop(COleDataObject* pDataObject,
DROPEFFECT dropEffect, CPoint point)
{
BOOL bRet = DataObjectToList(pDataObject);
...
}
Data type, used for transferring the files is CF_HDROP
. The data are passed through the global memory, its handle it is possible to take from COleDataObject
using GetData
function. The amount of transferred files and paths to them can be received with the help of handle using function DragQueryFile
( CFilesDragDropView:: FileNamesToList
). The received files are displayed in a ListView
window.
Transfer of files from the application
To transfer files from the application using Copy/Paste and Drag&Drop technologies it is necessary to create structure DROPFILES
. This structure corresponds to a data type CF_HDROP
of the exchange buffer. The paths to files in the structure are separated from each other by symbol '\0 ', the end of the list of files is marked by two symbols '\0 '. There is a standard function of path extraction from the buffer - DragQueryFile
, but there is no standard function for creating a buffer. For this purpose I have designed a class CDropFiles
. The class is used in the following way:
- First function
AddFile
enters all the paths of transferred files - Then the function
CreateBuffer
creates a necessary data structure. For access to the structure the functionsGetBuffer
andGetBuffSize
are used. When using Copy or Cut command, the data generated inCDropFile:: m_pBuff
are entered in the exchange buffer between the applications by functionSetClipboardData
.
In Drag&Drop technology for the transfer of files from the application the function OnBeginDrag
is used. It is called by the message LVN_BEGINDRAG
of CListCtrl
class. If we use a window, which does not generate the similar message, it is possible to use the message WM_LBUTTONDOWN
. The data for the transfer are entered in object COleDataSource
by the function CacheGlobalData
, the data transfer is carried out by DoDragDrop
function. For the object COleDataSource
to work it is necessary to create COleDropSource
object. This object is not used in any way in transfer. All necessary actions it carries out in the constructor. Memory of the exchange buffer is emptied by the receiving party.
The text of function
void CFilesDragDropView::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
CDropFiles DropFiles; // My class for creating DROPFILES struct
if(!PrepareFileBuff(DropFiles))
{
ASSERT(0);
}
COleDropSource DropSource;
COleDataSource DropData;
HGLOBAL hMem = ::GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE|GMEM_DDESHARE,
DropFiles.GetBuffSize());
memcpy( (char*)::GlobalLock(hMem), DropFiles.GetBuffer(),
DropFiles.GetBuffSize() );
::GlobalUnlock(hMem);
DropData.CacheGlobalData( CF_HDROP, hMem );
DROPEFFECT de = DropData.DoDragDrop(DROPEFFECT_COPY|DROPEFFECT_MOVE,NULL);
if(de == DROPEFFECT_COPY)
{
// Copy files if CTRL btn is hold;
}
else
{
// Move files, as default;
DeleteSelectedFiles();
}
*pResult = 0;
}
Testing of the demonstration project
If you transfer files from any catalogue to the FilesDragDrop application, and then from the application to another catalogue, the files will be really transferred. That's why when testing I recommend to use the special temporary catalogues to avoid the transfer of necessary files.
Links
- http://www.brigsoft.com/mp3explorer - the technology described in the given article, was applied in a product Mp3 Music Explorer.
- http://www.brigsoft.com/edu/FilesDragDrop/FilesDragDrop_demo.zip- demo project (VC++ v.6)
- http://www.brigsoft.com/edu - other author's articles and sources.
Comments (0)
Post a Comment