如何从Windows中的文件中提取覆盖图标或其路径

问题描述 投票:0回答:1

我们有一个图标覆盖扩展,它根据文件状态显示不同的覆盖。对于自动化测试,我正在寻找一个来检查是否显示正确的覆盖图。因此,我询问是否可以提取覆盖图标本身,或者获取图标的路径进行比较。

我尝试了以下代码:

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;
}

不幸的是我从来没有得到覆盖图标,它是某种标准图标。

c# windows winapi windows-shell
1个回答
0
投票

您可以使用 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,
}
© www.soinside.com 2019 - 2024. All rights reserved.