Как я выбираю значок папки в Windows 7 с помощью Shell32. SHGetFileInfo

А, гибкие диски, помните те?

Вы могли бы потратить целый день на написание своего последнего приложения-убийцы, а потом обнаружить, что не смогли сохранить его, потому что оно было слишком большим, чтобы поместиться на 5,25-дюймовом Плотность диска.

Это было тогда, когда дискеты действительно были гибкими. Тонкие и хрупкие, обычно размером 5,25 или 8 дюймов, хотя первые внутренние накопители в ПК были 5,25 дюйма. Как упоминалось ранее, ранние версии MS Dos использовались для автоматического назначения диска A: первому дисководу гибких дисков и B: второму. Жесткие диски даже тогда не вписывались в ПК. Вы можете купить винчестерский жесткий диск емкостью 5 МБ, который весит около 30 кг и поставляется в большом внешнем корпусе размером почти с современный мини-компьютер с башней.

Если на вашем ПК установлены двойные дискеты, вы можете набрать команду типа «копировать a: b:», чтобы скопировать содержимое диска A: на диск B:

Но тогда все это вернулось во времени когда Билл Гейтс стоил около 10000 долларов!

15
задан tronda 19 December 2017 в 08:16
поделиться

2 ответа

Не следует указывать null в качестве первого параметра для SHGeFileInfo . Вместо этого используйте путь к папке (обратите внимание, что некоторые папки имеют другие (нестандартные) значки). Например, вы можете использовать временную папку или корневую папку вашего приложения.

Лучше всего получить правильный значок для каждой папки (другими словами: измените подпись GetFolderIcon на public static Icon GetFolderIcon (string folderPath, IconSize size, FolderType folderType) и вызовите его для каждой отображаемой папки)

Похоже, существует библиотека с открытым исходным кодом, в которой уже есть управляемая оболочка для получения значков папок. Найдено на PInvoke.net (запись для SHGetFileInfo):

Однако это не работает, если вам нужен значок диска или папки.

В этом случае вы можете использовать класс ExtendedFileInfo, предоставленный проектом ManagedWindowsApi ( http://mwinapi.sourceforge.net ).

Если вы хотите придерживаться решения, созданного вручную , у меня это работает (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);
            }
        }
    }
}
20
ответ дан 1 December 2019 в 02:20
поделиться

You shouldn't specify null as yur first parameter to SHGeFileInfo.

That's right.

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.

It doesn't need to be a real (existing) folder path. Any non-empty string will do. e.g.:

SHGetFileInfo("AnyNonEmptyStringWillDo", FILE_ATTRIBUTE_DIRECTORY, sfi,
      SizeOf(sfi), SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX)
9
ответ дан 1 December 2019 в 02:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: