为什么我从Clipboard类中获取OutOfMemoryException?

时间:2018-12-19 17:29:33

标签: c# wpf windows

我正在尝试使用System.Windows.Clipboard类从剪贴板中获取图像:

var bitmapSource = System.Windows.Clipboard.GetImage();

通过PrintScreen键复制图像时,它可以正常工作。但是,从医疗应用程序复制图像时,出现以下异常:

System.OutOfMemoryException: Insufficient memory to continue the execution of the program.
   at System.Runtime.InteropServices.ComTypes.IDataObject.GetData(FORMATETC& format, STGMEDIUM& medium)
   at System.Windows.DataObject.OleConverter.GetDataInner(FORMATETC& formatetc, STGMEDIUM& medium)
   at System.Windows.DataObject.OleConverter.GetDataFromOleOther(String format, DVASPECT aspect, Int32 index)
   at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert, DVASPECT aspect, Int32 index)
   at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert)

图像可以在Paint和Word上很好地粘贴,因此图像已正确复制到剪贴板。这不是一个很大的图像,所以我绝对不会用完内存。有什么想法吗?

呼叫Clipboard.GetDataObject().GetFormats()返回以下信息:

{string[11]}
    [0]: "Rich Text Format"
    [1]: "MetaFilePict"
    [2]: "PNG+Office Art"
    [3]: "Office Drawing Shape Format"
    [4]: "DeviceIndependentBitmap"
    [5]: "Bitmap"
    [6]: "System.Drawing.Bitmap"
    [7]: "System.Windows.Media.Imaging.BitmapSource"
    [8]: "Format17"
    [9]: "EnhancedMetafile"
    [10]: "System.Drawing.Imaging.Metafile"

我尝试了以上每种格式的Clipboard.GetData(format),唯一返回非空对象的格式是“ PNG + Office Art”,“ Office Drawing Shape Format”,“ Format17”和“ EnhancedMetafile” “。

1 个答案:

答案 0 :(得分:1)

我相信您的答案是here。简而言之:

  

结论是,如果您正在WPF中使用剪贴板并且正在获得似乎没有任何意义的System.OutOfMemoryExceptions,那么您可能已经忘记了将SerializableAttribute添加到放置在剪贴板。

那么您是该医疗应用程序吗?因为似乎是问题在于如何将图像放置在剪贴板中,而不是如何检索图像。

更新:由于它不是您的应用程序,因此您可能不得不忍受他们的错误(或Clipboard.GetData()中的错误)。 The source code of Clipboard.GetImage()是这样:

public static Image GetImage() {
    var dataObject = Clipboard.GetDataObject();
    if (dataObject != null) {
        return dataObject.GetData(DataFormats.Bitmap, true) as Image;
    }

    return null;
}

请注意,您的堆栈跟踪显示该异常发生在GetData()中。查看源代码,这意味着对GetDataObject()的调用有效,这意味着您(理论上)可以自己使用GetDataObject()并将IDataObject转换为可以使用的内容。< / p>

可能需要进行一些探索才能弄清楚发生了什么。您也许可以使用IDataObject.GetFormats()来检查它的内容,然后使用IDataObject.GetData()来获取该格式的数据。

更新2: here的解决方案为我们指明了正确的方向,但需要进行一些修改:

var data = Clipboard.GetDataObject();
var ms = (MemoryStream) data.GetData("PNG+Office Art");

var image = Image.FromStream(ms)