Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# WinForms: Identify type of drag-drop action event

The use case: users need the ability to drag & drop email items from Outlook onto a form in my WinForms (.Net 4) application. The application saves these items in .msg format and stores them in a predetermined location.

The problem: my code is not robust against drag-drop from other sources (e.g. dragging a jpeg from IE onto the form triggers the same event). This is because I cannot determine whether the dragged item is an Outlook object, or what source the dragged item(s) came from.

Is there a workaround such that I can only accept drag-drop items of a particular type? Here is my code in the DragDrop event handler:

Outlook.Application outlook = new Outlook.Application();
Outlook.Selection sel = outlook.ActiveExplorer().Selection;

try
{    
    foreach (object item in sel)
    {
        if (item is Outlook.MailItem)
        {
            var mail = item as Outlook.MailItem;

            CopyMailItemToLocalTempDir(mail);

            txtComment.Text = "Email from " + mail.SenderName + " Regarding " + mail.Subject;
        }
    }
}
finally
{
    // This is hokey but it prevents Outlook from remembering previously selected items
    // - refer http://stackoverflow.com/questions/14090420/interop-outlook-doesnt-clear-selected-mails-at-drag-and-drop
    var folder = outlook.ActiveExplorer().CurrentFolder;
    outlook.ActiveExplorer().CurrentFolder = outlook.GetNamespace("MAPI").GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
    Thread.Sleep(50);
    outlook.ActiveExplorer().CurrentFolder = folder;

    Marshal.ReleaseComObject(sel);
    Marshal.ReleaseComObject(outlook);
    sel = null;
    outlook = null;
}

Some details on the DragEventArgs object (e) when dragging from Outlook:

e.Data.GetFormats() returns: 
{string[15]}
    [0]: "RenPrivateSourceFolder"
    [1]: "RenPrivateLatestMessages"
    [2]: "RenPrivateMessages"
    [3]: "RenPrivateItem"
    [4]: "FileGroupDescriptor"
    [5]: "FileGroupDescriptorW"
    [6]: "FileDrop"
    [7]: "FileNameW"
    [8]: "FileName"
    [9]: "FileContents"
    [10]: "Object Descriptor"
    [11]: "System.String"
    [12]: "UnicodeText"
    [13]: "Text"
    [14]: "CSV"

e.Data.GetData("Text") returns: 
"From\tSubject\tReceived\tSize\tCategories\t\r\nJoe Sender\tThis is the email subject\t10:51 AM\t3 KB\t\t"
like image 408
Vishal Bardoloi Avatar asked Jul 03 '13 16:07

Vishal Bardoloi


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.

What is C and C++ meaning?

C is a function driven language because C is a procedural programming language. C++ is an object driven language because it is an object oriented programming. Function and operator overloading is not supported in C. Function and operator overloading is supported by C++. C is a function-driven language.


2 Answers

i have here the source code of solution that allow to drop only outlook items. here are the event handlers:

private void Form1_DragEnter(object sender, DragEventArgs e)
    {
        //display formats available
        this.label1.Text = "Formats:\n";
        foreach (string format in e.Data.GetFormats())
        {
            this.label1.Text += "    " + format + "\n";
        }

        //ensure FileGroupDescriptor is present before allowing drop
        if (e.Data.GetDataPresent("FileGroupDescriptor"))
        {
            e.Effect = DragDropEffects.All;
        }
    }

    private void Form1_DragDrop(object sender, DragEventArgs e)
    {
        //wrap standard IDataObject in OutlookDataObject
        OutlookDataObject dataObject = new OutlookDataObject(e.Data);

        //get the names and data streams of the files dropped
        string[] filenames = (string[])dataObject.GetData("FileGroupDescriptorW");
        MemoryStream[] filestreams = (MemoryStream[])dataObject.GetData("FileContents");

        this.label1.Text += "Files:\n";
        for (int fileIndex = 0; fileIndex < filenames.Length; fileIndex++)
        {
            //use the fileindex to get the name and data stream
            string filename = filenames[fileIndex];
            MemoryStream filestream = filestreams[fileIndex];
            this.label1.Text += "    " + filename + "\n";

            //save the file stream using its name to the application path
            FileStream outputStream = File.Create(filename);
            filestream.WriteTo(outputStream);
            outputStream.Close();
        }
    }
like image 62
No Idea For Name Avatar answered Oct 04 '22 00:10

No Idea For Name


Is there a workaround such that I can only accept drag-drop items of a particular type?

Yes, there is 2 way

(When working with single files):

if (e.Data.GetData(typeof(...)) is ...)
    //process it

and

if (e.Data.GetDataPresent(typeof(...)))
    //process it

About robustness

Since you have not specified the type to be Outlook.MailItem (or maybe Image) but the source: I assume your program fails on other parts of the code (due to bad design). E.g. ActiveExplorer().Selection in 2nd line or in the finally {} part. This is easily manageable by prefiltering/try-catching in place (before involving outlook) or in the DragEnter event (better when the type is strictly some type of outlook).

To master drag & drop stuff, check out this.

For multiple file handling

or for special types like outlook messages, you already have a good solution with plenty of explanations in the article you mentioned.

I also found an answer to your non-general (outlook only) use case (wrote in 2012) that exhibits OutlookDataObject class and probably based on the article you mentioned (wrote in 2008).

like image 35
Alb Avatar answered Oct 04 '22 01:10

Alb