SHGetFileInfo我取在Windows

SHGetFileInfo我取在Windows

本文介绍了如何使用Shell32.SHGetFileInfo我取在Windows 7的文件夹图标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下的code这适用于Windows XP和Vista - 32位和64位:

I have the following code which works on Windows XP and Vista - both 32 and 64 bit:

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

的常数的定义如下方式:

The constants are defined the following way:

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中,结果如下:

This gives the following results in windows 7 when fetching the folder icon:

而在Vista中 - 用同样的方法结果在下面的文件夹图标:

While at Vista - using the same method result in the following folder icon:

我想正确的Windows文件夹中的Windows 7图标也 - 不是用来表示在安装Windows的驱动器图标

I would like the "correct" Windows folder icon for Windows 7 also - not the icon used to indicate the drive where Windows is installed.

我不知道在Win32 API和我的非托管编程是旁边没有在Windows平台上。

I don't know the win32 API and my non-managed programming is next to none on the Windows platform.

推荐答案

您不应指定的请示第一个参数 SHGeFileInfo 。使用的文件夹路径,而不是(请注意,某些文件夹有不同的(非标)图标)。您可以使用临时文件夹或例如应用程序的根目录下。

You shouldn't specify null as yur first parameter to SHGeFileInfo. Use the path to a folder instead (please note that some folders have different (non-standard) icons). You could use the temp folder or your application's root folder for example.

最好的做法是让每个文件夹的正确的图标(换句话说:对 GetFolderIcon 签名更改为公共静态图标GetFolderIcon(串FOLDERPATH,IconSize大小,FolderType folderType)并调用它为你显示每个文件夹)。

Best practise would be to get the correct icon for each folder (in other words: Change the signature of GetFolderIcon to public static Icon GetFolderIcon(string folderPath, IconSize size, FolderType folderType) and call it for each folder you display).

似乎有其已经具备了获取的文件夹图标的托管包装的开源库。在PInvoke.net(为的SHGetFileInfo项)已找到:

There seems to be an open source library which already has a managed wrapper for fetching folder icons.Found on PInvoke.net (the entry for SHGetFileInfo):

然而,这并不重要,如果你想要一个磁盘或文件夹的图标的工作。

在这种情况下,你可以使用由ManagedWindowsApi项目所提供的ExtendedFileInfo类( http://mwinapi.sourceforge.net )。

In that case, you can use the ExtendedFileInfo class provided by the ManagedWindowsApi project (http://mwinapi.sourceforge.net).

如果你想坚持一个手工制作的解决方案,这对我的作品(Win7的X64 RTM,.NET 3.5 SP1):

If you want to stick to a hand-crafted solution, this works for me (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);
            }
        }
    }
}

这篇关于如何使用Shell32.SHGetFileInfo我取在Windows 7的文件夹图标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 16:03