如何从 Microsoft Office 2007 中保存 ImageMSO 图标?

Posted

技术标签:

【中文标题】如何从 Microsoft Office 2007 中保存 ImageMSO 图标?【英文标题】:How to save ImageMSO icon from Microsoft Office 2007? 【发布时间】:2010-11-07 13:59:10 【问题描述】:

我从 Microsoft Office 2007 中找到了很多不错的图标。您知道使用 VBA 将所有图标提取并保存为 PNG 文件吗?

Partial ImageMSO http://rabu4g.bay.livefilestore.com/y1p2SF1q63YjDjPNmK4nYMW2644r9AO2aAsE__vBYznTeXD0b4SJUU0O07fxPD0r7aO_83gCJ-8OfcOQsFKG0fQMRnTEneBU1TI/Capture.PNG

以下代码是用于从 ImageMSO 获取图像的代码。

Application.CommandBars.GetImageMso([name], [width], [height])

我可以将所有内容显示为 PictureBox 控件并将 excel 文件保存为网页。但是,每个图标的质量都很低。

此外,我尝试使用以下代码创建用于导出为位图对象的 C# Excel 插件项目。但是我发现它不能导出为半透明的PNG。

stdole.IPictureDisp p = Application.CommandBars.GetImageMso(fileName, size, size);
Bitmap b = Bitmap.FromHbitmap((IntPtr)p.Handle, (IntPtr)p.hPal);

PS。我想将所有图标保存为 PNG 格式,因为我需要使用它的半透明功能。它允许我在大多数背景颜色上使用所有图标而不是白色背景。

【问题讨论】:

@Soul_Master 提取成功了吗? 不。我只是放弃了。 【参考方案1】:

所有的PNG文件都可以在here找到这些都是PNG格式的。好编程! (还提供了一个不错的 ZIP 存档Here)ZIP 存档包含所有 17 个 Excel 图标。

当您使用 GetImageMso 方法时,您最终会得到对象的 IPicture 接口。 IPicture 界面访问适合以原始格式保存到文件的图标 - .ICO、.WMF 或 .BMP 不支持 PNG 格式。以下链接解释了为什么这不能直接实现:

http://msdn.microsoft.com/en-us/library/aa434604.aspx(msoGetImageMso 方法) http://msdn.microsoft.com/en-us/library/ms680761%28VS.85%29.aspx(IP图片接口) http://msdn.microsoft.com/en-us/library/ms694504%28VS.85%29.aspx(另存为文件方法)

但是,使用更复杂的方法会产生您想要的结果:

http://blogs.msdn.com/mshneer/archive/2007/10/10/preserving-transparency-when-rendering-office-icons.aspx

【讨论】:

【参考方案2】:

我已经封装了一个 C# 实用程序类,用于将 Office2007 画廊图标提取到 .png 文件,同时正确地保持它们的透明度。主要代码取自 Andrew Whitechapel 写的一篇很棒的文章( http://blogs.msdn.com/b/andreww/archive/2007/10/10/preserving-the-alpha-channel-when-converting-images.aspx)。我已将它与 Office 2007 示例图标表集成,以防您要将所有这些图标提取到目标文件夹。

步骤是:

1) 在http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=11675下载Office Gallery 电子表格

2) 使用 Office2007IconsGallery.xlsm 示例电子表格的位置以及您想要提取图标的目标文件夹调用 OfficeIcons.ExtractAllIcons()。

代码

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Xml.Linq;
using ExcelDna.Integration;
using ICSharpCode.SharpZipLib.Zip;
using Microsoft.Office.Interop.Excel;
using stdole;

