當你在其他應用程式中發現精美的圖標想加以利用時,該如何提取並保存?市面上雖有現成的圖標提取工具,但若能理解其底層運作原理,甚至親手打造專屬的提取工具,將更具彈性與掌控感。本文將帶你深入探討圖標資源的提取技術,並示範如何以 MFC 封裝可重用的類別,實現從 EXE、DLL、ICL 等檔案中擷取圖標,並支援儲存為 ICO 與 BMP 兩種格式。
範例程式整合出兩個核心類別:CIcons 負責圖標資源的讀取、列舉與格式轉換;CDib 則處理裝置無關位圖(DIB)的操作與顯示。兩者分別由 Icons.h/.cpp 與 Dib.h/.cpp 四個檔案組成,直接加入專案即可調用,快速建立自訂的圖標管理工具。
利用 CFileDialog 開啟對話方塊,支援 *.ICO;*.BMP;*.EXE;*.DLL;*.ICL 等濾鏡。取得路徑後,先將副檔名轉為小寫,便於後續分流處理:
CFileDialog fileDialog(TRUE, _T("*.ICO"), NULL, NULL,
_T("資源檔案(*.ICO,*.BMP,*.EXE,*.DLL,*.ICL)|*.ICO;*.BMP;*.EXE;*.DLL;*.ICL||"));
if (fileDialog.DoModal() == IDOK) {
CString szOpenFileName = fileDialog.GetPathName();
CString szOpenFileExtName = fileDialog.GetFileExt();
szOpenFileExtName.MakeLower();
// ...
}
CIcons::ReadIconFromICOFile() 解析檔案結構,並以 ExtractIcon() 取得 HICON 句柄。FindResource()、LoadResource() 等 API 定位 RT_GROUP_ICON 與 RT_ICON,再組合成完整圖標物件。CDib 載入後轉換為圖標資源。清空舊有列表內容(m_List.ResetContent()),逐一將解析出的圖標以圖示模式加入 CListBox,並保存對應的資源索引或檔案路徑作為項目資料,方便後續另存新檔或預覽。
掌握核心類別後,你可以輕鬆擴充功能:
CIcons::SaveAsICO() 或 SaveAsBMP() 一鍵輸出。CDib 的縮放與調色盤操作,產出 16×16、32×32、48×48 等多種規範尺寸。BeginUpdateResource() 等 API,實現圖標的替換、新增與刪除。if (szOpenFileExtName == _T("ico")) {
LPICONRESOURCE lpIR = pIcons->ReadIconFromICOFile(szOpenFileName);
HICON hIcon = ExtractIcon(AfxGetInstanceHandle(), szOpenFileName, 0);
if (hIcon != NULL) {
m_List.AddString(szOpenFileName); // 此處可改為 owner-draw 顯示縮圖
// 將 hIcon 暫存至項目資料,供後續另存使用
}
}
透過封裝 CIcons 與 CDib,開發者得以脫離繁雜的 Win32 資源 API,專注於上層邏輯與介面設計。無論是開發獨立圖標管理工具,還是整合至既有專案作為資源瀏覽模組,這套架構都能提供穩健、可擴充的基礎。

圖一:程式執行介面,左側列出提取的圖標資源