Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Gráficos (https://www.clubdelphi.com/foros/forumdisplay.php?f=8)
-   -   Obtener iconos grandes (https://www.clubdelphi.com/foros/showthread.php?t=62306)

_cero_ 16-12-2008 07:07:43

Obtener iconos grandes
 
Pues de nuevo dando una pequeña lata por aquí, verán yo uso “SHGetFileInfo” para extraer los iconos de algunas aplicaciones o documentos de Windows, el problema es que yo quisiera obtener los iconos con alta resolución, como de unos 128x128 ó 256x256(que son los que ya maneja el vista), para mostrarlos en un TImage, es esto posible?

O que por favor alguien me diga como poder cambiar el tamaño de los iconos sin comprometer demasiado la calidad de estos.

Estoy trabajando en c++ builder 2007, pero cualquier respuesta es buena. De antemano gracias.

cHackAll 16-12-2008 17:53:41

Los iconos en cualquier resolucion de un archivo binario están almacenados en su seccion de recursos, te aconsejo comenzar a buscar en el foro la extracción de recursos de un binario.

Saludos

_cero_ 16-12-2008 18:35:09

Pues gracias cHackAll, lo que sucede es que también me gustaría mostrar los iconos de algunas extensiones como por ejemplo txt, y en este caso de donde obtengo los iconos en alta resolución ya que estos no tienen archivos de recursos y con “SHGetFileInfo” solo me los da con una resolución de 16x16.

AzidRain 16-12-2008 22:13:19

Te recomiendo te eches una vuelta por photostock, tienen una biblioteca enorme de diferentes ilustraciones y dibujos que puedes convertir en íconos facilmente. Puedes usar el programa IcoFX que es gratuito para editarlos, es muy sencillo de usar y te permite generar íconos como los que necesitas.

No tengas miedo de hacer tus propios íconos, no es tan dificil y sin duda le daras tu propio toque a tus aplicaciones.

_cero_ 16-12-2008 23:53:01

pues gracias AzidRain, pero la cosa no es falta de iconos de hecho yo uso el “icon craft” para este fin(muy bueno por cierto), lo que intento es obtener los que tiene el sistema por defecto para no confundir al usuario con mis iconos, además de que es imposible que ponga todos los iconos de las extensiones dentro de mi aplicación.

escafandra 17-12-2008 00:21:06

Aquí tienes un ejemplo de como manejar iconos en la sección de recursos de un ejecutable o dll.
Cita:

Empezado por _cero_ (Mensaje 331228)
...lo que intento es obtener los que tiene el sistema por defecto...

¿Has mirado la API ExtractAssociatedIcon?

Saludos.

_cero_ 17-12-2008 00:46:02

gracias escafandra por el ejemplo, y si ya probé “ExtractAssociatedIcon” pero al igual que “SHGetFileInfo” solo me devuelve iconos de 16x16, y en cuanto a recursos ya mencione mas arriba que también querría los iconos de las exenciones por ejemplo de un txt, doc o pdf, con una resolución de al menos 64x64.

cHackAll 17-12-2008 00:53:37

Probaron ambos dicha API? ExtractAssociatedIcon es del namespace System.Drawing... .NET!

_cero_ 17-12-2008 01:09:37

Yo si que la probe y va perfecto en win 32, pero solo da los iconos en 16x16.

Código:

HICON ExtractAssociatedIcon(     
    HINSTANCE hInst,
    LPTSTR lpIconPath,
    LPWORD lpiIcon
);

Quizá hubo una confusión por el hipervínculo.

cHackAll 17-12-2008 01:20:25

Cita:

Empezado por _cero_ (Mensaje 331233)
...Quizá hubo una confusión por el hipervínculo.

:rolleyes: al parecer...

Entonces; lo unico que queda es analizar los recursos.

PD;
Cita:

Empezado por F1
LoadIcon can only load an icon whose size conforms to the SM_CXICON and SM_CYICON system metric values. Use the LoadImage function to load icons of other sizes.

Tambien te tocara revisar la API ShellAPI.FindExecutable

Suerte!

_cero_ 17-12-2008 02:48:14

Pues estoy devuelta después de estudiar un poco la función “LoadImage” que dejo cHackAll(gracias), y después de eso sigo sin poder extraer los iconos de las diferentes extensiones con una calidad aceptable, lo único que he logrado es obtenerlos de ejecutables y dll, pero hasta ahí. Me pregunto si abra una forma de darle el icono a la función “LoadImage” para redimensionarlos.

escafandra 17-12-2008 17:39:02

_cero_, ¿has intentado leer los iconos con ExtractAssociatedIcon pero especificando el índice que quieres? (lpicon). No puedo probarlo ahora, estoy en un ordenador que no tiene instalado el compilador. Se me ocurre que los leas uno a uno y compruebes el tamaño en un bucle hasta que encuentres el que deseas.

Saludos.:rolleyes:

_cero_ 17-12-2008 19:03:28

Eso es una muy buena propuesta escafandra, ya lo avía intentado cambiando LPWORD lpiIcon, pero solo le di valores enteros (como 1, 10, 2, etc.) Y como no me funciono y además no sabía bien qué onda con los índices lo deje, así que si me pusieras un ejemplillo de cómo hacer lo que propones te lo agradecería mucho.

_cero_ 18-12-2008 00:21:47

Pues miren logre conseguir un icono de 32x32, con el siguiente código.

función.
Código:

UINT ExtractIconEx(         
  LPCTSTR lpszFile,
  int nIconIndex,
  HICON *phiconLarge,
  HICON *phiconSmall,
  UINT nIcons
);

Y aquí está como la use.
Código:

HICON hIcon;
HICON hIconSmall;
ExtractIconEx("C:\\Windows\\System32\\calc.exe", 0, &hIcon, &hIconSmall,1);

Image1->Picture->Icon->Handle  = hIcon;//hIconSmall;

Quisiera unos iconos más grandes, pero aun no entiendo el rollo de los índices de los iconos (y creo que con esto se solucionaría todo), alguien me podría explicar algo sobre los índices de los iconos?.

_cero_ 18-12-2008 01:10:05

Ya profundice mas en este tema, y me quedo claro que un exe o dll pueden tener más de un icono y el índice es el numero que identifica a cada icono, ahora bien como saben un icono puede tener barias imágenes dentro de este, así que mi pregunta es de cómo puedo accesar a estas imágenes que están dentro del icono.
Les dejo una imagen por si no queda claro de a que estoy intentando accesar.

http://www.subirimagenes.com/otros-captura-1646462.html

escafandra 18-12-2008 01:43:23

_cero_ Estuve probando los índices en ExtractAssociatedIcon y no he obtenido el resultado deseado. Sólo devuelve un hIcon 32x32.

Cita:

Empezado por _cero_ (Mensaje 331391)
alguien me podría explicar algo sobre los índices de los iconos?.

Pues un icono, tanto en su versión file.ico como en su versión en memoria y resource, puede contener mas de una imagen de icono, es decir un grupo de iconos de distinto tamaño y número de colores. De esta forma se puede elegir el mas apropiado según el modo de video presente. Tienes información de esto aquí y en este hilo. Esto me hizo pensar que quizás ExtractAssociatedIcon permitiría escoger un icono... pero no funciona.

De todas formas he cotilleado SHELL32.dll con un editor de recursos y los iconos de 48x48 están, tiene muchos mas iconos que los que muestra cuando tratas de personalizar el icono mostrado por una carpeta, por ejemplo.

Bueno, ¿y si del Registro sacamos el default icon de un tipo de archivo?. Por ejemplo HKEY_CLASSES_ROOT\txtfile\DefaultIcon = %SystemRoot%\system32\shell32.dll,-152 se puede leer como un resource, 152 es el grupo de iconos correspondiente al notepad y archivos de extensión asociada a este programa. Basta leerlos y obtener el del tamaño que te interesa.

Claro, esta es una solución que puede funcionar muy bien pero es un poco trabajosa. He buscado en la Red y este problema lo ha encontrado mucha gente.... Quizas una búsqueda mas a fondo de con una solución mas simple. :rolleyes:

Saludos.

escafandra 18-12-2008 01:53:26

Cita:

Empezado por _cero_ (Mensaje 331394)
así que mi pregunta es de cómo puedo accesar a estas imágenes que están dentro del icono.

Quizás esto te pueda ayudar:

Código:

//---------------------------------------------------------------------------
// Devuelve un ResMem Icon de un hModule
// Devuelve el tamaño de la memoria de archivo de un Icono de un hModule
// Retorna 0 si falla, 1 si Buffer==0 y AllSize si devuelve el valor en Buffer.
// Precisa de un Buffer previo de tamaño Size
// Si Buffer = NULL, devuelve en Size el tamaño necesario para el buffer
// Id: Indice del Grupo de iconos como si fuese una array comenzando por 0
int ExtractResIconFromModule(HMODULE hModule, int Id, void* Buffer, int* Size)
{
    LPGRPICONDIR grpIconDir;
    LPGRPICONDIR grpSrcIconDir;
    LPGRPICONDIRENTRY grpIconEntry;
    LPICONIMAGE  grpIconImage;
    LPICONIMAGE  resIconImage;
    BYTE* IconMem = (BYTE*)Buffer;
    HRSRC hRes;        // handle para res. info. del ejecutable
    int IconsCount = 0;
    int AllSize = sizeof(GRPICONDIR);

    // Cuento cuantos iconos tiene el recurso y la memoria necesaria
    hRes = FindResource(hModule, Id, RT_GROUP_ICON);
    if(hRes){
      grpSrcIconDir = (LPGRPICONDIR)LoadResource(hModule, hRes);
      IconsCount = grpSrcIconDir->idCount;
      for(int n=0; n<IconsCount; n++)
        AllSize += sizeof(ICONDIRENTRY) + grpSrcIconDir->idEntries[n].dwBytesInRes;
    }
    if(IconsCount==0){
      *Size = 0;
      return 0;
    }
    if(Buffer == 0 ){
      *Size = AllSize;
      return 1;
    }
    if(*Size < AllSize) return 0;

    // Preparo la Cabecera General grpIconDir
    grpIconDir  = (LPGRPICONDIR)IconMem;
    grpIconDir->idReserved = 0;
    grpIconDir->idType = 1;
    grpIconDir->idCount = IconsCount;
    grpIconEntry = LPMEMICONDIRENTRY(IconMem + sizeof(GRPICONDIR) - sizeof(GRPICONDIRENTRY));

    // Localizar el ICON resource en el ejecutable y sus Imagenes.
    hRes = NULL;
    grpIconImage = (LPICONIMAGE)((BYTE*)grpIconDir + sizeof(GRPICONDIR) + (sizeof(GRPICONDIRENTRY)*(grpIconDir->idCount-1)));
    for(int n=0; n<IconsCount; n++){
      int nID = grpSrcIconDir->idEntries[n].nID;
      hRes = FindResource(hModule, MAKEINTRESOURCE(nID), RT_ICON);
      // Preparo las cabeceras Entrada de cada Imagen
      resIconImage = (ICONIMAGE*)LoadResource(hModule, hRes);
      grpIconEntry[n].bWidth = resIconImage->icHeader.biWidth;
      grpIconEntry[n].bHeight = resIconImage->icHeader.biHeight/2;
      grpIconEntry[n].bColorCount =  NColors(resIconImage->icHeader.biBitCount);
      grpIconEntry[n].bReserved = 0;
      grpIconEntry[n].wPlanes = 1;
      grpIconEntry[n].wBitCount = resIconImage->icHeader.biBitCount;
      grpIconEntry[n].dwBytesInRes = SizeofResource(hModule, hRes);
      grpIconEntry[n].nID = n;
      // Copio la imagen
      memcpy(grpIconImage, resIconImage, grpIconEntry[n].dwBytesInRes);
//      grpIconImage = (LPICONIMAGE)((BYTE*)grpIconImage + grpIconDir->idEntries[n-1].dwBytesInRes);
      grpIconImage = (LPICONIMAGE)((BYTE*)grpIconImage + grpIconEntry[n].dwBytesInRes);
    }

    return AllSize;
}

o esta otra versión de la misma función:
Código:

//---------------------------------------------------------------------------
// Devuelve un ResMem Icon de un hModule
// Reserva la memoria necesaria y Requiere liberarla luego con
// VirtualFree(Mem, 0, MEM_RELEASE);
// Id: Indice del Grupo de iconos como si fuese una array comenzando por 0
void* ExtractResIconFromModule(HMODULE hModule, int Id)
{
    LPGRPICONDIR grpIconDir;
    LPGRPICONDIR grpSrcIconDir;
    LPGRPICONDIRENTRY grpIconEntry;
    LPICONIMAGE  grpIconImage;
    LPICONIMAGE  resIconImage;
    HRSRC hRes;        // handle para res. info. del ejecutable
    int IconsCount = 0;
    int AllSize = sizeof(GRPICONDIR);

    // Cuento cuantos iconos tiene el recurso y la memoria necesaria
    hRes = FindResource(hModule, Id, RT_GROUP_ICON);
    if(hRes){
      grpSrcIconDir = (LPGRPICONDIR)LoadResource(hModule, hRes);
      IconsCount = grpSrcIconDir->idCount;
      for(int n=0; n<IconsCount; n++)
        AllSize += sizeof(ICONDIRENTRY) + grpSrcIconDir->idEntries[n].dwBytesInRes;
    }
    if(IconsCount==0) return 0;

    // Reservo memoria para la imagen del Icono en memoria
    BYTE* IconMem = (BYTE*)VirtualAlloc(0, AllSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // Preparo la Cabecera General grpIconDir
    grpIconDir  = (LPGRPICONDIR)IconMem;
    grpIconDir->idReserved = 0;
    grpIconDir->idType = 1;
    grpIconDir->idCount = IconsCount;
    grpIconEntry = LPMEMICONDIRENTRY(IconMem + sizeof(GRPICONDIR) - sizeof(GRPICONDIRENTRY));

    // Localizar el ICON resource en el ejecutable y sus Imagenes.
    hRes = NULL;
    grpIconImage = (LPICONIMAGE)((BYTE*)grpIconDir + sizeof(GRPICONDIR) + (sizeof(GRPICONDIRENTRY)*(grpIconDir->idCount-1)));
    for(int n=0; n<IconsCount; n++){
      int nID = grpSrcIconDir->idEntries[n].nID;
      hRes = FindResource(hModule, MAKEINTRESOURCE(nID), RT_ICON);
      // Preparo las cabeceras Entrada de cada Imagen
      resIconImage = (ICONIMAGE*)LoadResource(hModule, hRes);
      grpIconEntry[n].bWidth = resIconImage->icHeader.biWidth;
      grpIconEntry[n].bHeight = resIconImage->icHeader.biHeight/2;
      grpIconEntry[n].bColorCount =  NColors(resIconImage->icHeader.biBitCount);
      grpIconEntry[n].bReserved = 0;
      grpIconEntry[n].wPlanes = 1;
      grpIconEntry[n].wBitCount = resIconImage->icHeader.biBitCount;
      grpIconEntry[n].dwBytesInRes = SizeofResource(hModule, hRes);
      grpIconEntry[n].nID = n;
      // Copio la imagen
      memcpy(grpIconImage, resIconImage, grpIconEntry[n].dwBytesInRes);
//      grpIconImage = (LPICONIMAGE)((BYTE*)grpIconImage + grpIconDir->idEntries[n-1].dwBytesInRes);
      grpIconImage = (LPICONIMAGE)((BYTE*)grpIconImage + grpIconEntry[n].dwBytesInRes);
    }

    return IconMem;
}

Saludos.:D

_cero_ 18-12-2008 02:27:46

Pues muchas gracias escafandra, la función que dejaste se ve interesante, pero me gusto mas la idea que presentaste sobre obtener la dirección e índice del icono de una extensión desde el registro (muy buena idea, yo ni si quera sabia que se podía), así podría extraer y guardar los iconos que use en una especie de cache, y para obtener el tamaño de la imagen que quiero solo usaría el siguiente código.

Código:

Image1->Picture->Icon ->Handle=LoadImage(NULL, "C:\\txt.ico",
IMAGE_ICON, 128, 128,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);

Lo intento de esta forma y les cuento.

escafandra 18-12-2008 10:29:18

Solo una cosa mas, esta forma de asignar la imagen del icono:
Código:

Image1->Picture->Icon ->Handle = hIcon;
Puede dar problemas con el nº de colores para algunas versiones de Builder antiguas. Funciona bien para iconos de 16 colores pero si tiene mas, se reducen, al menos en BCB 5 y 6. Me imagino que en delphi 5 y 6 pasará lo mismo. Creo que las versiones de 2008 no tienen este problema.

Para solventar este problema escribí una función que mapea un HICON en memoria según un HDC concreto.

Si en tu Builder 2007 no tienes ese problema, pues perfecto. Si es así dímelo.

Saludos.:)

PD:
La idea de cHackAll:
Cita:

Empezado por cHackAll (Mensaje 331235)
Tambien te tocara revisar la API ShellAPI.FindExecutable

Te puede servir para aquellos iconos desde su ejecutable, claro que lños que estén en el resource del mismo ejecutable. A mi me parece también una buena opción.;)

_cero_ 18-12-2008 19:55:49

Pues no quería contestar hasta que tuviera una función concreta, pero me he atorado en la extracción del icono de los recursos a un archivo .ico, ya intente la función que dejo escafandra, pero no le entiendo mucho asi que por favor, me podrían ayudar con la extracción de un icono (ahora si proveniente de un exe o dll), a un directorio digamos "C:\".:confused::confused::confused::confused:


La franja horaria es GMT +2. Ahora son las 09:25:27.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi