如何使用Shell32.SHGetFileInfo在Windows 7上获取文件夹图标
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Shell32.SHGetFileInfo在Windows 7上获取文件夹图标相关的知识,希望对你有一定的参考价值。
我有以下代码适用于Windows XP和Vista - 32位和64位:
public static Icon GetFolderIcon(IconSize size, FolderType folderType)
{
// Need to add size check, although errors generated at present!
uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES;
if (FolderType.Open == folderType)
{
flags += Shell32.SHGFI_OPENICON;
}
if (IconSize.Small == size)
{
flags += Shell32.SHGFI_SMALLICON;
}
else
{
flags += Shell32.SHGFI_LARGEICON;
}
// Get the folder icon
var shfi = new Shell32.SHFILEINFO();
Shell32.SHGetFileInfo( null,
Shell32.FILE_ATTRIBUTE_DIRECTORY,
ref shfi,
(uint) Marshal.SizeOf(shfi),
flags );
Icon.FromHandle(shfi.hIcon); // Load the icon from an HICON handle
// Now clone the icon, so that it can be successfully stored in an ImageList
var icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone();
User32Dll.DestroyIcon( shfi.hIcon ); // Cleanup
return icon;
}
常量按以下方式定义:
public const uint SHGFI_ICON = 0x000000100;
public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
public const uint SHGFI_OPENICON = 0x000000002;
public const uint SHGFI_SMALLICON = 0x000000001;
public const uint SHGFI_LARGEICON = 0x000000000;
public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
这在获取文件夹图标时在Windows 7中提供以下结果:
在Vista中 - 使用相同的方法导致以下文件夹图标:
我想要Windows 7的“正确”Windows文件夹图标 - 而不是用于指示安装Windows的驱动器的图标。
我不知道win32 API,我的非托管编程在Windows平台上几乎没有。
您不应将null
指定为SHGeFileInfo
的第一个参数。请改用文件夹的路径(请注意,某些文件夹具有不同的(非标准)图标)。例如,您可以使用临时文件夹或应用程序的根文件夹。
最佳做法是为每个文件夹获取正确的图标(换句话说:将GetFolderIcon
的签名更改为public static Icon GetFolderIcon(string folderPath, IconSize size, FolderType folderType)
并为您显示的每个文件夹调用它)。
似乎有一个开源库已经有一个托管文件夹图标的托管包装器。在PInvoke.net上找到(SHGetFileInfo的条目):
但是,如果您需要驱动器或文件夹的图标,则无法使用此功能。
在这种情况下,您可以使用ManagedWindowsApi项目(http://mwinapi.sourceforge.net)提供的ExtendedFileInfo类。
如果你想坚持手工制作的解决方案,这对我有用(Win7 x64 RTM,.NET 3.5 SP1):
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace IconExtractor
{
[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;
};
public enum FolderType
{
Closed,
Open
}
public enum IconSize
{
Large,
Small
}
public partial class Form1 : Form
{
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, out SHFILEINFO psfi, uint cbFileInfo, uint uFlags);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DestroyIcon(IntPtr hIcon);
public const uint SHGFI_ICON = 0x000000100;
public const uint SHGFI_USEFILEATTRIBUTES = 0x000000010;
public const uint SHGFI_OPENICON = 0x000000002;
public const uint SHGFI_SMALLICON = 0x000000001;
public const uint SHGFI_LARGEICON = 0x000000000;
public const uint FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
public static Icon GetFolderIcon(IconSize size, FolderType folderType)
{
// Need to add size check, although errors generated at present!
uint flags = SHGFI_ICON | SHGFI_USEFILEATTRIBUTES;
if (FolderType.Open == folderType)
{
flags += SHGFI_OPENICON;
}
if (IconSize.Small == size)
{ flags += SHGFI_SMALLICON;
}
else
{
flags += SHGFI_LARGEICON;
}
// Get the folder icon
var shfi = new SHFILEINFO();
var res = SHGetFileInfo(@"C:Windows",
FILE_ATTRIBUTE_DIRECTORY,
out shfi,
(uint) Marshal.SizeOf(shfi),
flags );
if (res == IntPtr.Zero)
throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error());
// Load the icon from an HICON handle
Icon.FromHandle(shfi.hIcon);
// Now clone the icon, so that it can be successfully stored in an ImageList
var icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone();
DestroyIcon( shfi.hIcon ); // Cleanup
return icon;}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
Icon icon = GetFolderIcon(IconSize.Large, FolderType.Open);
pictureBox1.Image = icon.ToBitmap();
// Note: The image actually should be disposed somewhere
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
您不应将null指定为SHGetFileInfo的第一个参数。
那就对了。
请改用文件夹的路径(请注意,某些文件夹具有不同的(非标准)图标)。例如,您可以使用临时文件夹或应用程序的根文件夹。
它不需要是真实的(现有的)文件夹路径。任何非空字符串都可以。例如。:
SHGetFileInfo("AnyNonEmptyStringWillDo", FILE_ATTRIBUTE_DIRECTORY, sfi,
SizeOf(sfi), SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX)
以上是关于如何使用Shell32.SHGetFileInfo在Windows 7上获取文件夹图标的主要内容,如果未能解决你的问题,请参考以下文章
Python - 如何使用管道执行shell命令,但没有'shell = True'?