2016-10-28 51 views
3

我正在开发与Windows剪贴板相关的C#应用​​程序。由于在Dot Net剪贴板库(STA,无法打开剪贴板等)中存在许多缺点,我决定直接使用系统API。使用P时调用堆损坏GlobalSize

我想要做的是每种格式的备份数据(尽可能多,如果不是全部),将它们推入堆栈,然后再弹出到剪贴板。如果您尝试使用AutoHotKey,那么它会执行“ClipboardAll”。

问题提出时,我试图获取数据,我这是怎么写的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); 

这就是我如何使用它们:

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; 

然后当我复制的东西在微软Office Excel中,我得到: A Heap corrupted Exception at "GlobalSize" Method.

而我试图跳过触发例外的格式:

if(format==14||format==2) continue; 

然后一切正常。

格式2表示CF_BITMAP,格式14是CF_ENHMETAFILE,我想他们可能会在剪贴板中使用所谓的“延迟渲染”技术,也就是说他们的数据在第一次创建时是空的,而当有人试图获得他们,我想知道渲染调用时数据的句柄是否会改变,但我不确定。

所以,有没有人可以帮助,找出原因,并告诉我如何解决。

+0

http://www.olivierlanglois.net/metafile-clipboard.html – stuartd

+0

该代码在23年前停止工作。您必须使用IDataObject来访问剪贴板数据。 –

回答

2

从文档:

剪贴板控制手柄的GetClipboardData函数返回,而不是应用程序。应用程序应立即复制数据。应用程序不能释放手柄,也不能将其锁定。在调用EmptyClipboard或CloseClipboard函数后,或者在使用相同剪贴板格式调用SetClipboardData函数后,应用程序不得使用句柄。

您不遵守这些规则。而不是解锁你释放手柄。不要释放手柄,解锁它。

根本不执行任何错误检查。所以也许一些API调用失败,你不知道。也许GetClipboardData返回NULL。你怎么知道的?始终检查错误状况的返回值。

您的程序中可能存在其他错误,您尚未显示所有代码。例如,我们无法看到您打开剪贴板的位置。

+0

谢谢。我有同样的问题。使用'GlobalUnlock'而不是'GlobalFree'取得了诀窍。 –