想從其他應用程式提取精美圖示?本文以自製工具「輕輕鬆鬆抓圖示」為例,完整示範如何擷取各類檔案(ICO、BMP、EXE、DLL、ICL)中的圖示資源,並儲存為 ICO 或 BMP 格式。核心封裝為 CIcons 與 CDib 兩大類別(四個檔案:Icons.h/cpp、Dib.h/cpp),專案加入即可直接呼叫。

void CIconSnapDlg::OnOK() {
CFileDialog fileDialog(TRUE, _T("*.ICO"), NULL, NULL,
_T("資源檔(*.ICO,*.BMP,*.EXE,*.DLL,*.ICL)|*.ICO;*.BMP;*.EXE;*.DLL;*.ICL||"));
if (fileDialog.DoModal() == IDOK) {
szOpenFileName = fileDialog.GetPathName();
szOpenFileExtName = fileDialog.GetFileExt(); szOpenFileExtName.MakeLower();
m_List.ResetContent();
if (szOpenFileExtName == _T("ico")) { // ICO 檔
lpIR = pIcons->ReadIconFromICOFile(szOpenFileName);
HICON hIcon = ExtractIcon(AfxGetInstanceHandle(), szOpenFileName, 0);
if (hIcon) m_List.AddString(szOpenFileName);
((CStatic*)GetDlgItem(IDC_ICONS))->SetIcon(hIcon);
}
else if (szOpenFileExtName == _T("bmp")) { // BMP 檔
pIcons->IconImageFromBMPFile(szOpenFileName, &lpIR->IconImages[0], TRUE);
HICON hIcon = pIcons->MakeIconFromResource(&lpIR->IconImages[0]);
if (hIcon) m_List.AddString(szOpenFileName);
((CStatic*)GetDlgItem(IDC_ICONS))->SetIcon(hIcon);
}
else { // EXE/DLL/ICL 資源檔
HINSTANCE hLibrary = LoadLibraryEx(szOpenFileName, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (!hLibrary) { MessageBox(_T("載入失敗,需為 Win32 檔案!")); return; }
EDII.szFileName = szOpenFileName; EDII.hInstance = hLibrary;
if (!EnumResourceNames(EDII.hInstance, RT_GROUP_ICON, (ENUMRESNAMEPROC)MyEnumProcedure, (LPARAM)GetSafeHwnd()))
{ MessageBox(_T("列舉圖示資源失敗!")); return; }
}
m_List.SetCurSel(0);
if (m_List.GetCount() == 0) { MessageBox(_T("無圖示資源!")); m_Copy.EnableWindow(FALSE); m_SaveAs.EnableWindow(FALSE); return; }
m_Copy.EnableWindow(TRUE); m_SaveAs.EnableWindow(TRUE);
InvalidateRect(NULL, TRUE); // 觸發 OnPaint 顯示
}
}
LPTSTR lpIconID; HICON hIcon;
if ((lpIconID = (LPTSTR)m_List.GetItemData(m_List.GetCurSel())) != (LPTSTR)LB_ERR) {
if (szOpenFileExtName == _T("exe") || szOpenFileExtName == _T("dll") || szOpenFileExtName == _T("icl")) {
hIcon = pIcons->GetIconFromInstance(EDII.hInstance, lpIconID);
((CStatic*)GetDlgItem(IDC_ICONS))->SetIcon(hIcon);
}
}
void CIconSnapDlg::OnButtonSaveas() {
LPTSTR lpIconID;
CFileDialog fileDialog(FALSE, _T("*.ICO"), NULL, NULL, _T("圖示檔(*.ICO)|*.ICO|位圖檔(*.BMP)|*.BMP||"));
if (fileDialog.DoModal() == IDOK) {
szSaveFileName = fileDialog.GetPathName();
szSaveFileExtName = fileDialog.GetFileExt(); szSaveFileExtName.MakeLower();
if (szOpenFileExtName == _T("exe") || szOpenFileExtName == _T("dll") || szOpenFileExtName == _T("icl"))
if ((lpIconID = (LPTSTR)m_List.GetItemData(m_List.GetCurSel())) != (LPTSTR)LB_ERR)
lpIR = pIcons->ReadIconFromEXEFile(szOpenFileName, lpIconID);
if (szSaveFileExtName == _T("bmp")) {
if (lpIR && m_List.GetCount() > 0) { BeginWaitCursor(); pIcons->IconImageToBMPFile(szSaveFileName, &lpIR->IconImages[0]); EndWaitCursor(); }
else MessageBox(_T("無可儲存資源!"));
}
else if (szSaveFileExtName == _T("ico")) {
if (lpIR && m_List.GetCount() > 0) { BeginWaitCursor(); pIcons->WriteIconToICOFile(lpIR, szSaveFileName); EndWaitCursor(); }
else MessageBox(_T("無可儲存資源!"));
}
}
}
核心 API:LoadLibraryEx(LOAD_LIBRARY_AS_DATAFILE) 載入資源模組、EnumResourceNames 列舉群組圖示、CIcons 類別封裝讀寫轉換邏輯。完整原始碼可整合至專案直接使用。