首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用Win32应用程序接口或Windows API代码包在C#中检索在Windows10上显示为小而打开的通用文件夹图标?

如何使用Win32应用程序接口或Windows API代码包在C#中检索在Windows10上显示为小而打开的通用文件夹图标?
EN

Stack Overflow用户
提问于 2020-04-12 03:57:09
回答 1查看 303关注 0票数 1

在C#中使用Win32应用程序接口检索文件/文件夹图标是一个微不足道的过程,这一过程已经被无数次地记录下来,一直追溯到.Net的开始。

每个有文档记录的解决方案都只是相同方法的变体:p/调用SHGetFileInfo(),传递适当的属性/标志。

我是在Windows10上开发的,我假设它使用的是Shell32.dll v6.1 --与Windows7附带的版本相同,最后一个版本是根据Microsoft's documentation发布的。在我的开发系统上,C:\Windows\system32\shell32.dll的资源管理器的Properties窗口的Details选项卡中显示的版本是"10.0.18362.719“。

我的目标是使用这种方法来生成一个“通用的”文件夹图标。我需要它是小(vs大)和在开放(vs关闭)状态。

我注意到,如果有人从SHGetFileInfo()请求一个小的通用文件夹图标,结果总是以"closed“状态出现。

相反,如果从SHGetFileInfo()请求一个大的通用文件夹图标,结果总是以“打开”状态出现。

下面的代码是这方面最简单的演示。对于大图标,将SmallIcon标志更改为LargeIcon。对于已关闭的图标,请删除OpenIcon标志。

代码语言:javascript
运行
复制
public static Icon GetMyIcon()
{
    var flags = (uint)(ShellAttribute.Icon | ShellAttribute.SmallIcon | ShellAttribute.OpenIcon);

    var fileInfo = new ShellFileInfo();
    var size = (uint)Marshal.SizeOf(fileInfo);
    var result = Interop.SHGetFileInfo(string.Empty, (uint)FileAttribute.Directory, out fileInfo, size, flags);

    if (result == IntPtr.Zero)
        throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());

    try
    {
        return (Icon)Icon.FromHandle(fileInfo.hIcon).Clone();
    }
    finally
    {
        Interop.DestroyIcon(fileInfo.hIcon);
    }
}

其中Interop方法声明如下:

代码语言:javascript
运行
复制
public static class Interop
{
    [DllImport("shell32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SHGetFileInfo(string path,
        uint attributes,
        out ShellFileInfo fileInfo,
        uint size,
        uint flags);

    [DllImport("user32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool DestroyIcon(IntPtr pointer);
}

是否需要某种黑魔法才能获得一个通用的文件夹图标,要么是小而打开的,要么是大而关闭的?

我还可以在我的项目中使用Windows API Code Pack,所以如果可以绕过Win32 API,仅使用这个库就可以达到我想要的结果,这就足够了。

更新:在Ian H的建议下,我尝试使用SHGetStockIconInfo应用程序接口,但不幸的是结果是相同的:

代码语言:javascript
运行
复制
private static Icon GetStockIcon()
{
    SHSTOCKICONINFO sii = new SHSTOCKICONINFO();
    sii.cbSize = (UInt32)Marshal.SizeOf(typeof(SHSTOCKICONINFO));

    Marshal.ThrowExceptionForHR(SHGetStockIconInfo(SHSTOCKICONID.SIID_FOLDEROPEN,
            SHGSI.SHGSI_ICON | SHGSI.SHGSI_SMALLICON,
            ref sii));
    return Icon.FromHandle(sii.hIcon);
}
EN

回答 1

Stack Overflow用户

发布于 2020-04-17 17:50:04

系统打开图标大小为32*32,您可以使用GetObject获取。

我的要求是一个带有“打开”外观的小图标(16x16)。

以下是在C++中使用IShellItemImageFactory根据系统打开图标外观创建大小为16*16的位图的示例,您可以将其作为解决办法。

代码语言:javascript
运行
复制
        SHFILEINFOW sfi = { 0 };
        ICONINFO iconinfo;
        HBITMAP hBitmap;
        IShellItemImageFactory *pImageFactory;
        SIZE size = { 16, 16 };

        CoInitialize(NULL);

        hr = SHGetFileInfo(L"D:\\Test",
            -1,
            &sfi,
            sizeof(sfi),
            SHGFI_SYSICONINDEX | SHGFI_OPENICON | SHGFI_ICON);

        if (FAILED(hr))
        {
            OutputDebugString(L"SHGetFileInfo fails.\n");
        }

        GetIconInfo(sfi.hIcon, &iconinfo);
        hBitmap = iconinfo.hbmColor;

        BITMAP bmp;
        ZeroMemory(&bmp, sizeof(bmp));

        if (iconinfo.hbmColor)
        {
            // Get initial size is 32*32
            int nWrittenBytes = GetObject(iconinfo.hbmColor, sizeof(bmp), &bmp);

            hr = SHCreateItemFromParsingName(L"D:\\Test", NULL, IID_PPV_ARGS(&pImageFactory));
            if (SUCCEEDED(hr))
            {
                // Get expected size 16*16
                hr = pImageFactory->GetImage(size, SIIGBF_BIGGERSIZEOK, &hBitmap);
                if (FAILED(hr))
                {
                    OutputDebugString(L"IShellItemImageFactory::GetImage failed with error code %x");
                }
                pImageFactory->Release();
            }

            // Confirm if the size is 16*16
            nWrittenBytes = GetObject(hBitmap, sizeof(bmp), &bmp);
        }

打开的小图标将如下所示:

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61162922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档