Introduction
Would like to drag n drop an Outlook attachment to a tree view and got stuck? Don't worry, I am here to help you.
When I came across this requirement, I searched the web and I found something which helped me a lot in developing my project, albeit with modifications. You can see the original code here: http://www.codeguru.com/cpp/i-n/internet/email/article.php/c3381/.
This link is pretty old and provides sample code, but for VB, not for MFC and using the VC6 compiler. One of the things which That I did not like was that it used COM. Here, I am using the MFC advanced OLE drag and drop mechanism which wraps the COM and provides a very simple mechanism for development.
The Outlook Clipboard format is not a standard one. It registers its private formats called CFSTR_FILECONTENTS
and CFSTR_FILEDESCRIPTORA
. Also remember that it does not register a Unicode version CFSTR_FILEDESCRIPTORW
, and hence, even though my sample code will build on non-Unicode as well as Unicode, in the Unicode build, some Unicode characters may get lost when in use.
The first thing you start with is implementing the OnCreate()
function of the treeview class and registering the window and the private clipboard format.
int CDragnDropView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CTreeView::OnCreate(lpCreateStruct) == -1)
return -1;
cp_format_contents = ::RegisterClipboardFormat(CFSTR_FILECONTENTS);
cp_format_descriptor = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA);
m_oleDropTarget.Register (this);
return 0;
}
The next step is to override the OnDragEnter()
, OndragOver()
, OnDrop()
, and OnDragLeave()
functions.
In the OnDragEnter()
and OnDragOver()
functions, you just filter out when to enable the drag and drop and when to disable it. The core functionality is put inside the OnDrop()
function. If you start a drag and drop operation, but would not drop it on to the tree view or just presses Escape, the OnDragLeave()
function will be called instead of OnDrop()
, and this is the place where you should write the cleanup code, e.g., memory deletion etc.
In my sample project, I have a root node called Javed
which points to nowhere, but it has two child nodes, Node1
and Node2
, which point to D:\Javed\Node1 and D:\Javed\Node2, respectively. When you drop an Outlook attachment on to one of these nodes, it will be dropped to the respective node. You need to have these folders in your system; otherwise you need to change the path of the node in the OnDrop()
function.
void CDragnDropView::OnDrop()>
{
if (bStatus)
{
CString strFile_name,strLocation;
CString strTargetNode = GetTreeCtrl().GetItemText(m_htTargetNode);
if(!strTargetNode.CompareNoCase(_T("Node1")))
strLocation = _T("D:\\Javed\\Node1\\");
if(!strTargetNode.CompareNoCase(_T("Node2")))
strLocation = _T("D:\\Javed\\Node2\\");
strFile_name = file_descriptor.cFileName;
strFile_name = strLocation + strFile_name;
hr = StreamToFile(storage.pstm, strFile_name);
}
}
Now you can download the sample project and get a deeper look into the code.
Points of Interest
Any feedback on this is appreciated.