C# 如何用DragDrop拖放特殊文件到程序窗口 (如:我的电脑 回收站 网上邻居)
2014-10-22 17:00
501 查看
最常见的情况是把一个文件拖放到Form窗体中,窗体显示文件的路径和文件名。这个功能容易实现,具体思路是借助Form的事件响应函数DragEnter和DragDrop来完成。
DragEnter函数主要作用是在拖拽文件进入窗体时修改鼠标图标样式,指定拖拽的可能效果(是拷贝文件数据,还是显示文件路径)。
DragDrop函数主要作用是在鼠标拖放结束时进行某些操作。
可以使用下面代码实现常规文件的拖放:
函数e.Data.GetData(string)里可填的数据类型可以是DataFormats.FileDrop,也可以是字符串形式如"FileDrop","FileName"等,根据拖放文件的类型而不同。我们可以通过e.Data.GetFormats()来获得具体的格式类型列表。
常规文件Formats类型信息如下:
例如:FileDrop包含了文件的全路径字符串,FileName则包含文件名。
特殊文件的拖放(如:我的电脑,网上邻居,回收站等)也可以用e.Data.GetFormats()来获得具体的格式类型列表。
具体信息如下:
显然里面并没有FileDrop和FileName。因此要想获取特殊文件的文件名用FileDrop和FileName不行。那么这个办法就不奏效了。
然而我们却注意到一个细节,不论什么类型的文件都有"Shell IDList Array","DragImageBits",“DragContext”等其它信息。
经过查找相关资料了解到"Shell IDList Array"实际上它指向一个CIDA结构。通过它可以得到对应的PIDL。而PIDL里有文件的相关信息。
特殊文件拖放的实现代码:
效果截图:
DragEnter函数主要作用是在拖拽文件进入窗体时修改鼠标图标样式,指定拖拽的可能效果(是拷贝文件数据,还是显示文件路径)。
DragDrop函数主要作用是在鼠标拖放结束时进行某些操作。
可以使用下面代码实现常规文件的拖放:
<pre name="code" class="csharp"> private void Form1_DragEnter(object sender, DragEventArgs e) { <span style="white-space:pre"> </span>e.Effect = DragDropEffects.Link; //重要代码:把拖拽的文件当成一个文件链接 } <span style="white-space:pre"> </span>private void Form1_DragDrop(object sender, DragEventArgs e) { //string[] formatList = e.Data.GetFormats(); string filename = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString (); //或者 string filename = ((Array)e.Data.GetData(“FileDrop”)).GetValue(0).ToString (); }
函数e.Data.GetData(string)里可填的数据类型可以是DataFormats.FileDrop,也可以是字符串形式如"FileDrop","FileName"等,根据拖放文件的类型而不同。我们可以通过e.Data.GetFormats()来获得具体的格式类型列表。
常规文件Formats类型信息如下:
例如:FileDrop包含了文件的全路径字符串,FileName则包含文件名。
特殊文件的拖放(如:我的电脑,网上邻居,回收站等)也可以用e.Data.GetFormats()来获得具体的格式类型列表。
具体信息如下:
显然里面并没有FileDrop和FileName。因此要想获取特殊文件的文件名用FileDrop和FileName不行。那么这个办法就不奏效了。
然而我们却注意到一个细节,不论什么类型的文件都有"Shell IDList Array","DragImageBits",“DragContext”等其它信息。
经过查找相关资料了解到"Shell IDList Array"实际上它指向一个CIDA结构。通过它可以得到对应的PIDL。而PIDL里有文件的相关信息。
特殊文件拖放的实现代码:
private void Form1_DragEnter(object sender, DragEventArgs e) { e.Effect = DragDropEffects.Link; //重要代码:把拖拽的文件当成一个文件链接 } private void Form1_DragDrop(object sender, DragEventArgs e) { string[] str = e.Data.GetFormats(); MemoryStream data = (MemoryStream)e.Data.GetData("Shell IDList Array"); byte[] b = data.ToArray(); IntPtr p = Marshal.AllocHGlobal(b.Length); Marshal.Copy(b, 0, p, b.Length); UInt32 cidl = (UInt32)Marshal.ReadInt32(p); int offset = sizeof(UInt32); IntPtr parentpidl = (IntPtr)((int)p + (UInt32)Marshal.ReadInt32(p, offset)); for (int i = 1; i <= cidl; ++i) { offset += sizeof(UInt32); IntPtr relpidl = (IntPtr)((int)p + (UInt32)Marshal.ReadInt32(p, offset)); IntPtr abspidl = ILCombine(parentpidl, relpidl); SHFILEINFO sf = new SHFILEINFO(); if (SHGetFileInfo(abspidl, 0, ref sf, Marshal.SizeOf(sf), SHGFI.PIDL | SHGFI.DISPLAYNAME | SHGFI.TYPENAME).ToInt32() > 0) { MessageBox.Show(sf.szDisplayName); } ILFree(abspidl); } }"Shell IDList Array"的构建与解析用到了下面的代码:(参考帖子:http://www.cnblogs.com/feiyun0112/archive/2009/02/09/1386802.html)
[DllImport("shell32.dll")] public static extern IntPtr ILCombine(IntPtr pidl1, IntPtr pidl2); [DllImport("shell32.dll")] public static extern void ILFree(IntPtr pidl); public enum SFGAO : uint { BROWSABLE = 0x8000000, CANCOPY = 1, CANDELETE = 0x20, CANLINK = 4, CANMONIKER = 0x400000, CANMOVE = 2, CANRENAME = 0x10, CAPABILITYMASK = 0x177, COMPRESSED = 0x4000000, CONTENTSMASK = 0x80000000, DISPLAYATTRMASK = 0xfc000, DROPTARGET = 0x100, ENCRYPTED = 0x2000, FILESYSANCESTOR = 0x10000000, FILESYSTEM = 0x40000000, FOLDER = 0x20000000, GHOSTED = 0x8000, HASPROPSHEET = 0x40, HASSTORAGE = 0x400000, HASSUBFOLDER = 0x80000000, HIDDEN = 0x80000, ISSLOW = 0x4000, LINK = 0x10000, NEWCONTENT = 0x200000, NONENUMERATED = 0x100000, READONLY = 0x40000, REMOVABLE = 0x2000000, SHARE = 0x20000, STORAGE = 8, STORAGEANCESTOR = 0x800000, STORAGECAPMASK = 0x70c50008, STREAM = 0x400000, VALIDATE = 0x1000000 } public const int MAX_PATH = 260; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct SHFILEINFO { public IntPtr hIcon; public int iIcon; public SFGAO dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; } public enum SHGFI : uint { ADDOVERLAYS = 0x20, ATTR_SPECIFIED = 0x20000, ATTRIBUTES = 0x800, DISPLAYNAME = 0x200, EXETYPE = 0x2000, ICON = 0x100, ICONLOCATION = 0x1000, LARGEICON = 0, LINKOVERLAY = 0x8000, OPENICON = 2, OVERLAYINDEX = 0x40, PIDL = 8, SELECTED = 0x10000, SHELLICONSIZE = 4, SMALLICON = 1, SYSICONINDEX = 0x4000, TYPENAME = 0x400, USEFILEATTRIBUTES = 0x10 } public enum FILE_ATTRIBUTE { READONLY = 0x00000001, HIDDEN = 0x00000002, SYSTEM = 0x00000004, DIRECTORY = 0x00000010, ARCHIVE = 0x00000020, DEVICE = 0x00000040, NORMAL = 0x00000080, TEMPORARY = 0x00000100, SPARSE_FILE = 0x00000200, REPARSE_POINT = 0x00000400, COMPRESSED = 0x00000800, OFFLINE = 0x00001000, NOT_CONTENT_INDEXED = 0x00002000, ENCRYPTED = 0x00004000 } [DllImport("shell32", EntryPoint = "SHGetFileInfo", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr SHGetFileInfo(IntPtr ppidl, FILE_ATTRIBUTE dwFileAttributes, ref SHFILEINFO sfi, int cbFileInfo, SHGFI uFlags);
效果截图:
相关文章推荐
- 如何用命令行方式进入我的电脑、回收站、网上邻居
- asp.net C#如何调用文件选择窗口
- 程序中如何删除MO中当前正在使用的SHP文件(C#,MO2.4)
- XP网上邻居访问别的电脑要用户名和密码,如何取消
- C#程序中:如何修改xml文件中的节点(数据)(
- C#文件拖放操作(DragDrop File)
- [愚翁专栏]如何用C#做一个悬浮窗口程序
- 如何在ASP.NET中实现拖放Drag and drop
- QT 文件拖放事件dropEvent和dragEnterEvent
- c# 如何获得你电脑安装的所有程序信息
- 如何用C#做一个悬浮窗口程序
- c# .net 如何截取当前程序窗口指定位置的截图
- 如何在C#中用程序执行指定的SQL脚本文件,实现自动安装创建数据库.txt
- 【转】C#生成dll文件:如何用C#编译生成dll文件即动态链接库文件供其它程序调用
- 如何在C#中用程序执行指定的SQL脚本文件,实现自动安装创建数据库
- 如何用C#开发的程序,打开关联文本文件,并且读取文件
- 如何用C#做一个悬浮窗口程序
- 如何用C#做一个悬浮窗口程序
- 如何用c++或者C#打开特殊的系统窗口,如power options
- 如何用C#编写程序监测某个文件夹内是否有文件进行了增,删,改的动作?