Как программно получить имя файла при перетаскивании из .Net Solution Explorer? - PullRequest
2 голосов
/ 03 апреля 2019

Я хочу написать приложение, которое создает zip-файлы путем прямого перетаскивания файлов из обозревателя решений Visual Studio в мое приложение.

Я использовал следующий фрагмент кода для перехвата входящего объекта DataObject:

private void lblIncludedFiles_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        e.Effect = DragDropEffects.Copy;
    }
}

Я перепробовал все возможные значения DataFormats, все они возвращают false.

Ответы [ 2 ]

2 голосов
/ 03 апреля 2019

Поскольку эта задача может быть несколько менее простой, чем на бумаге, здесь приведен пример процедуры, которая должна позволить получить список файлов, перетаскиваемых из панели обозревателя решений Visual Studio.

DataFormats, которые генерирует Visual Studio, являются частыми (UnicodeText и Text), но фактический список файлов передается в (классический) объект MemoryStream, который не является общим DataFormat: CF_VSSTGPROJECTITEMS.

MemoryStream содержит текст Unicode - фактический список отбрасываемых кортежей Project + File Name, разделенных символом канала (|) - и некоторые другие двоичные разделы, которые я не считаю полезными для описания Вот.

Другой не распространенный / предопределенный формат, VX Clipboard Descriptor Format, также является объектом MemoryStream, но это просто строка Unicode, которая содержит имя проекта.


В этом примере объединенные элементы, являющиеся частью Drop, организованы с использованием пользовательского объекта класса, который содержит информацию о:

  • название и UUID проекта (ов), откуда поступают файлы,
  • Путь проекта и путь к файлу (.[xxx]prj),
  • имя объекта, запустившего операцию перетаскивания,
  • список всех удаленных файлов, проекта, частью которого они являются, и их необработанный тип (.cs, .vb, .h, .png и т. Д.)

Выберите элемент управления, который получит Drop, и добавьте обработчики:

private void ctlVSDrop_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetFormats().Contains("CF_VSSTGPROJECTITEMS"))
    {
        e.Effect = DragDropEffects.Copy;
    }
}

private void ctlVSDrop_DragDrop(object sender, DragEventArgs e)
{
    VisualStudioDataObject vsObject = new VisualStudioDataObject(e.Data);
}

Объект класса VisualStudioDataObject содержит методы, необходимые для извлечения информации из DataObject, на который ссылается событие DragDrop DragEventArgs:

(протестировано с Visual Studio 2017)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

class VisualStudioDataObject
{
    public VisualStudioDataObject(IDataObject data)
    {
        if (data is null) {
            throw new ArgumentNullException("IDataObject data", "Invalid DataObject");
        }
        this.FileList = new List<FileObject>();
        GetData(data);
    }

    public List<FileObject> FileList { get; private set; }
    public string ProjectUUID { get; private set; }
    public string ProjectPath { get; private set; }
    public string ProjectFilePath { get; private set; }
    public string StartingObject { get; private set; }

    public class FileObject
    {
        public FileObject(string project, string path, string type) {
            this.SourceProject = project;
            this.FilePath = path;
            this.FileType = type;
        }
        public string SourceProject { get; }
        public string FilePath { get; }
        public string FileType { get; }
    }

    private void GetData(IDataObject data)
    {
        List<string> formats = data.GetFormats(false).ToList();
        if (formats.Count == 0) return;

        foreach (string format in formats)
        {
            switch (format)
            {
                case "UnicodeText":
                    this.StartingObject = data.GetData(DataFormats.UnicodeText, true).ToString();
                    break;
                case "VX Clipboard Descriptor Format":
                    var projectMS = (MemoryStream)data.GetData("VX Clipboard Descriptor Format", false);
                    projectMS.Position = 0;
                    string prjFile = Encoding.Unicode.GetString(projectMS.ToArray()).TrimEnd("\0".ToCharArray());
                    this.ProjectFilePath = prjFile;
                    this.ProjectPath = Path.GetDirectoryName(prjFile);
                    break;
                case "CF_VSSTGPROJECTITEMS":
                    GetFileData((MemoryStream)data.GetData("CF_VSSTGPROJECTITEMS", false));
                    break;
            }
        }
    }
    private void GetFileData(MemoryStream ms)
    {
        string uuidPattern = @"\{(.*?)\}";
        string content = Encoding.Unicode.GetString(ms.ToArray());
        //Get the Project UUID and remove it from the data object
        var match = Regex.Match(content, uuidPattern, RegexOptions.Singleline);
        if (match.Success) {
            this.ProjectUUID = match.Value;
            content = content.Replace(this.ProjectUUID, "").Substring(match.Index);

            //Split the file list: Part1 => Project Name, Part2 => File name
            string[] projectFiles = content.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < projectFiles.Length; i += 2)
            {
                string sourceFile = projectFiles[i + 1].Substring(0, projectFiles[i + 1].IndexOf("\0"));
                this.FileList.Add(new FileObject(projectFiles[i], sourceFile, Path.GetExtension(sourceFile)));
            }
        }
        else
        {
            this.FileList = null;
            throw new InvalidDataException("Invalid Data content");
        }
    }
}
0 голосов
/ 03 апреля 2019

Я пытаюсь выполнить аппроксимацию с помощью TreeView Control:

        Tree.AllowDrop = true;
        Tree.DragEnter += (s, e) =>
        {
            e.Effect = DragDropEffects.Move;
        };

        Tree.DragDrop += (s, e) =>
        {
            var data = e.Data;
            var value = data.GetData(typeof(string));
        };

После удаления файла cs из обозревателя решений внутри дерева вы можете прочитать путь к файлу cs.Путь, который вы можете использовать для преобразования файла в zip.

>>> value = "C:\\Users\\Name\\Desktop\\Projekte\\Projekte-Visual Studio\\Project\\Project\\Classes\\Method.cs"

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...