当前位置: 首页 > 知识库问答 >
问题:

C#WinForms:识别拖放操作事件的类型

左丘修齐
2023-03-14

用例:用户需要能够拖动

问题是:我的代码不能抵抗来自其他来源的拖放(例如,将jpeg从IE拖到表单上会触发相同的事件)。这是因为我无法确定拖动的项目是否是Outlook对象,或者拖动的项目来自哪个源。

是否有一种变通方法,使我只能接受特定类型的拖放项?以下是我在DragDrop事件处理程序中的代码:

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;
}

从Outlook拖动时DragEventArgs对象(e)的一些详细信息:

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"

共有2个答案

唐健
2023-03-14

是否有解决方法使我只能接受特定类型的拖放项目?

(使用单个文件时):

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

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

因为您尚未将类型指定为Outlook。MailItem(或者可能是图像),但来源:我假设您的程序在代码的其他部分失败(由于糟糕的设计)。E、 g.ActiveExplorer()。在第二行或最后{}部分中选择。通过预过滤/尝试捕捉到位(在涉及outlook之前)或在DragEnter事件中(当类型严格为某种outlook时更好),这很容易管理。

要掌握阻力

或者对于像outlook消息这样的特殊类型,你已经有了一个很好的解决方案,在你提到的文章中有很多解释。

我还找到了您的非通用(仅限outlook)用例(写在2012年)的答案,该用例展示了OutlookDataObject类,可能基于您提到的文章(写在2008年)。

吕宸
2023-03-14

我这里有解决方案的源代码,只允许删除outlook项目。以下是事件处理程序:

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();
        }
    }
 类似资料:
  • 拖放(Drag’n’Drop)是一个很赞的界面解决方案。取某件东西并将其拖放是执行许多东西的一种简单明了的方式,从复制和移动文档(如在文件管理器中)到订购(将物品放入购物车)。 在现代 HTML 标准中有一个 关于拖放的部分,其中包含了例如 dragstart 和 dragend 等特殊事件。 这些事件使我们能够支持特殊类型的拖放,例如处理从 OS 文件管理器中拖动文件,并将其拖放到浏览器窗口中。

  • 问题内容: 我想通过覆盖JLabel上的鼠标事件来启用JLabel上的拖放功能,但是当我在mousePressed事件中定义拖放时,mouseReleased对该JLabel无效。难道我做错了什么 ? 缩略图是JLabel的数组 运行该程序时,拖放有效,但不会打印“此处释放鼠标”语句。但是,当我从mousePressed()方法中删除负责DND的代码时,将打印“此处释放了鼠标”。 这段代码有什么问

  • 我想将事件附加到元素以处理文件拖放事件,但似乎此事件也附加到所有子元素。例如 ...如果我将文件拖到属于元素的任何元素上,控制台将输出。因此,如果我将此事件附加到或,则当悬停在页面上的任何元素上时,事件将触发。 对于<code>dragleave 为什么会这样?有没有办法把这个事件只附加到指定的元素上?如果没有,有没有办法将事件从所有子元素中分离出来? 这里有一个摆弄的例子:http://jsfi

  • 问题内容: 有谁知道是否有一种方法来获取具有ErrorProvider图标处于活动状态的控件的列表。即。验证失败的任何控件。我试图避免循环窗体中的所有控件。 我想显示某种消息,指示表单上有多少错误。由于我的表单包含选项卡,因此我试图使用户知道不活动的选项卡上可能存在错误,因此他们需要检查所有选项卡。 谢谢 巴里 问题答案: 这属于“你怎么 不 知道” 类别。是您的代码正在调用ErrorProvid

  • 我有以下疑问: 问题是使用。就地查询返回错误: 下面是db fiddle,它表明了这个问题: https://www.db-fiddle.com/f/vUBjUyKDUNLWzySHKCKcXA/1 我怎样才能解决这个问题?

  • 本文向大家介绍winforms 处理Form的HelpButtonClicked事件,包括了winforms 处理Form的HelpButtonClicked事件的使用技巧和注意事项,需要的朋友参考一下 示例 您可以HelpButton通过处理来检测用户何时单击表单的标题栏HelpButtonClicked。您可以通过将Cancel事件args的属性设置为来让事件继续或取消true。