2

如何在 C# 中使用 SHExtractIconsW dll 函数,我设法在 AutoIt 中做到这一点,

Local $arResult = DllCall('shell32.dll', 'int', 'SHExtractIconsW', _
        'wstr', $sIcon, _
        'int', $aDetails[5], _
        'int', $iSize, _
        'int', $iSize, _
        'ptr*', 0, 'ptr*', 0, 'int', 1, 'int', 0)

这是来自微软网站的参考, http: //msdn.microsoft.com/en-us/library/windows/desktop/bb762163 (v=vs.85).aspx

基本上我想从exe文件中提取图标,但是这里几乎所有的例子都不能做到这一点,在autoit中我可以用SHExtractIconsW做到这一点,所以我想在C#中尝试一下。

注意:我想要 64x64 到 256x256 的图标大小,而不是下。

4

1 回答 1

3

这似乎是一个记录得很差的函数。

的文档phIcon说:

当此函数返回时,包含一个指向图标句柄数组的指针。

但由于参数具有 type HICON*,调用者必须提供数组。

的文档pIconId也是错误的。原来它也是一个数组。

所有编组都可以使用默认设置完成。由于此 API 没有 ANSI 版本,因此请为其提供全名,SHExtractIconsW并将其设置Charset为 Unicode。

文档而言,没有提到SetLastError被调用。

[DllImport("Shell32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)]
static extern uint SHExtractIconsW(
    string pszFileName,
    int nIconIndex,
    int cxIcon,
    int cyIcon,
    IntPtr[] phIcon,
    uint[] pIconId,
    uint nIcons,
    uint flags
);

要调用它,您需要像这样分配数组:

IntPtr[] Icons = new IntPtr[nIcons];
uint[] IconIDs = new uint[nIcons];

最后,我回应@Cody 的评论。由于此 API 的文档记录明显不正确,因此我会尝试使用已正确记录且您将来可以依赖的替代 API。


由于您似乎很难让这一切正常工作,这里有一个有趣的程序,它从shell32.dll. 我没有尝试进行任何错误检查,也没有DestroyIcon在图标上调用等等。

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication12
{
    public partial class Form1 : Form
    {
        [DllImport("Shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
        static extern uint SHExtractIconsW(
            string pszFileName,
            int nIconIndex,
            int cxIcon,
            int cyIcon,
            IntPtr[] phIcon,
            uint[] pIconId,
            uint nIcons,
            uint flags
        );

        public Form1()
        {
            InitializeComponent();
        }

        private IntPtr[] Icons;
        private int currentIcon = 0;
        uint iconsExtracted;

        private void Form1_Load(object sender, EventArgs e)
        {
            uint nIcons = 1000;
            Icons = new IntPtr[nIcons];
            uint[] IconIDs = new uint[nIcons];
            iconsExtracted = SHExtractIconsW(
                @"C:\Windows\System32\shell32.dll",
                0,
                256, 256,
                Icons,
                IconIDs,
                nIcons,
                0
            );
            if (iconsExtracted == 0)
                ;//handle error
            Text = string.Format("Icon count: {0:d}", iconsExtracted);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            pictureBox1.Image = Bitmap.FromHicon(Icons[currentIcon]);
            currentIcon = (currentIcon + 1) % (int)iconsExtracted;
        }
    }
}
于 2013-04-12T20:11:27.727 回答