Поскольку эта задача может быть несколько менее простой, чем на бумаге, здесь приведен пример процедуры, которая должна позволить получить список файлов, перетаскиваемых из панели обозревателя решений 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");
}
}
}