如何使用filegroupdescriptor将文件拖到资源管理器c# [英] How to use filegroupdescriptor to drag file to explorer c#

查看:15
本文介绍了如何使用filegroupdescriptor将文件拖到资源管理器c#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将列表框的元素拖放到资源管理器.开始拖放时,我需要按需准备文件并将其保存到内存流中.你能给我提供一个如何使用 FileGroupDescriptor 数据结构的例子吗?谢谢.安德烈亚

解决方案

您可以在此处找到有关如何执行此操作的示例 在 C# 中将虚拟文件传输到 Windows 资源管理器;还有一些关于这个主题的好信息:Outlook 拖放 C#p>

简而言之,您要做的是使用 FILEDESCRIPTOR(您可以在 pinvoke.net 上找到它的声明详细信息)结构来初始化 DataObject,以便传输文件及其内容.下面是如何将 1 文件从 winforms ListBox 传输到资源管理器的示例.

列表框的鼠标按下事件处理程序:

private void listBox1_MouseDown(object sender, MouseEventArgs e){数据对象数据对象 = 新数据对象();DragFileInfo filesInfo = new DragFileInfo("d:\test.txt");使用 (MemoryStream infoStream = GetFileDescriptor(filesInfo),contentStream = GetFileContents(filesInfo)){dataObject.SetData(CFSTR_FILEDESCRIPTORW, infoStream);dataObject.SetData(CFSTR_FILECONTENTS, contentStream);dataObject.SetData(CFSTR_PERFORMEDDROPEFFECT, null);DoDragDrop(dataObject, DragDropEffects.All);}}

初始化数据对象所需的代码:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]结构文件描述符{公共 UInt32 dwFlags;公共指导 clsid;public System.Drawing.Size sizel;公共 System.Drawing.Point 点;公共 UInt32 dwFileAttributes;公共 System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;公共 System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;公共 System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;公共 UInt32 nFileSizeHigh;公共 UInt32 nFileSizeLow;[MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)]公共字符串 cFileName;}公共常量字符串 CFSTR_PREFERREDDROPEFFECT = "首选 DropEffect";公共常量字符串 CFSTR_PERFORMEDDROPEFFECT = "执行 DropEffect";公共常量字符串 CFSTR_FILEDESCRIPTORW = "FileGroupDescriptorW";公共常量字符串 CFSTR_FILECONTENTS = "文件内容";公共常量 Int32 FD_WRITESTIME = 0x00000020;公共常量 Int32 FD_FILESIZE = 0x00000040;公共常量 Int32 FD_PROGRESSUI = 0x00004000;公共结构 DragFileInfo{公共字符串文件名;公共字符串源文件名;公共日期时间写入时间;公共 Int64 文件大小;公共 DragFileInfo(字符串文件名){FileName = Path.GetFileName(fileName);源文件名 = 文件名;写入时间 = 日期时间.现在;FileSize = (new FileInfo(fileName)).L​​ength;}}私有 MemoryStream GetFileDescriptor(DragFileInfo fileInfo){MemoryStream 流 = 新的 MemoryStream();stream.Write(BitConverter.GetBytes(1), 0, sizeof(UInt32));FILEDESCRIPTOR 文件描述符 = 新的 FILEDESCRIPTOR();fileDescriptor.cFileName = fileInfo.FileName;Int64 fileWriteTimeUtc = fileInfo.WriteTime.ToFileTimeUtc();fileDescriptor.ftLastWriteTime.dwHighDateTime = (Int32)(fileWriteTimeUtc >> 32);fileDescriptor.ftLastWriteTime.dwLowDateTime = (Int32)(fileWriteTimeUtc & 0xFFFFFFFF);fileDescriptor.nFileSizeHigh = (UInt32)(fileInfo.FileSize >> 32);fileDescriptor.nFileSizeLow = (UInt32)(fileInfo.FileSize & 0xFFFFFFFF);文件描述符.dwFlags = FD_WRITESTIME |FD_FILESIZE |FD_PROGRESSUI;Int32 fileDescriptorSize = Marshal.SizeOf(fileDescriptor);IntPtr fileDescriptorPointer = Marshal.AllocHGlobal(fileDescriptorSize);字节[] fileDescriptorByteArray = new Byte[fileDescriptorSize];尝试{Marshal.StructureToPtr(fileDescriptor, fileDescriptorPointer, true);Marshal.Copy(fileDescriptorPointer, fileDescriptorByteArray, 0, fileDescriptorSize);}最后{Marshal.FreeHGlobal(fileDescriptorPointer);}stream.Write(fileDescriptorByteArray, 0, fileDescriptorByteArray.Length);返回流;}私有 MemoryStream GetFileContents(DragFileInfo fileInfo){MemoryStream 流 = 新的 MemoryStream();使用 (BinaryReader reader = new BinaryReader(File.OpenRead(fileInfo.SourceFileName))){字节[] 缓冲区 = 新字节[fileInfo.FileSize];reader.Read(buffer, 0, (Int32)fileInfo.FileSize);if (buffer.Length == 0) 缓冲区 = 新字节[1];stream.Write(buffer, 0, buffer.Length);}返回流;}

