今天在论坛看到一个贴子,问如何知道在拖放<我的电脑>
http://social.microsoft.com/Forums/zh-CN/visualcshartzhchs/thread/2a4fc136-3d57-4c64-87de-f19aa9a76d0e/
试了一下。发现DragEventArgs.Data可以得到"Shell IDList Array"格式的数据,它实际指向一个CIDA structurer
http://msdn.microsoft.com/en-us/library/bb773212.aspx
通过它,我们就可以得到对应的PIDL (如果对 PIDL 不熟悉,请看Windows外壳名字空间的浏览)。
有了PIDL, 我们就和容易得到文件的相关信息。
[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);
protected override void OnDragDrop(DragEventArgs drgevent)
{
base .OnDragDrop(drgevent);
MemoryStream data = (MemoryStream)drgevent.Data.GetData( " Shell IDList Array " );
byte [] b = data.ToArray();
IntPtr p = Marshal.AllocHGlobal(b.Length);
Marshal.Copy(b, 0 , p, b.Length);
// Get number of items.
UInt32 cidl = (UInt32)Marshal.ReadInt32(p);
int offset = sizeof (UInt32);
IntPtr parentpidl = (IntPtr)(( int )p + (UInt32)Marshal.ReadInt32(p, offset));
// Get subitems.
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);
}
}
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);
protected override void OnDragDrop(DragEventArgs drgevent)
{
base .OnDragDrop(drgevent);
MemoryStream data = (MemoryStream)drgevent.Data.GetData( " Shell IDList Array " );
byte [] b = data.ToArray();
IntPtr p = Marshal.AllocHGlobal(b.Length);
Marshal.Copy(b, 0 , p, b.Length);
// Get number of items.
UInt32 cidl = (UInt32)Marshal.ReadInt32(p);
int offset = sizeof (UInt32);
IntPtr parentpidl = (IntPtr)(( int )p + (UInt32)Marshal.ReadInt32(p, offset));
// Get subitems.
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);
}
}