Lately, I was requested to enable an application to receive a drop event of an Outlook message. Of course the base of the operation is exactly the same but the message from Outlook is in a special proprietary format.
First look at my toolset
When I first had the request, I queried Google for it to discover that one of the tools I often use (Aspose.Network) offered something to help me. A first quick test showed me that I was able to handle the drop operation of an Outlook message correctly but when we were ready to implement it into the real solution which is using an Infragistics UltraTree we discovered that both products are not really compatible with each other. Infragistics has its own set of events that are not supported by Aspose. So I went to Google again...
Another false-positive result
My Google session quickly brought me to a Code Project article titled “Drag-and-Drop Attached File From Outlook (97 and above) to C# Window Form” from Tom Gueth that was very promising. So I downloaded it and give it a try to discover that it wasn’t working for what I needed. It allows you to drag an attachment from an email to your form but not the whole email as I needed. One of the comments at the bottom of this article led me to the solution I am showing here.
So what is working for me?
I was looking for a solution that doesn’t require me to instantiate Outlook as we all know that it can lead us into problems when deploying to a large set of users. But didn’t find anything working well with the constraints I had.
So I have added a reference to “Microsoft.Office.Interop.Outlook” component like shown in figure 1.
Figure 1: Adding a reference to Outlook
Then I built my very complex demo GUI like shown in figure 2. The GUI only contains 3 labels (named Label1, lblFormat, and lblFile in top-to-bottom order). The BorderStyle of the 3 controls has been set to FixedSingle, and the AutoSize property set to False. The AllowDrop property of the top-most label control has been set to True because this one will be used as the drop target.
Figure 2: the GUI of the demo application
Then I was ready to start writing code. I started by declaring a class level instance of Outlook like this:
Dim objOL As New Microsoft.Office.Interop.Outlook.Application
Then I have added code to the DragOver event of the Label1 control (the top-most one) to provide feedback when users are dragging a file (from Windows Explorer) or a mail message (from Outlook) over it:
If e.Data.GetDataPresent(DataFormats.FileDrop) Then 'handle a file dragged from Windows explorer e.Effect = DragDropEffects.Copy lblFormat.Text = "DragOver ... File drop" ElseIf e.Data.GetDataPresent("FileGroupDescriptor") Then 'handle a message dragged from Outlook e.Effect = DragDropEffects.Copy lblFormat.Text = "DragOver ... Outlook" Else 'otherwise, do not handle e.Effect = DragDropEffects.None lblFormat.Text = "" End If
Then I have added this code to the DragLeave event of the Label1 control to empty the format label control:
lblFormat.Text = String.Empty
If e.Data.GetDataPresent(DataFormats.FileDrop) Then 'supports a drop of a file from Windows Explorer ' copy the name of the dragged files into a string array Dim draggedFiles As String() = CType(e.Data.GetData(DataFormats.FileDrop), String()) 'handle each file passed as needed For Each fileName As String In draggedFiles 'hardcode a destination path for testing Dim strDestinationFile As String = _ IO.Path.Combine("c:\temp", _ IO.Path.GetFileName(fileName)) 'test if source and destination are the same If strDestinationFile.Trim.ToUpper = fileName.Trim.ToUpper Then lblFile.Text += strDestinationFile + _ " - Source and Destination are the same!!!" + _ Environment.NewLine Else lblFile.Text += "Copying - " + _ strDestinationFile + Environment.NewLine IO.File.Copy(fileName, strDestinationFile) End If Next ElseIf e.Data.GetDataPresent("FileGroupDescriptor") Then 'supports a drop of a Outlook message 'Dim objMI As Object - if you want to do late-binding Dim objMI As Microsoft.Office.Interop.Outlook.MailItem For Each objMI In objOL.ActiveExplorer.Selection() 'hardcode a destination path for testing Dim strFile As String = _ IO.Path.Combine("c:\temp", _ (objMI.Subject + ".msg").Replace(":", "")) lblFile.Text += strFile + Environment.NewLine objMI.SaveAs(strFile) Next End If lblFormat.Text = String.Empty
For Each objMI In objOL.ActiveExplorer.Selection()
Going late-bound
If you don’t like the idea of referencing Outlook (because you are not sure what version of Outlook people are using), it is possible to use late-binding and still have the same result at runtime. Many programmers are using early-binding while developing to have access to the Intelli-Sense but go late-bound before building a release version.
To achieve it, you need to:
Conclusion
This article shows how to support file drop from Windows Explorer as well as an email message drop from Outlook. I would have preferred a solution without relying on Outlook but it seems to be much more complex. After all, if people are dropping a message from Outlook that means that it should be installed!