Windows 提供兩種主要方式取得檔案關聯圖示:
// 介面:Button + Image + OpenDialog
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if (OpenDialog1->Execute())
{
AnsiString file = OpenDialog1->FileName;
HICON hIcon = ExtractIcon(Handle, file.c_str(), 0); // 索引 0 = 第一個圖示
if (hIcon)
{
TIcon *icon = new TIcon();
icon->Handle = hIcon;
AnsiString tmp = "temp.ico";
icon->SaveToFile(tmp); // 儲存暫存檔
Image1->Picture->LoadFromFile(tmp); // 載入 TImage
delete icon;
DeleteFile(tmp);
}
}
}
ExtractIcon(hInst, lpszExeFileName, nIconIndex):nIconIndex=-1 回傳圖示總數
#include
#pragma comment(lib, "shell32.lib")
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if (OpenDialog1->Execute())
{
AnsiString file = OpenDialog1->FileName;
SHFILEINFO sfi = {0};
// 取得大圖示 (32x32)
HIMAGELIST hImg = (HIMAGELIST)SHGetFileInfo(
file.c_str(), 0, &sfi, sizeof(sfi),
SHGFI_ICON | SHGFI_LARGEICON | SHGFI_SYSICONINDEX
);
if (sfi.hIcon)
{
TIcon *icon = new TIcon();
icon->Handle = sfi.hIcon;
AnsiString tmp = "temp.ico";
icon->SaveToFile(tmp);
Image1->Picture->LoadFromFile(tmp);
delete icon;
// 圖示屬系統映像清單,不可 DestroyIcon,若自行複製則需 DestroyIcon
}
}
}
| 旗標 | 用途 |
|---|---|
SHGFI_ICON | 取得圖示控制代碼 |
SHGFI_LARGEICON | 32x32 (預設小圖示 16x16) |
SHGFI_SMALLICON | 16x16 |
SHGFI_SYSICONINDEX | 回傳系統映像清單索引 (sfi.iIcon),可搭配 ImageList_GetIcon |
SHGFI_USEFILEATTRIBUTES | 檔案不存在時,依屬性模擬 (如僅有副檔名) |
SHGFI_TYPENAME | 取得類型名稱 (sfi.szTypeName,如 "Text Document") |
SHGFI_DISPLAYNAME | 取得顯示名稱 (sfi.szDisplayName) |
// 取得系統映像清單控制代碼
HIMAGELIST hSysImg = (HIMAGELIST)SHGetFileInfo(
"C:\\", 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
// 直接從映像清單繪製/取得圖示
HICON hIcon = ImageList_GetIcon(hSysImg, sfi.iIcon, ILD_TRANSPARENT);
// 繪製至 Canvas
ImageList_Draw(hSysImg, sfi.iIcon, Canvas->Handle, x, y, ILD_TRANSPARENT);
SHGetFileInfo 呼叫、暫存檔 I/O需可執行檔內建圖示用 ExtractIcon;需**完整 Shell 關聯圖示** (含文件、捷徑、資料夾) 必用 SHGetFileInfo。現代 UI 開發建議直接操作系統映像清單,效能與視覺一致性最佳。