Creating a DROPFILES Structure

  • Thread starter Thread starter Jeff Gaines
  • Start date Start date
J

Jeff Gaines

I am trying to set up a DROPFILES structure and copy it to the
clipboard as follows:

[StructLayout(LayoutKind.Sequential)]
struct POINT
{
public int x;
public int y;
}

[StructLayout(LayoutKind.Sequential)]
struct DROPFILES
{
public int pFiles;
public POINT pt;
public bool fNC;
public bool fWide;
}

public bool clipCopyFiles(string[] strFiles)
{
bool blnReturn = false;
char[] cData;
DROPFILES df = new DROPFILES();
int intChars, intFiles, intPos;
int intDataLen = 0;
IntPtr lpGlobal = IntPtr.Zero;

// Build null terminated list of files
// Data length is total length of file names plus trailing null
intDataLen = 0;
int intNumFiles = strFiles.GetUpperBound(0);
for(intFiles = 0; intFiles <= intNumFiles; intFiles++)
intDataLen = intDataLen + strFiles[intFiles].Length + 1;

// Allow for final trailing zero
intDataLen++;

// Initialise char array with a margin
cData = new Char[intDataLen + 2];
intPos = 0;

for(intFiles = 0; intFiles <= intNumFiles; intFiles++)
{
for(intChars = 0; intChars < strFiles[intFiles].Length;
intChars++)
cData[intPos++] = strFiles[intFiles][intChars];
cData[intPos++] = '\0';
}
cData[intPos++] = '\0';

// Allocate and get pointer to global memory - needs a margin!
lpGlobal = Marshal.AllocHGlobal(Marshal.SizeOf(df) + intDataLen
+ 10);
if(lpGlobal == IntPtr.Zero)
return false;

// Build DROPFILES structure in global memory.
df.pFiles = Marshal.SizeOf(df);
df.fWide = false;
Marshal.StructureToPtr(df, lpGlobal, true);
IntPtr ipNew = new IntPtr(lpGlobal.ToInt32() +
Marshal.SizeOf(df));
Marshal.Copy(cData, 0, ipNew, intDataLen);

// Open and empty clipboard
if(!OpenClipboard(this.Handle))
return false;

EmptyClipboard();

// Copy data to clipboard
blnReturn = (SetClipboardData(CF_HDROP, lpGlobal) !=
IntPtr.Zero);

// Clean up
CloseClipboard();
Marshal.FreeHGlobal(lpGlobal);

return blnReturn;
}

It is based on a VB6 app (that works fine). I have had quite a few
crashes getting it together and it now works to the extent that
getting the file format from the clipboard returns 'FileDrop'. Right
clicking in Explorer shows the 'Paste' option is available but
attempting to paste the files in Explorer produces the error 'Cannot
copy file: Cannot read from the source file or disk'. The files do
exist and I am trying to paste into another folder, i.e. not on top of
the existing files.

Has anybody any thought on this? Am I attempting the impossible?
It seems so close yet so far :-))
 
I am trying to set up a DROPFILES structure and copy it to the
clipboard as follows:

A follow up to my own post :-((

Like most things the route to the answer came to me once I'd put the
computer down for an hour.

Using:

Marshal.Copy(cData, 0, ipNew, intDataLen);

with cData as a char array copies each letter followed by a zero so
scrambling the file names. By using a byte array and copying data into
it thus:

bData[intPos++] = (byte)strFiles[intFiles][intChars];

the data is copied sequentially into memory without the extra zeros, I
guess it's a function of the size of 'char' against 'byte'.

The routine now works and can be used to copy a list of file names to
the Clipboard for pasting into Explorer or elsewhere.
 
Back
Top