I`m developing an application in C# associated with Windows clipboard. As there are many disadvantages in Dot Net Clipboard library (STA, Fail to Open Clipboard, etc. ) I dicided to use system API directly.
What I want to do is backup data of each format ( as many as possible, if not all) , push them into a stack, and later pop out to clipboard again. If you tried AutoHotKey,this is what "ClipboardAll" in it will do.
Problem presents when I tried to get the data, this is How I write for Pinvoke:
[DllImport("user32.dll", SetLastError = true)]
public static extern bool OpenClipboard(IntPtr hWndNewOwner);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool CloseClipboard();
[DllImport("user32.dll")]
public static extern IntPtr GetClipboardData(uint uFormat);
[DllImport("user32.dll", SetLastError = true)]
public static extern uint EnumClipboardFormats(uint format);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GlobalLock(IntPtr hMem);
[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GlobalUnlock(IntPtr hMem);
[DllImport("kernel32.dll")]
public static extern UIntPtr GlobalSize(IntPtr hMem);
And this is how I use them:
var x = GetFormats(); // a list returned from EnumClipboardFormats
foreach (uint format in x)
{
IntPtr p = NativeMethods.GetClipboardData(format);
int length = (int) NativeMethods.GlobalSize(p);
IntPtr memPtr = NativeMethods.GlobalLock(p);
byte[] buffer = new byte[length];
Marshal.Copy(memPtr, buffer, 0, length);
NativeMethods.GlobalFree(p);
dataObject.Data[format] = buffer;//My data object
}
WinApi.CloseClipBoard();
return dataObject;
Then when I copy something in Microsoft Office Excel , I got: A Heap corrupted Exception at "GlobalSize" Method.
And after I tried to skip the format that triggered the Exception:
if(format==14||format==2) continue;
then everything worked fine.
The format 2 repsents CF_BITMAP and format 14 is CF_ENHMETAFILE, I guess they may use so-called "delay rendering" technology in clipboard, that is to say their data were null when first created and were filled when someone tried to get them, I wonder if the handle of data will change when rendering invoke, but I'm not sure.
So is there anyone can help, to find out the reason, and tell me how to fix.