|
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace JFileManager
{
internal class cDropFiles
{
private cDropFiles()
{
//
// No instances, all static - this is standalone as it is a bit specialised
//
}
/// <summary>
/// Copies array of file names to Clipboard in FileDrop format, returns true on success, false on failure
/// </summary>
/// <param name="strFiles">String array of fully qualified file names to be copied to Clipboard. </param>
public static DataObject CopyFilesToClipboardForDragDrop(string[] strFiles, POINT pt)
{
// Create and Copy File List to Clipboard in several formats
if (strFiles == null)
return null;
// Obtain a DROPFILES for the give list of files
MemoryStream msDrop = FileListToDropFiles(strFiles, pt);
// Get a DataObject for Shortcuts
MemoryStream msLinks = FileListToShellIDListArray(strFiles);
// Get a File List
string strFileList = CreateFileList(strFiles);
// Now wrap them all in one DataObject
DataObject doTemp = new DataObject();
doTemp.SetData(DataFormats.FileDrop, true, msDrop);
doTemp.SetData("Shell IDList Array", true, msLinks);
doTemp.SetData(DataFormats.StringFormat, true, strFileList);
// Copy the data object to the clipboard
Clipboard.SetDataObject(doTemp, false);
return doTemp;
}
private static string CreateFileList(string[] strSource)
{
string strReturn = "";
for (int intCount = 0; intCount <= strSource.GetUpperBound(0); intCount++)
strReturn += strSource[intCount] + '\0';
strReturn += '\0';
return strReturn;
}
private static object[] FileListToIDListArray(string[] files)
{
IntPtr pidl;
int cbPidl;
// Allocate an array of objects (byte arrays) to store the
// pidl of each item in the file list
object[] apidl = new object[files.Length];
for (int i = 0; i < files.Length; i++)
{
// Obtain a pidl for the file
pidl = ILCreateFromPath(files[i]);
cbPidl = (int)ILGetSize(pidl);
// Convert the pidl to a byte array
apidl[i] = (object)new byte[cbPidl];
Marshal.Copy(pidl, (byte[])apidl[i], 0, cbPidl);
// Free the pidl
ILFree(pidl);
}
return apidl;
}
private static MemoryStream FileListToShellIDListArray(string[] files)
{
int cb = 0;
int offset = 0;
int i;
uint pidlDesktop = 0;
object[] apidl = null;
MemoryStream stream = null;
BinaryWriter streamWriter = null;
// Convert the array of paths to an array of pidls
apidl = FileListToIDListArray(files);
// Determine the amount of memory required for the CIDA
// The 2 in the statement below is for the offset to the
// folder pidl and the count field in the CIDA structure
cb = offset = Marshal.SizeOf(typeof(uint)) * (apidl.Length + 2);
for (i = 0; i < apidl.Length; i++)
{
cb += ((byte[])apidl[i]).Length; ;
}
// Create a memory stream that we will write the CIDA into
stream = new MemoryStream();
// Wrap the memory stream with a BinaryWriter object
streamWriter = new BinaryWriter(stream);
// Write the cidl member of the CIDA structure
streamWriter.Write(apidl.Length);
// Write the array of offsets for each pidl. Calculate each offset as we go
streamWriter.Write(offset);
offset += Marshal.SizeOf(pidlDesktop);
for (i = 0; i < apidl.Length; i++)
{
streamWriter.Write(offset);
offset += ((byte[])apidl[i]).Length;
}
// Write the parent folder pidl
streamWriter.Write(pidlDesktop);
// Write the item pidls
for (i = 0; i < apidl.Length; i++)
{
streamWriter.Write((byte[])apidl[i]);
}
// Return the memory stream that contains the CIDA
return stream;
}
private static MemoryStream FileListToDropFiles(string[] strFiles, POINT pt)
{
DataObject doTemp = new DataObject();
int intNumFiles = strFiles.GetUpperBound(0) + 1;
int intCount;
// Create DROPFILES structure
DROPFILES df = new DROPFILES();
df.pFiles = Marshal.SizeOf(df);
df.pt = pt;
df.fNC = false;
df.fWide = 0;
// Calculate memory required
int intMemRequired = Marshal.SizeOf(typeof(DROPFILES));
IntPtr ipGlobal = Marshal.AllocHGlobal(intMemRequired);
// Copy the DROPFILES structure in to memory
Marshal.StructureToPtr(df, ipGlobal, true);
// Debugging - Read it back
//DROPFILES dfTemp = new DROPFILES();
//dfTemp = (DROPFILES)Marshal.PtrToStructure(ipGlobal, typeof(DROPFILES));
// Create a MemoryStream that we will write the data into
MemoryStream msTemp = new MemoryStream();
BinaryWriter streamWriter = new BinaryWriter(msTemp);
// Write the DROPFILES structure to the MemoryStream - convert to a byte[]
byte[] bTemp = new byte[Marshal.SizeOf(typeof(DROPFILES))];
Marshal.Copy(ipGlobal, bTemp, 0, 20);
streamWriter.Write(bTemp, 0, 20);
// Now Write the FileList - don't copy over strFiles, it copies the preceeding '@' and breaks it!
string strFileList = CreateFileList(strFiles);
for (intCount = 0; intCount < strFileList.Length; intCount++)
streamWriter.Write(strFileList[intCount]);
// Terminating double zero
streamWriter.Write((byte)0);
streamWriter.Write((byte)0);
// //Debugging - write it to a file to test
// string strTest = @"D:\Temp\TestData.bin";
// FileStream fs = new FileStream(strTest, FileMode.Create);
// // Create the writer for data.
// BinaryReader r = new BinaryReader(msTemp);
// msTemp.Position = 0;
//
// BinaryWriter w = new BinaryWriter(fs);
// // Write data to Test.data.
// try
// {
// for(int i = 0; i < msTemp.Length; i++)
// {
// w.Write(r.ReadByte());
// }
// }
// finally
// {
// w.Close();
// }
// Free Global Memory
Marshal.FreeHGlobal(ipGlobal);
return msTemp;
}
// ILCreateFromPath
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr ILCreateFromPath(string pwszPath);
// ILFree
[DllImport("shell32.dll", CharSet = CharSet.None)]
public static extern void ILFree(IntPtr pidl);
// ILGetSize
[DllImport("shell32.dll", CharSet = CharSet.None)]
public static extern uint ILGetSize(IntPtr pidl);
[StructLayout(LayoutKind.Sequential)]
public struct DROPFILES
{
public int pFiles;
public POINT pt;
public bool fNC;
public int fWide;
}
} // End cDropFiles
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I have been a keen hobbyist programmer since getting my first computer - a Vic 20 (you had to be able to write programs then since few programs were available and all were expensive).
Retired and now living in Pewsey, Wiltshire, where I spend (far too much of) my time writing computer programs to keep my mind active.