C# 从.Net解决方案资源管理器拖放时,如何以编程方式获取文件名?
我想编写一个应用程序,通过直接将文件从VisualStudio解决方案资源管理器拖放到我的应用程序中来生成zip文件 我使用了以下代码段来捕获传入的数据对象:C# 从.Net解决方案资源管理器拖放时,如何以编程方式获取文件名?,c#,.net,visual-studio,winforms,C#,.net,Visual Studio,Winforms,我想编写一个应用程序,通过直接将文件从VisualStudio解决方案资源管理器拖放到我的应用程序中来生成zip文件 我使用了以下代码段来捕获传入的数据对象: private void lblIncludedFiles_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Co
private void lblIncludedFiles_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.Copy;
}
}
我尝试了
数据格式的所有可能值,它们都返回false 我试着用TreeView控件接近:
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"
希望能有所帮助。由于此任务可能没有纸面上看起来那么简单,因此下面是一个示例过程,该过程应允许获取从Visual Studio解决方案资源管理器面板拖动的文件列表
Visual Studio生成的数据格式
部分通用(UnicodeText
和Text
),但实际的文件列表在一个(经典的)MemoryStream对象中传递,该对象不是通用的数据格式
:CF_VSSTGPROJECTITEMS
MemoryStream包含Unicode文本,即正在删除的项目+文件名元组的实际列表,由管道(|
)符号分隔,以及一些我认为在这里描述不有用的其他二进制部分
另一种非通用/预定义格式,VX剪贴板描述符格式,也是MemoryStream对象,但它只是一个包含项目名称的Unicode字符串
在此示例中,作为放置的一部分的组合元素使用包含以下信息的自定义类对象进行组织:
- 文件来自的项目的名称和UUID
- 项目路径和文件路径(
[xxx]prj
)
- 启动拖放操作的对象的名称
- 删除的所有文件、它们所属的项目及其原始类型的列表(
.cs
、.vb
、.h
、.png
等)
选择将接收拖放的控件并添加处理程序:
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)
{
var vsObject = new VisualStudioDataObject(e.Data);
}
类对象VisualStudioDataObject
包含从DragDrop
事件DragEvents
引用的DataObject
提取信息所需的方法:
(使用Visual Studio 2017进行测试)
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用系统文本;
使用System.Text.RegularExpressions;
使用System.Windows.Forms;
类VisualStudioDataObject
{
公共VisualStudioDataObject(IDataObject数据)
{
如果(数据为空){
抛出新ArgumentNullException(“IDataObject数据”、“无效数据对象”);
}
this.FileList=新列表();
获取数据(数据);
}
公共列表文件列表{get;private set;}
公共字符串ProjectUUID{get;private set;}
公共字符串项目路径{get;private set;}
公共字符串ProjectFilePath{get;private set;}
公共字符串开始对象{get;private set;}
公共类文件对象
{
公共文件对象(字符串项目、字符串路径、字符串类型){
this.SourceProject=project;
this.FilePath=path;
this.FileType=type;
}
公共字符串源项目{get;}
公共字符串文件路径{get;}
公共字符串文件类型{get;}
}
私有void GetData(IDataObject数据)
{
列表格式=data.GetFormats(false).ToList();
如果(formats.Count==0)返回;
foreach(格式中的字符串格式){
开关(格式){
案例“Unicodext”:
this.StartingObject=data.GetData(DataFormats.unicodext,true).ToString();
打破
案例“VX剪贴板描述符格式”:
var projectMS=(MemoryStream)data.GetData(格式,false);
projectMS.Position=0;
string prjFile=Encoding.Unicode.GetString(projectMS.ToArray()).TrimEnd(“\0.toCharray());
this.ProjectFilePath=prjFile;
this.ProjectPath=Path.GetDirectoryName(prjFile);
打破
案例“CF_VSSTG项目”:
GetFileData((MemoryStream)data.GetData(format,false));
打破
}
}
}
私有void GetFileData(MemoryStream ms)
{
字符串uuidPattern=@“\{(.*?\}”;
字符串内容=Encoding.Unicode.GetString(ms.ToArray());
//获取项目UUID并将其从数据对象中删除
var match=Regex.match(content、uuidPattern、RegexOptions.Singleline);
如果(匹配成功){
this.ProjectUUID=match.Value;
content=content.Replace(this.ProjectUUID,”).Substring(match.Index);
//拆分文件列表:Part1=>Project Name,Part2=>file Name
string[]projectFiles=content.Split(新的[]{'|'},StringSplitOptions.RemoveEmptyEntries);
对于(int i=0;i
谢谢您抽出时间。虽然您的解决方案可以很好地进行单个选择,但当您选择多个项目时,它仅显示第一个项目的文件。这就是我选择另一种解决方案的原因。非常感谢。这个解决方案是完美的!
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(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(format, 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");
}
}
}