我们有一个图标覆盖扩展,它根据文件状态显示不同的覆盖。对于自动化测试,我正在寻找一个来检查是否显示正确的覆盖图。因此,我询问是否可以提取覆盖图标本身,或者获取图标的路径进行比较。
我尝试了以下代码:
SHFILEINFO shfi = new SHFILEINFO();
IntPtr result = SHGetFileInfo(filePath, 0, ref shfi, (uint)Marshal.SizeOf(shfi), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_OVERLAYINDEX);
if (result != IntPtr.Zero)
{
int overlayIndex = shfi.iIcon >> 24;
Console.WriteLine($"Overlay Index: {overlayIndex}");
DestroyIcon(shfi.hIcon);
}
尽管
overlayIndex
每次都是0,有没有办法在没有主图标的情况下获得覆盖图标来进行比较或检查?
编辑: 在吉米的评论后我尝试了以下方法:
private static Icon GetOverlay(string filePath)
{
var imageListGuid = new Guid("46EB5926-582E-4017-9FDF-E8998DAA0950");
IMAGELIST sysImageList;
var result = SHGetImageList(SHIL_SMALL, ref imageListGuid, out sysImageList);
if (result == 0)
{
var shfi = new SHFILEINFO();
var hSuccess = SHGetFileInfo(filePath, 0, ref shfi, (uint)Marshal.SizeOf(shfi), SHGFI_ICON | SHGFI_OVERLAYINDEX | SHGFI_SMALLICON);
if (hSuccess != IntPtr.Zero)
{
var iconIndex = shfi.iIcon;
var overlayIndex = iconIndex & 0xF;
var hOverlayIcon = ImageList_GetIcon(sysImageList.handle, overlayIndex, 0);
var overlay = Icon.FromHandle(hOverlayIcon);
return overlay;
}
}
return null;
}
不幸的是我从来没有得到覆盖图标,它是某种标准图标。
您可以使用 IImageList::GetOverlayImage 方法,这是一个完整的示例:
static void Main()
{
var info = new SHFILEINFO();
SHGetFileInfo(@"c:\temp\my.lnk", FileAttributes.Normal, ref info, Marshal.SizeOf(info), SHGFI.SHGFI_ICON | SHGFI.SHGFI_OVERLAYINDEX);
DestroyIcon(info.hIcon); // file + overlay, we don't need it
// per doc: upper eight bits of the iIcon member
var overlayIndex = info.iIcon >> 24; // overlayIndex >= 1 and <= 15 (system limit)
if (overlayIndex > 0)
{
SHGetImageList(SHIL.SHIL_LARGE, typeof(IImageList).GUID, out var list);
if (list != null)
{
list.GetOverlayImage(overlayIndex, out var imageIndex);
if (imageIndex >= 0)
{
list.GetIcon(imageIndex, ILD.ILD_NORMAL, out var hicon);
if (hicon != IntPtr.Zero)
{
var bmp = Bitmap.FromHicon(hicon);
bmp.Save("icon" + overlayIndex + ".png");
DestroyIcon(hicon);
}
}
}
}
}
[DllImport("shell32", CharSet = CharSet.Unicode)]
public static extern IntPtr SHGetFileInfo(string pszPath, FileAttributes dwFileAttributes, ref SHFILEINFO psfi, int cbSizeFileInfo, SHGFI uFlags);
[DllImport("shell32")]
private static extern int SHGetImageList(SHIL iImageList, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IImageList ppv);
[DllImport("user32")]
public static extern bool DestroyIcon(IntPtr handle);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHFILEINFO
{
public IntPtr hIcon;
public int iIcon;
public int dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
}
public enum SHIL
{
SHIL_LARGE = 0,
SHIL_SMALL = 1,
SHIL_EXTRALARGE = 2,
SHIL_SYSSMALL = 3,
SHIL_JUMBO = 4,
}
[Flags]
public enum ILD
{
ILD_NORMAL = 0x00000000,
ILD_TRANSPARENT = 0x00000001,
ILD_MASK = 0x00000010,
ILD_IMAGE = 0x00000020,
ILD_ROP = 0x00000040,
ILD_BLEND25 = 0x00000002,
ILD_BLEND50 = 0x00000004,
ILD_OVERLAYMASK = 0x00000F00,
ILD_PRESERVEALPHA = 0x00001000,
ILD_SCALE = 0x00002000,
ILD_DPISCALE = 0x00004000,
ILD_ASYNC = 0x00008000,
ILD_SELECTED = ILD_BLEND50,
ILD_FOCUS = ILD_BLEND25,
ILD_BLEND = ILD_BLEND50,
}
[ComImport, Guid("46eb5926-582e-4017-9fdf-e8998daa0950"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public partial interface IImageList
{
[PreserveSig]
int Add(IntPtr hbmImage, IntPtr hbmMask, out int pi);
[PreserveSig]
int ReplaceIcon(int i, IntPtr hicon, out int pi);
[PreserveSig]
int SetOverlayImage(int iImage, int iOverlay);
[PreserveSig]
int Replace(int i, IntPtr hbmImage, IntPtr hbmMask);
[PreserveSig]
int AddMasked(IntPtr hbmImage, uint crMask, out int pi);
[PreserveSig]
int Draw(ref int pimldp);
[PreserveSig]
int Remove(int i);
[PreserveSig]
int GetIcon(int i, ILD flags, out IntPtr picon);
[PreserveSig]
int GetImageInfo(int i, out int pImageInfo);
[PreserveSig]
int Copy(int iDst, [MarshalAs(UnmanagedType.IUnknown)] object punkSrc, int iSrc, uint uFlags);
[PreserveSig]
int Merge(int i1, [MarshalAs(UnmanagedType.IUnknown)] object punk2, int i2, int dx, int dy, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
[PreserveSig]
int Clone([MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
[PreserveSig]
int GetImageRect(int i, IntPtr prc);
[PreserveSig]
int GetIconSize(out int cx, out int cy);
[PreserveSig]
int SetIconSize(int cx, int cy);
[PreserveSig]
int GetImageCount(out int pi);
[PreserveSig]
int SetImageCount(uint uNewCount);
[PreserveSig]
int SetBkColor(uint clrBk, out uint pclr);
[PreserveSig]
int GetBkColor(out uint pclr);
[PreserveSig]
int BeginDrag(int iTrack, int dxHotspot, int dyHotspot);
[PreserveSig]
int EndDrag();
[PreserveSig]
int DragEnter(IntPtr hwndLock, int x, int y);
[PreserveSig]
int DragLeave(IntPtr hwndLock);
[PreserveSig]
int DragMove(int x, int y);
[PreserveSig]
int SetDragCursorImage([MarshalAs(UnmanagedType.IUnknown)] object punk, int iDrag, int dxHotspot, int dyHotspot);
[PreserveSig]
int DragShowNolock(bool fShow);
[PreserveSig]
int GetDragImage(IntPtr ppt, IntPtr pptHotspot, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppv);
[PreserveSig]
int GetItemFlags(int i, out uint dwFlags);
[PreserveSig]
int GetOverlayImage(int iOverlay, out int piIndex);
}
[Flags]
public enum SHGFI
{
SHGFI_ICON = 0x000000100,
SHGFI_DISPLAYNAME = 0x000000200,
SHGFI_TYPENAME = 0x000000400,
SHGFI_ATTRIBUTES = 0x000000800,
SHGFI_ICONLOCATION = 0x000001000,
SHGFI_EXETYPE = 0x000002000,
SHGFI_SYSICONINDEX = 0x000004000,
SHGFI_LINKOVERLAY = 0x000008000,
SHGFI_SELECTED = 0x000010000,
SHGFI_ATTR_SPECIFIED = 0x000020000,
SHGFI_LARGEICON = 0x000000000,
SHGFI_SMALLICON = 0x000000001,
SHGFI_OPENICON = 0x000000002,
SHGFI_SHELLICONSIZE = 0x000000004,
SHGFI_PIDL = 0x000000008,
SHGFI_USEFILEATTRIBUTES = 0x000000010,
SHGFI_ADDOVERLAYS = 0x000000020,
SHGFI_OVERLAYINDEX = 0x000000040,
}