提取Office图标的方法
阅读原文时间:2023年07月14日阅读:1

需求

几年前,好声音以独特节目形式吸引了很多选手和观众的 观注,旨在"只寻找优质声音"; 可声音各有特色时,还得看颜值,当然这也无可厚非。虽然扯得有点远,我想表达的是软件开发的稳定性与美观性之间的平衡问题,亦或是功能需求与用户体验关系把握问题。有人认为只是功能强大,满足需求,界面是次要的;而实际结果,功能也并不强大,界面操作也十分复杂;我个人观点正好相反,如果我们的软件并不能达到功能强大,运行稳定,我们更得加强界面的开发,正确地引导用户,减少出错机率。

下面是Excel 2019 的界面,引领着整个行业的界面风格:

现在需要将其图标提取怎么操作?

实现

通过一些图标提取软件都无法提取,唯一可以使用的方法是调有官方的GetImageMso方法。

开发环境:VS2019+VSTO,以Excel为例。

首先新建一个Add In工程:

其次,在ThisAddIn类里创建一个Application对象,以便全局访问。

public static Excel.Application App;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
App = this.Application;
}

然后,添加一个Ribbon,并新增按键及相关事件。

接着,使用GetImageMso方法下载相应名称、大小的图片。

IPictureDisp pictureDisp = ThisAddIn.App.CommandBars.GetImageMso(name, 32, 32);

最后,将IPictureDisp转化透明图标输出,这是第二个关键点:

public class ImageHelper
{
///

/// IPictureDisp转Bitmap ///
/// IPictureDisp
/// Bitmap
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 int bmType;  
        public int bmWidth;  
        public int bmHeight;  
        public int bmWidthBytes;  
        public short bmPlanes;  
        public short bmBitsPixel;  
        public IntPtr bmBits;  
    }

    \[StructLayout(LayoutKind.Sequential)\]  
    public struct BITMAPINFOHEADER  
    {  
        public int biSize;  
        public int biWidth;  
        public int biHeight;  
        public short biPlanes;  
        public short 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);  

}

成果

Word图标:

Excel图标:

PowerPoint图标:

Project图标:

Visio 图标:

打包图片资源下载:

https://download.csdn.net/download/ADKIIDGTFK926/12078303

参考

https://blog.csdn.net/blackwoodcliff/article/details/89891405

https://github.com/OfficeDev/office-fluent-ui-command-identifiers