通過 P/Invoke 調用 shell32.dll 獲取文件圖標、顯示名、類型名等信息。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SHFILEINFO
{
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
}
[Flags]
public enum SHGFI : uint
{
ICON = 0x100, DISPLAYNAME = 0x200, TYPENAME = 0x400,
ATTRIBUTES = 0x800, ICONLOCATION = 0x1000,
EXETYPE = 0x2000, SYSICONINDEX = 0x4000,
LINKOVERLAY = 0x8000, SELECTED = 0x10000,
ATTR_SPECIFIED = 0x20000, LARGEICON = 0x0,
SMALLICON = 0x1, OPENICON = 0x2, SHELLICONSIZE = 0x4,
PIDL = 0x8, USEFILEATTRIBUTES = 0x10,
ADDOVERLAYS = 0x20, OVERLAYINDEX = 0x40
}
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(
string pszPath, uint dwFileAttributes,
ref SHFILEINFO psfi, uint cbFileInfo, SHGFI uFlags);
public static Icon GetLargeIcon(string filePath)
{
var info = new SHFILEINFO();
SHGetFileInfo(filePath, 0, ref info, (uint)Marshal.SizeOf(info),
SHGFI.ICON | SHGFI.LARGEICON);
try { return Icon.FromHandle(info.hIcon); }
catch { return null; }
}
public static Icon GetSmallIcon(string filePath)
{
var info = new SHFILEINFO();
SHGetFileInfo(filePath, 0, ref info, (uint)Marshal.SizeOf(info),
SHGFI.ICON | SHGFI.SMALLICON);
try { return Icon.FromHandle(info.hIcon); }
catch { return null; }
}
var large = ShellHelper.GetLargeIcon(@"C:\Windows\notepad.exe");
var small = ShellHelper.GetSmallIcon(@"C:\Windows\notepad.exe");
pictureBoxLarge.Image = large?.ToBitmap();
pictureBoxSmall.Image = small?.ToBitmap();
ImageList + 系統圖標索引 (SHGFI.SYSICONINDEX)Icon 或使用系統圖標索引Icon.FromHandle 返回的 Icon 需 DisposeSHGetFileInfo 是獲取系統文件圖標的標準途徑。掌握結構體佈局、標誌組合、P/Invoke 簽名、句柄管理,即可在 WinForms/WPF 中實現原生級文件圖標顯示。生產環境建議配合 ImageList 使用系統圖標索引模式,兼顧性能與顯示質量。