希望这能让您了解如何进行,问候

I would like to drag and drop an element of a listbox to explorer. When the drag and drop is started, I need to prepare the file on demand and save it to a memory stream. Can you provide me with an example on how to do it using the FileGroupDescriptor data structure? Thanks. Andrea

解决方案

you can find an example on how to do this here Transferring Virtual Files to Windows Explorer in C#; also some good info on the topic here: Outlook Drag and Drop in C#

In short what you have to do is to init the DataObject with FILEDESCRIPTOR (you can find its declaration details on pinvoke.net) structure(s) for file(s) getting transfered and their content. Below is an example on how you could transfer 1 file from winforms ListBox to explorer.

mouse down event handler for the listbox:

private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
    DataObject dataObject = new DataObject();
    DragFileInfo filesInfo = new DragFileInfo("d:\test.txt");

    using (MemoryStream infoStream = GetFileDescriptor(filesInfo),
                        contentStream = GetFileContents(filesInfo))
    {
        dataObject.SetData(CFSTR_FILEDESCRIPTORW, infoStream);
        dataObject.SetData(CFSTR_FILECONTENTS, contentStream);
        dataObject.SetData(CFSTR_PERFORMEDDROPEFFECT, null);

        DoDragDrop(dataObject, DragDropEffects.All);
    }
}

code needed to init the dataobject:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
struct FILEDESCRIPTOR
{
    public UInt32 dwFlags;
    public Guid clsid;
    public System.Drawing.Size sizel;
    public System.Drawing.Point pointl;
    public UInt32 dwFileAttributes;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
    public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
    public UInt32 nFileSizeHigh;
    public UInt32 nFileSizeLow;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)]
    public String cFileName;
}

public const string CFSTR_PREFERREDDROPEFFECT = "Preferred DropEffect";
public const string CFSTR_PERFORMEDDROPEFFECT = "Performed DropEffect";
public const string CFSTR_FILEDESCRIPTORW = "FileGroupDescriptorW";
public const string CFSTR_FILECONTENTS = "FileContents";

public const Int32 FD_WRITESTIME = 0x00000020;
public const Int32 FD_FILESIZE = 0x00000040;
public const Int32 FD_PROGRESSUI = 0x00004000;

public struct DragFileInfo
{
    public string FileName;
    public string SourceFileName;
    public DateTime WriteTime;
    public Int64 FileSize;

    public DragFileInfo(string fileName)
    {
        FileName = Path.GetFileName(fileName);
        SourceFileName = fileName;
        WriteTime = DateTime.Now;
        FileSize = (new FileInfo(fileName)).Length;
    }
}

private MemoryStream GetFileDescriptor(DragFileInfo fileInfo)
{
    MemoryStream stream = new MemoryStream();
    stream.Write(BitConverter.GetBytes(1), 0, sizeof(UInt32));

    FILEDESCRIPTOR fileDescriptor = new FILEDESCRIPTOR();

    fileDescriptor.cFileName = fileInfo.FileName;
    Int64 fileWriteTimeUtc = fileInfo.WriteTime.ToFileTimeUtc();
    fileDescriptor.ftLastWriteTime.dwHighDateTime = (Int32)(fileWriteTimeUtc >> 32);
    fileDescriptor.ftLastWriteTime.dwLowDateTime = (Int32)(fileWriteTimeUtc & 0xFFFFFFFF);
    fileDescriptor.nFileSizeHigh = (UInt32)(fileInfo.FileSize >> 32);
    fileDescriptor.nFileSizeLow = (UInt32)(fileInfo.FileSize & 0xFFFFFFFF);
    fileDescriptor.dwFlags = FD_WRITESTIME | FD_FILESIZE | FD_PROGRESSUI;

    Int32   fileDescriptorSize = Marshal.SizeOf(fileDescriptor);
    IntPtr  fileDescriptorPointer = Marshal.AllocHGlobal(fileDescriptorSize);
    Byte[]  fileDescriptorByteArray = new Byte[fileDescriptorSize];

    try
    {
        Marshal.StructureToPtr(fileDescriptor, fileDescriptorPointer, true);
        Marshal.Copy(fileDescriptorPointer, fileDescriptorByteArray, 0, fileDescriptorSize);
    }
    finally
    {
        Marshal.FreeHGlobal(fileDescriptorPointer);
    }
    stream.Write(fileDescriptorByteArray, 0, fileDescriptorByteArray.Length);
    return stream;
}

private MemoryStream GetFileContents(DragFileInfo fileInfo)
{
    MemoryStream stream  = new MemoryStream();            
    using (BinaryReader reader = new BinaryReader(File.OpenRead(fileInfo.SourceFileName)))
    {
        Byte[] buffer = new Byte[fileInfo.FileSize];
        reader.Read(buffer, 0, (Int32)fileInfo.FileSize);
        if (buffer.Length == 0) buffer = new Byte[1];
        stream.Write(buffer, 0, buffer.Length);
    }
    return stream;
}

hope this will give you an idea on how to proceed, regards

这篇关于如何使用filegroupdescriptor将文件拖到资源管理器c#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