public class OfficeIconUtils

    public static void ExtractAllIcons(string xlsmPath, string targetFolder)
    
        // extract  customUI.xml
        var zf = new ZipFile(xlsmPath);
        var entry = zf.GetEntry("customUI/customUI.xml");
        var zipStream = zf.GetInputStream(entry);
        XNamespace ns = "http://schemas.microsoft.com/office/2006/01/customui";
        var root = XElement.Load(zipStream);
        foreach (var gallery in root.Descendants(ns + "gallery"))
        
            //create a sub-folder for the gallery
            var subFolder = Path.Combine(targetFolder, 
                gallery.Attribute("label").Value);
            var width = int.Parse(gallery.Attribute("itemWidth").Value);
            var height = int.Parse(gallery.Attribute("itemHeight").Value);
            Directory.CreateDirectory(subFolder);
            foreach (var item in gallery.Descendants(ns + "item"))
            
                SaveIcon(item.Attribute("imageMso").Value, 
                    subFolder, width, height);
            
        
    

    public static void SaveIcon(string msoName, string folder, 
        int width = 32, int height = 32)
    
        ConvertPixelByPixel(
            ((Application)(ExcelDnaUtil.Application))
                .CommandBars.GetImageMso(msoName, width, height))
            .Save(Path.Combine(folder, string.Format("0.png", 
            msoName)), ImageFormat.Png);
    


    public static Bitmap ConvertPixelByPixel(IPictureDisp ipd)
    
        // get the info about the HBITMAP inside the IPictureDisp
        var dibsection = new DIBSECTION();
        GetObjectDIBSection((IntPtr)ipd.Handle, Marshal.SizeOf(dibsection), ref dibsection);
        var width = dibsection.dsBm.bmWidth;
        var height = dibsection.dsBm.bmHeight;

        // create the destination Bitmap object
        var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);

        unsafe
        
            // get a pointer to the raw bits
            var pBits = (RGBQUAD*)(void*)dibsection.dsBm.bmBits;

            // copy each pixel manually
            for (var x = 0; x < dibsection.dsBmih.biWidth; x++)
                for (var y = 0; y < dibsection.dsBmih.biHeight; y++)
                
                    var offset = y * dibsection.dsBmih.biWidth + x;
                    if (pBits[offset].rgbReserved != 0)
                    
                        bitmap.SetPixel(x, y, Color.FromArgb(pBits[offset].rgbReserved, pBits[offset].rgbRed, pBits[offset].rgbGreen, pBits[offset].rgbBlue));
                    
                
        

        return bitmap;
    

    [StructLayout(LayoutKind.Sequential)]
    private struct RGBQUAD
    
        public byte rgbBlue;
        public byte rgbGreen;
        public byte rgbRed;
        public byte rgbReserved;
    

    [StructLayout(LayoutKind.Sequential)]
    public struct BITMAP
    
        public Int32 bmType;
        public Int32 bmWidth;
        public Int32 bmHeight;
        public Int32 bmWidthBytes;
        public Int16 bmPlanes;
        public Int16 bmBitsPixel;
        public IntPtr bmBits;
    

    [StructLayout(LayoutKind.Sequential)]
    public struct BITMAPINFOHEADER
    
        public int biSize;
        public int biWidth;
        public int biHeight;
        public Int16 biPlanes;
        public Int16 biBitCount;
        public int biCompression;
        public int biSizeImage;
        public int biXPelsPerMeter;
        public int biYPelsPerMeter;
        public int biClrUsed;
        public int bitClrImportant;
    

    [StructLayout(LayoutKind.Sequential)]
    public struct DIBSECTION
    
        public BITMAP dsBm;
        public BITMAPINFOHEADER dsBmih;
        public int dsBitField1;
        public int dsBitField2;
        public int dsBitField3;
        public IntPtr dshSection;
        public int dsOffset;
    

    [DllImport("gdi32.dll", EntryPoint = "GetObject")]
    public static extern int GetObjectDIBSection(IntPtr hObject, int nCount, ref DIBSECTION lpObject);


代码

【讨论】:

如果您指定了它所依赖的 500 个依赖项,那就太好了,更不用说一旦找到它们,所有代码都无法编译。 添加了参考,对此感到抱歉。它肯定可以编译 -【参考方案3】:

我已经尝试过 Ismail 的回答,效果很好。然而,我花了一段时间才弄清楚如何让它工作。我可能会分享这点知识:

该解决方案需要来自 codeplex 的 ExcelDna:link。

由于我使用的是Net 4.0,我没有 .zip 支持,所以我首先将 .xslm 文件解压缩到一个平面目录结构,然后我将代码更改为直接从文件中读取。 然后在 Excel 中,我将 ExcelDna 扩展方法称为

=ExtractIcons("Office2207IconsGallery";"folder_where_to_store_icons")

实用程序类的 using 语句(对我而言):

using System.Xml.Linq;

using System.IO;

using System.Drawing;

using System.Runtime.InteropServices;

using System.Drawing.Imaging;

using Application = Microsoft.Office.Interop.Excel.Application;

using ExcelDna.Integration;

using stdole;

希望这会有所帮助....谢谢伊斯梅尔!

【讨论】:

【参考方案4】:

我在 Excel 开发中经常使用 ImageMso。偶然发现这篇文章后,我更进一步,将一个包放在一起,以直观地搜索、提取和保存 Microsoft Excel 中的图标作为文件或复制和粘贴(具有 alpha 通道透明度)到另一个应用程序。我还从各种来源编制了一份包含 8,899 个不同 ImageMso 名称的列表。我希望其他人会发现这很有用。

Microsoft Office Icons (ImageMSO) Gallery & Extraction

【讨论】:

我能够在 Windows 8 上将加载项加载到我的 Excel 2013。但“插入”选项卡中没有新的组/命令。 我使用的是 32 位版本的 Excel 2013。加载此插件后没有任何反应。 在 Win7 上的 Excel 2010 32 位中非常适合我!谢谢! 我发布了一个包含多项优化的更新。我附上了在 Windows 8 上在 Microsoft Excel 2013 中运行的画廊的屏幕截图。我希望​​这可以解决您的问题,如果没有,也许我可以为您获取 PNG 文件。最值得注意的是,现在有 8,899 个 ImageMSO 名称来自寻找其他来源。 不确定我是不是盲人,但我看不到你从哪里下载插件。该站点仅包含带有源代码的“存档”。

以上是关于如何从 Microsoft Office 2007 中保存 ImageMSO 图标?的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft Office Communicator Automation API 2007 和接收即时消息

microsoft office Enterprise 2007在安装过程中出错怎么办?

Microsoft office Enterprise 2007安装错误。。这怎么办???

怎么对Microsoft (Office) Word Document 2007 索引化?

Microsoft office2007 ppt如何设置手动播放和自动播放

如何破解office2007学生版