2016-10-28 19 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'取得了訣竅。 –