/// <summary>
/// Helper class with Windows Clipboard functions
/// </summary>
internal
static
class
ClipboardUtils
{
#region NativeMethods class
private
static
class
NativeMethods
{
public
const
string
CFSTR_FILEDESCRIPTORW =
"FileGroupDescriptorW"
;
[Flags]
public
enum
FD :
uint
{
FD_ACCESSTIME = 0x10,
FD_ATTRIBUTES = 4,
FD_CLSID = 1,
FD_CREATETIME = 8,
FD_FILESIZE = 0x40,
FD_LINKUI = 0x8000,
FD_SIZEPOINT = 2,
FD_WRITESTIME = 0x20
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public
struct
FILEDESCRIPTOR
{
public
FD 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;
}
}
#endregion
#region action methods
public
static
bool
ContainsClipboardFiles()
{
if
(Clipboard.ContainsFileDropList())
{
return
true
;
}
var
dataObject = (DataObject)Clipboard.GetDataObject();
return
dataObject.GetDataPresent(NativeMethods.CFSTR_FILEDESCRIPTORW);
}
public
static
List<ClipboardFileInfo> GetClipboardFiles()
{
var
list =
new
List<ClipboardFileInfo>();
if
(Clipboard.ContainsFileDropList())
{
var
fileDropList = Clipboard.GetFileDropList();
if
(fileDropList !=
null
&& fileDropList.Count != 0)
{
foreach
(
string
item
in
fileDropList)
{
var
fi =
new
System.IO.FileInfo(item);
if
(fi.Exists && (fi.Attributes & FileAttributes.Directory) == 0)
{
list.Add(
new
ClipboardFileInfo(fi));
}
}
}
}
else
{
var
dataObject = (DataObject)Clipboard.GetDataObject();
List<NativeMethods.FILEDESCRIPTOR> descriptors = GetFileDescriptors(dataObject);
int
fileIndex = -1;
foreach
(
var
descriptor
in
descriptors)
{
fileIndex++;
if
((descriptor.dwFlags & NativeMethods.FD.FD_ATTRIBUTES) != 0 &&
((FileAttributes)descriptor.dwFileAttributes & FileAttributes.Directory) == 0)
{
if
(descriptors.Any(o => descriptor.cFileName.StartsWith(o.cFileName +
"\\"
)))
{
continue
;
}
long
length = ((descriptor.nFileSizeHigh << 0x20) | (descriptor.nFileSizeLow & ((
long
) 0xffffffffL)));
list.Add(
new
ClipboardFileInfo(dataObject, fileIndex, descriptor.cFileName, (FileAttributes)descriptor.dwFileAttributes, length));
}
}
}
return
list;
}
#endregion
#region private member functions
private
static
List<NativeMethods.FILEDESCRIPTOR> GetFileDescriptors(DataObject dataObject)
{
var
list =
new
List<NativeMethods.FILEDESCRIPTOR>();
if
(dataObject.GetDataPresent(NativeMethods.CFSTR_FILEDESCRIPTORW))
{
var
obj2 = dataObject
as
System.Runtime.InteropServices.ComTypes.IDataObject;
if
(obj2 !=
null
)
{
var
input = dataObject.GetData(NativeMethods.CFSTR_FILEDESCRIPTORW)
as
Stream;
if
(input !=
null
)
{
int
count =
new
BinaryReader(input).ReadInt32();
for
(
int
i = 0; i < count; i++)
{
var
descriptor = (NativeMethods.FILEDESCRIPTOR)ReadStructureFromStream(input,
typeof
(NativeMethods.FILEDESCRIPTOR));
list.Add(descriptor);
}
}
}
}
return
list;
}
private
static
object
ReadStructureFromStream(Stream source, Type structureType)
{
byte
[] buffer =
new
byte
[Marshal.SizeOf(structureType)];
int
readed = source.Read(buffer, 0, buffer.Length);
if
(readed == buffer.Length)
{
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
IntPtr ptr = handle.AddrOfPinnedObject();
return
Marshal.PtrToStructure(ptr, structureType);
}
finally
{
handle.Free();
}
}
if
(readed != 0)
{
throw
new
ArgumentException(
"source is too small to hold entire structure"
);
}
return
null
;
}
#endregion
}