Word Interop - 将嵌入式形状保存为图像

问题描述 投票:1回答:1

我正试图保存一个嵌入的 形状 作为一个图像使用C#。

如果对象是嵌入作为一个实际的图像(WMFJPEG),我可以检索图像没有问题,但当对象是一个嵌入式形状或OLE对象,显示在Word中的图像,我似乎不能提取或检索所述对象,然后要么复制到剪贴板或保存所述图像。

这是我当前的代码示例;要么对象是空的,要么我得到以下错误。

System.Runtime.InteropServices.ExternalException: 'A generic error occurred in GDI+.'

任何帮助是感激的。谢谢你的帮助。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace ImageMagickSandboxWinForms
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        public static BitmapSource ConvertBitmap(Bitmap source)
        {
            return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                          source.GetHbitmap(),
                          IntPtr.Zero,
                          Int32Rect.Empty,
                          BitmapSizeOptions.FromEmptyOptions());
        }

        public static Bitmap BitmapFromSource(BitmapSource bitmapsource)
        {
            Bitmap bitmap;
            using (var outStream = new MemoryStream())
            {
                BitmapEncoder enc = new BmpBitmapEncoder();
                enc.Frames.Add(BitmapFrame.Create(bitmapsource));
                enc.Save(outStream);
                bitmap = new Bitmap(outStream);
            }
            return bitmap;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string physicsDocLocation = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));
            physicsDocLocation += @"\[Doc path Here].docx";
            var wordApp = new Microsoft.Office.Interop.Word.Application();

            var wordDoc = wordApp.Documents.Open(physicsDocLocation);
            int iCount = wordDoc.InlineShapes.Count;
            for (int i = 1; i < (wordDoc.InlineShapes.Count + 1); i++)
            {
                var currentInlineShape = wordDoc.InlineShapes[i];
                currentInlineShape.Range.Select();
                wordDoc.ActiveWindow.Selection.Range.Copy();
                BitmapSource clipBoardImage = System.Windows.Clipboard.GetImage();
                Bitmap bmpClipImage = BitmapFromSource(clipBoardImage);
                string finalPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), @"TestConversions");
                finalPath += @"\" + Guid.NewGuid().ToString() + ".jpg";
                using (MemoryStream memory = new MemoryStream())
                {
                    using (FileStream fs = new FileStream(finalPath, FileMode.Create, FileAccess.ReadWrite))
                    {
                        bmpClipImage.Save(memory, ImageFormat.Jpeg); <<<---- Error happens here.
                        byte[] bytes = memory.ToArray();
                        fs.Write(bytes, 0, bytes.Length);
                    }
                }
            }
            wordDoc.Close();
            wordApp.Quit();
        }
    }
}
c# ms-word office-interop data-conversion
1个回答
0
投票

我有这些代码在我的图书馆,不知道我在哪里找到的,但希望你为你做的工作:我使用Clippboard捕捉不同的图像,Jus t dont forget,线程是需要访问剪贴板。

       for (var i = 1; i <= wordApplication.ActiveDocument.InlineShapes.Count; i++)
        {

            var inlineShapeId = i; 


            var thread = new Thread(() => SaveInlineShapeToFile(inlineShapeId, wordApplication));

            // STA is needed in order to access the clipboard
            // https://stackoverflow.com/a/518724/700926
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            thread.Join();
        }

   // General idea is based on: https://stackoverflow.com/a/7937590/700926
    protected static void SaveInlineShapeToFile(int inlineShapeId, Application wordApplication)
    {
        // Get the shape, select, and copy it to the clipboard
        var inlineShape = wordApplication.ActiveDocument.InlineShapes[inlineShapeId];
        inlineShape.Select();
        wordApplication.Selection.Copy();

        // Check data is in the clipboard
        if (Clipboard.GetDataObject() != null)
        {
            var data = Clipboard.GetDataObject();

            // Check if the data conforms to a bitmap format
            if (data != null && data.GetDataPresent(DataFormats.Bitmap))
            {
                // Fetch the image and convert it to a Bitmap
                var image = (Image) data.GetData(DataFormats.Bitmap, true);
                var currentBitmap = new Bitmap(image);

                // Save the bitmap to a file
                currentBitmap.Save(@"C:\Users\Username\Documents\" + String.Format("img_{0}.png", inlineShapeId));
            }
        }
    }

如果你使用的是Winform或WPF,剪贴板对图像的作用是不同的。

if (Clipboard.ContainsImage())
{
// ImageUIElement.Source = Clipboard.GetImage(); // does not work
    System.Windows.Forms.IDataObject clipboardData = System.Windows.Forms.Clipboard.GetDataObject();
  if (clipboardData != null)
  {
    if (clipboardData.GetDataPresent(System.Windows.Forms.DataFormats.Bitmap))
    {
        System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)clipboardData.GetData(System.Windows.Forms.DataFormats.Bitmap);
        ImageUIElement.Source =  System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,BitmapSizeOptions.FromEmptyOptions());
        Console.WriteLine("Clipboard copied to UIElement");
    }
  }
}

如果由于格式翻译中的一个错误而导致其无法正常工作,那么在剪贴板上会出现以下情况。解决办法 . 因此,它不常见,但它很容易理解使用 "DeviceIndependentBitmap "的逻辑。

© www.soinside.com 2019 - 2024. All rights reserved.