无法从剪贴板检索图像



我试图将excel文件中的单元格范围保存到图片中。我使用了interop.exel api中的CopyPicture方法,所以图片应该在剪贴板上。例如,当我在word文档上按ctrl+v时,我会得到图片,但我无法用代码成功地得到它。GetImageFromClipBoard方法返回的数据为null。

public void SaveAsImage()
{
var usedRange = ws.UsedRange;
int startRow = usedRange.Row;
int endRow = startRow + usedRange.Rows.Count - 1;
int startColumn = usedRange.Column;
int endColumn = startColumn + usedRange.Columns.Count - 1; 
Xl.Range rng = wb.ActiveSheet.Range[ws.Cells[1, 1], 
ws.Cells[endRow, endColumn]];
rng.CopyPicture(Xl.XlPictureAppearance.xlScreen, 
Xl.XlCopyPictureFormat.xlBitmap);
Image image = GetImageFromClipBoard();
image.Save("image.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
[STAThread]
private Image GetImageFromClipBoard()
{
IDataObject clipboardData = Clipboard.GetDataObject();
Exception threadEx = null;
Thread staThread = new Thread(
delegate ()
{
try
{
clipboardData = Clipboard.GetDataObject();
}
catch (Exception ex)
{
threadEx = ex;
}
});
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
staThread.Join();
return (Bitmap)clipboardData.GetData(DataFormats.Bitmap);
}

您要做的是从剪贴板中检索位图,类型为"位图"。不过,我不确定Office是否使用那种类型。

注意,DataFormats不是枚举;它们只是指通常用于剪贴板内容的字符串ID。这立即意味着您可以添加自定义的。这些自定义的通常作为字节流放在剪贴板上。这个答案详细说明了在剪贴板上存储和获取这些字节数组的方法。

使用的主要文件之一是DIB(基本上是一个没有特定文件头的BMP文件),但Office特别使用这些:

  • "PNG+Office Art"
  • "JFIF+Office Art"
  • "GIF+Office Art"
  • "PNG"
  • "JFIF"
  • "GIF"

(我听说"+Office Art"也只是图像,但我自己还没有尝试过)

所以,是的,如果你试图获取这些,用剪贴板中的字节创建一个新的MemoryStream,并从MemoryStream中创建一个新Bitmap,你应该在那里。你基本上会尝试它们,直到你得到一些粘在一起的东西,从PNG开始。

不久前,我用完整的代码写了一个更详细的解释,重点是在剪贴板上复制和检索PNG和DIB。