需求
幾年前,好聲音以獨特節目形式吸引了很多選手和觀眾的 觀注,旨在"只尋找優質聲音"; 可聲音各有特色時,還得看顏值,當然這也無可厚非。雖然扯得有點遠,我想表達的是軟件開發的穩定性與美觀性之間的平衡問題,亦或是功能需求與用戶體驗關系把握問題。有人認為只是功能強大,滿足需求,界面是次要的;而實際結果,功能也並不強大,界面操作也十分復雜;我個人觀點正好相反,如果我們的軟件並不能達到功能強大,運行穩定,我們更得加強界面的開發,正確地引導用戶,減少出錯機率。
下面是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 { /// <summary> /// IPictureDisp轉Bitmap /// </summary> /// <param name="ipd">IPictureDisp</param> /// <returns>Bitmap</returns> 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