This appears to be a very poorly documented function.
The documentation for phIcon
says:
When this function returns, contains a pointer to the array of icon handles.
But since the parameter has type HICON*
, the caller must provide the array.
The documentation for pIconId
is also wrong. It turns out that it also is an array.
All the marshalling can be done using default settings. Since there is no ANSI version of this API, give it the full name, SHExtractIconsW
and set the Charset
to Unicode.
So far as the documentation goes, there's no mention of SetLastError
being called.
[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
);
To call this you'll need to allocate the arrays like this:
IntPtr[] Icons = new IntPtr[nIcons];
uint[] IconIDs = new uint[nIcons];
Finally, I echo @Cody's comment. Since this API is clearly documented incorrectly, I'd try to use an alternative API that is documented properly and that you can rely on for the future.
Since you seem to be struggling to get this all to work, here's a fun program that extracts and displays icons from shell32.dll
. I've not attempted to do any error checking, not called DestroyIcon
on the icons and so on.
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;
}
}
}