今天在论坛看到一个贴子,问如何知道在拖放<我的电脑>
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
IntPtrILCombine(
IntPtrpidl1,IntPtrpidl2);
[DllImport(
"
shell32.dll
"
)]
public
static
extern
void
ILFree(
IntPtrpidl);
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
IntPtrhIcon;
public
int
iIcon;
public
SFGAOdwAttributes;
[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
IntPtrSHGetFileInfo(
IntPtrppidl,
FILE_ATTRIBUTEdwFileAttributes,
ref
SHFILEINFOsfi,
int
cbFileInfo,
SHGFIuFlags);
protected
override
void
OnDragDrop(DragEventArgsdrgevent)
{
base
.OnDragDrop(drgevent);
MemoryStreamdata
=
(MemoryStream)drgevent.Data.GetData(
"
ShellIDListArray
"
);
byte
[]b
=
data.ToArray();
IntPtrp
=
Marshal.AllocHGlobal(b.Length);
Marshal.Copy(b,
0
,p,b.Length);
//
Getnumberofitems.
UInt32cidl
=
(UInt32)Marshal.ReadInt32(p);
int
offset
=
sizeof
(UInt32);
IntPtrparentpidl
=
(IntPtr)((
int
)p
+
(UInt32)Marshal.ReadInt32(p,offset));
//
Getsubitems.
for
(
int
i
=
1
;i
<=
cidl;
++
i)
{
offset
+=
sizeof
(UInt32);
IntPtrrelpidl
=
(IntPtr)((
int
)p
+
(UInt32)Marshal.ReadInt32(p,offset));
IntPtrabspidl
=
ILCombine(parentpidl,relpidl);
SHFILEINFOsf
=
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);
}
}