c# - tamaño - Usar un icono de Windows Vista de 256 x 256 en una aplicación
programa para convertir png a ico (5)
Eche un vistazo a las funciones del icono de Windows que están disponibles. También hay una descripción general que menciona la consulta de diferentes tamaños de iconos. Hay un hilo del foro Dream.In.Code para usar las API en C #, así como una referencia de Pinvoke.net .
Tengo una aplicación para la que he creado un icono de Windows Vista de 256 x 256.
Me preguntaba cómo podría usar un archivo PNG de 256x256 en el archivo ico utilizado como icono de la aplicación y mostrarlo en un cuadro de imagen en un formulario.
Estoy usando VB.NET, pero las respuestas en C # están bien. Estoy pensando que debo usar el reflejo.
No estoy seguro de si esto es posible incluso en Windows XP y puede que necesite las API de Windows Vista
Encontró información aquí . Para obtener el icono de Vista grande, debe usar el método SHGetFileInfo de Shell32. He copiado el texto relevante a continuación, por supuesto, querrás reemplazar la variable de nombre de archivo con "Assembly.GetExecutingAssembly (). Location".
using System.Runtime.InteropServices;
Un conjunto de constantes que usaremos en la llamada a SHGetFileInfo () para especificar el tamaño del icono que deseamos recuperar:
// Constants that we need in the function call
private const int SHGFI_ICON = 0x100;
private const int SHGFI_SMALLICON = 0x1;
private const int SHGFI_LARGEICON = 0x0;
La estructura de SHFILEINFO es muy importante ya que manejaremos varios archivos de información, entre los que se encuentra el ícono gráfico.
// This structure will contain information about the file
public struct SHFILEINFO
{
// Handle to the icon representing the file
public IntPtr hIcon;
// Index of the icon within the image list
public int iIcon;
// Various attributes of the file
public uint dwAttributes;
// Path to the file
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string szDisplayName;
// File type
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
La preparación final para el código no administrado es definir la firma de SHGetFileInfo, que se encuentra dentro del popular Shell32.dll:
// The signature of SHGetFileInfo (located in Shell32.dll)
[DllImport("Shell32.dll")]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, uint uFlags);
Ahora que tenemos todo preparado, es hora de hacer la llamada a la función y mostrar el ícono que recuperamos. El objeto que se recuperará es un tipo de icono (System.Drawing.Icon) pero queremos mostrarlo en un PictureBox así que convertiremos el ícono en un mapa de bits usando el método ToBitmap ().
Pero ante todo hay 3 controles que debe agregar al formulario, un Botón btnExtract que tiene "Icono de Extraer" para su propiedad de Texto, picIconSmall que es un PictureBox y un picIconLarge que también es un PictureBox. Eso es porque obtendremos dos tamaños de iconos. Ahora haga doble clic en btnExtract en la vista Diseño de Visual Studio y obtendrá su evento Click. Dentro está el resto del código:
private void btnExtract_Click(object sender, EventArgs e)
{
// Will store a handle to the small icon
IntPtr hImgSmall;
// Will store a handle to the large icon
IntPtr hImgLarge;
SHFILEINFO shinfo = new SHFILEINFO();
// Open the file that we wish to extract the icon from
if(openFile.ShowDialog() == DialogResult.OK)
{
// Store the file name
string FileName = openFile.FileName;
// Sore the icon in this myIcon object
System.Drawing.Icon myIcon;
// Get a handle to the small icon
hImgSmall = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_SMALLICON);
// Get the small icon from the handle
myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
// Display the small icon
picIconSmall.Image = myIcon.ToBitmap();
// Get a handle to the large icon
hImgLarge = SHGetFileInfo(FileName, 0, ref shinfo, Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_LARGEICON);
// Get the large icon from the handle
myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
// Display the large icon
picIconLarge.Image = myIcon.ToBitmap();
}
}
ACTUALIZACIÓN: encontró aún más información aquí .
Ninguna de las respuestas anteriores maneja los íconos Vista, solo pequeños (32x32) y grandes (48x48)
Hay una biblioteca que maneja Vista Icons aquí
... parece bastante complicado debido al formato de canal alfa dual png.
Trataré de hacer una respuesta concisa en vb .net pero puede tomar algún tiempo.
Hoy hice una muy buena función para extraer los mapas de bits de 256x256 de los iconos de Vista .
Al igual que usted, Nathan W, lo uso para mostrar el icono grande como un mapa de bits en el cuadro "Acerca de". Por ejemplo, este código obtiene el icono de Vista como imagen PNG y lo muestra en un PictureBox de 256x256:
picboxAppLogo.Image = ExtractVistaIcon(myIcon);
Esta función toma el objeto Icon como parámetro. Por lo tanto, puede usarlo con cualquier ícono, desde recursos , desde archivos, desde transmisiones, etc. (Lea a continuación sobre la extracción del icono EXE).
Se ejecuta en cualquier sistema operativo , porque no usa ninguna API Win32, es código 100% administrado :-)
// Based on: http://www.codeproject.com/KB/cs/IconExtractor.aspx
// And a hint from: http://www.codeproject.com/KB/cs/IconLib.aspx
Bitmap ExtractVistaIcon(Icon icoIcon)
{
Bitmap bmpPngExtracted = null;
try
{
byte[] srcBuf = null;
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{ icoIcon.Save(stream); srcBuf = stream.ToArray(); }
const int SizeICONDIR = 6;
const int SizeICONDIRENTRY = 16;
int iCount = BitConverter.ToInt16(srcBuf, 4);
for (int iIndex=0; iIndex<iCount; iIndex++)
{
int iWidth = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex];
int iHeight = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex + 1];
int iBitCount = BitConverter.ToInt16(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 6);
if (iWidth == 0 && iHeight == 0 && iBitCount == 32)
{
int iImageSize = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 8);
int iImageOffset = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 12);
System.IO.MemoryStream destStream = new System.IO.MemoryStream();
System.IO.BinaryWriter writer = new System.IO.BinaryWriter(destStream);
writer.Write(srcBuf, iImageOffset, iImageSize);
destStream.Seek(0, System.IO.SeekOrigin.Begin);
bmpPngExtracted = new Bitmap(destStream); // This is PNG! :)
break;
}
}
}
catch { return null; }
return bmpPngExtracted;
}
¡IMPORTANTE! Si desea cargar este ícono directamente desde el archivo EXE, entonces NO PUEDE usar Icon.ExtractAssociatedIcon (Application.ExecutablePath) como un parámetro, porque la función .NET ExtractAssociatedIcon () es tan estúpida, ¡solo EXTRAE el ícono de 32x32!
En su lugar, es mejor utilizar toda la clase IconExtractor , creada por Tsuda Kageyu ( http://www.codeproject.com/KB/cs/IconExtractor.aspx ). Puede simplificar levemente esta clase, para hacerla más pequeña. Use IconExtractor de esta manera:
// Getting FILL icon set from EXE, and extracting 256x256 version for logo...
using (TKageyu.Utils.IconExtractor IconEx = new TKageyu.Utils.IconExtractor(Application.ExecutablePath))
{
Icon icoAppIcon = IconEx.GetIcon(0); // Because standard System.Drawing.Icon.ExtractAssociatedIcon() returns ONLY 32x32.
picboxAppLogo.Image = ExtractVistaIcon(icoAppIcon);
}
Nota: todavía estoy usando mi función ExtractVistaIcon () aquí, porque no me gusta cómo IconExtractor maneja este trabajo: primero, extrae todos los formatos de icono usando IconExtractor.SplitIcon (icoAppIcon), y luego debe conocer la exacta Índice de icono de 256x256 para obtener el icono de vista deseado. Entonces, usar ExtractVistaIcon () aquí es mucho más rápido y simplista :)
Al tener el mismo problema de mostrar la imagen 256 * 256 * 32 desde un archivo ICO en un cuadro de imagen, encontré que la solución de SAL80 era la más eficiente (y casi funciona). Sin embargo, el código original no admite imágenes almacenadas como BMP (el icono grande suele ser PNG, pero no siempre ...).
Aquí está mi versión para referencias futuras. El código para crear el mapa de bits también es un poco más simple:
/// <summary>
/// Extracts the large Vista icon from a ICO file
/// </summary>
/// <param name="srcBuf">Bytes of the ICO file</param>
/// <returns>The large icon or null if not found</returns>
private static Bitmap ExtractVistaIcon(byte[] srcBuf)
{
const int SizeIcondir = 6;
const int SizeIcondirentry = 16;
// Read image count from ICO header
int iCount = BitConverter.ToInt16(srcBuf, 4);
// Search for a large icon
for (int iIndex = 0; iIndex < iCount; iIndex++)
{
// Read image information from image directory entry
int iWidth = srcBuf[SizeIcondir + SizeIcondirentry * iIndex];
int iHeight = srcBuf[SizeIcondir + SizeIcondirentry * iIndex + 1];
int iBitCount = BitConverter.ToInt16(srcBuf, SizeIcondir + SizeIcondirentry * iIndex + 6);
// If Vista icon
if (iWidth == 0 && iHeight == 0 && iBitCount == 32)
{
// Get image data position and length from directory
int iImageSize = BitConverter.ToInt32(srcBuf, SizeIcondir + SizeIcondirentry * iIndex + 8);
int iImageOffset = BitConverter.ToInt32(srcBuf, SizeIcondir + SizeIcondirentry * iIndex + 12);
// Check if the image has a PNG signature
if (srcBuf[iImageOffset] == 0x89 && srcBuf[iImageOffset+1] == 0x50 && srcBuf[iImageOffset+2] == 0x4E && srcBuf[iImageOffset+3] == 0x47)
{
// the PNG data is stored directly in the file
var x = new MemoryStream(srcBuf, iImageOffset, iImageSize, false, false);
return new Bitmap(x);
}
// Else it''s bitmap data with a partial bitmap header
// Read size from partial header
int w = BitConverter.ToInt32(srcBuf, iImageOffset + 4);
// Create a full header
var b = new Bitmap(w, w, PixelFormat.Format32bppArgb);
// Copy bits into bitmap
BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.WriteOnly, b.PixelFormat);
Marshal.Copy(srcBuf, iImageOffset + Marshal.SizeOf(typeof(Bitmapinfoheader)), bmpData.Scan0, b.Width*b.Height*4);
b.UnlockBits(bmpData);
return b;
}
}
return null;
}