Artículo original: Extract icons from EXE, DLL and ICO files with GdiPlus-X
http://weblogs.foxite.com/vfpimaging/archive/2007/02/09/3255.aspx
Autor: Cesar Ch.
Traducido por: Ana María Bisbé York
Algunos tipos de archivos admiten guardar varios iconos junto a otros datos binarios, como EXEs y DLLs. Los archivos .ICO admiten además almacenar más de un icono en un archivo único. Windows utiliza mucho esto, y guarda casi todos los íconos que utiliza todo el tiempo en algunas bibliotecas DLL o EXE.
La biblioteca
GdiPlusX puede fácilmente extraer estos íconos, utilizando la función
"ExtractAssociatedIcon" de la clase xfcIcon como se muestra a continuación:
IMPORTANTE:
Todos los ejemplos que se muestran a continuación utilizan la nueva biblioteca GDIPlus-X desde
XFP-X y requiere que usted tenga al menos la versión
RELEASE 0.07. GdiPlusX está aún en versión ALPHA, pero es realmente estable y fiable para hacer la gran mayoría de las tareas de GDI+. Descargue la versión más estable de Codeplex:
http://www.codeplex.com/Wiki/View.aspx?ProjectName=VFPX&title=GDIPlusX
* El siguiente código demuestra cómo extraer un ícono de un archivo EXE
lcPath = ADDBS(JUSTPATH(SYS(16)))+"..\source\"
_SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE(lcPath+"system.vcx","vcx")))
LOCAL lcFile, lnIndex
LOCAL loIcon as xfcIcon
LOCAL loBmp as xfcBitmap
lcFile = GETFILE("exe;ico;dll") && _vfp.ServerName
lnIndex = 0
WITH _SCREEN.System.Drawing
DO WHILE .T.
loIcon = .Icon.ExtractAssociatedIcon(lcFile, lnIndex)
IF ISNULL(loIcon)
EXIT
ENDIF
lcNewFile = "C:\" + JUSTFNAME(lcFile) + TRANSFORM(lnIndex) + ".png"
loBmp = loIcon.ToBitmap()
loBmp.Save(lcNewFile, .Imaging.ImageFormat.Png)
lnIndex = lnIndex + 1
ENDDO
ENDWITH
RETURN
El archivo
ExtractIcons.scx en la carpeta Samples ofrece un formulario que permite seleccionar cualquier archivo, y GdiPlusX va a dibujar todos los íconos asociados dentro de un objeto ImageCanvas, como muestra la siguiente imagen:
¿Necesita más iconos?
En mis pruebas, después de creada esta función, tuve curiosidad por saber qué iconos podría guardar mi PC dentro de tantos ejecutables y DLLs instaladas, entonces, he creado un sencillo programa que va a buscar por las carpetas seleccionadas, y hará búsqueda recursiva en todas sus subcarpetas, buscando todos los archivos que pudieran guardar iconos.
Para mi sorpresa, muchos, en realidad
MILES de íconos emergieron ... y los resultados fueron muy interesantes, ¡ se lo aseguro !
Puede intentarlo también en su PC.
Guarde el programa que aparece a continuación como HowTo_ExtractIconsFromDir2.prg en la carpeta HELP de la biblioteca. Utiliza una rutina muy buena de
Michael Reynolds que publicó amablemente en
www.fox.wikis.com para obtener los nombres de todos los archivos de las subcarpetas. Observe que esto va a requerir un gran esfuerzo para su PC, por lo que debe preparase para esperar cerca de un minuto hasta que se termine esta tarea. Después de ejecutar este ejemplo, todos los iconos se almacenarán en "C:\MyIcons\".
* Archivo : HowTo_ExtractIconsFromDir2.prg
* Autor : Cesar Ch.
* Guarde este archivo en el directorio HELP de la carpeta de la biblioteca GdiPlus-X
*
* El siguiente código realiza las acciones siguientes :
*
* Pregunta al usuario por una ruta
* Crea un cursor que contiene todos los nombres de archivos disponibles (EXE, DLL e ICO)
* del directorio seleccionado y sus subdirectorios
* Recorre el cursor y extrae todos los iconos asociados a cada archivo
* Inicia GDI+
LOCAL lcPath
lcPath = ADDBS(JUSTPATH(SYS(16)))+"..\source\"
_SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE(lcPath+"system.vcx","vcx")))
* Crea el directorio destino para guardar los iconos extraídos
lcDir = "c:\MyIcons\"
IF NOT DIRECTORY(lcDir)
MKDIR (lcDir)
ENDIF
* Crea el cursor que va a guardar la localización válida del archivo
CREATE CURSOR Recursive (cFile c(250))
LOCAL lcCurDrive, lcCurDir, lcSelectedDir
lcCurDrive = JUSTDRIVE(FULLPATH(CURDIR()))
lcCurDir = CURDIR()
lcSelectedDir = GETDIR()
IF EMPTY(lcSelectedDir)
WAIT WINDOW "Directorio no válido"
RETURN .F.
ENDIF
WAIT WINDOW "Recibiendo información de las carpetas" NOWAIT
* Busca el directorio seleccionado y sus subdirectorios
=Recurse(GETDIR())
CHDIR &lcCurDrive.&lcCurDir.
* BROWSE
WITH _SCREEN.System.Drawing
LOCAL lcFile, lnIndex, lnTotRec
LOCAL lnOldPercentage, lnPercentage
LOCAL loIcon as xfcIcon
LOCAL loBmp as xfcBitmap
STORE 0 TO lnPercentage, lnOldPercentage
lnTotRec = RECCOUNT()
SCAN
lcFile = Recursive.cFile
lnIndex = 0
DO WHILE .T.
loIcon = NULL
* Extrae el icono asociado
loIcon = .Icon.ExtractAssociatedIcon(lcFile, lnIndex)
IF ISNULL(loIcon)
EXIT
ENDIF
lcNewFile = lcDir + JUSTFNAME(lcFile) + TRANSFORM(lnIndex) + ".png"
loBmp = NULL
* Envía el icono a un objeto GDI+
loBmp = loIcon.ToBitmap()
IF VARTYPE(loBmp) <> "O"
EXIT
ENDIF
* Guarda el Bitmap como PNG
loBmp.Save(lcNewFile, .Imaging.ImageFormat.Png)
lnIndex = lnIndex + 1
ENDDO
* Muestra la progresión
lnRec = RECNO()
lnPercentage = ROUND((lnRec / lnTotRec),1)
IF lnPercentage > lnOldPercentage
WAIT WINDOW "Extrayendo iconos de archivos..." + CHR(13) + ;
"Pasado: " + TRANSFORM(lnPercentage * 100) + " %" NOWAIT
lnOldPercentage = lnPercentage
ENDIF
ENDSCAN
ENDWITH
RETURN
*****************************************************************************************
* FUNCIÓN : RECURSE
* AUTOR : MICHAEL REYNOLDS
* DESCRIPCIÓN : Buena para realizar el procesamiento de archivos a través de todo el árbol de directorios.
* La función, RECURSE(), se llama con toda la ruta del directorio.
* RECURSE() leerá todos los archivos y directorios.
* Puede llamar a una función para procesar los archivos que encuentra.
* Además, la función se llama a sí misma para procesar los subdirectorios
* http://fox.wikis.com/wc.dll?Wiki~RecursiveDirectoryProcessing~VFP
*****************************************************************************************
FUNCTION Recurse(pcDir)
LOCAL lnPtr, lnFileCount, laFileList, lcDir, lcFile
CHDIR (pcDir)
DIMENSION laFileList[1]
*--- Lee el directorio seleccionado
lnFileCount = ADIR(laFileList, '*.*', 'D')
FOR lnPtr = 1 TO lnFileCount
IF 'D' $ laFileList[lnPtr, 5]
*--- Obtiene el nombre del directorio
lcDir = laFileList[lnPtr, 1]
*--- Ignora los punteros del directorio actual y el padre
IF lcDir != '.' AND lcDir != '..'
*--- Call this routine again.
Recurse(lcDir)
ENDIF
ELSE
*--- Obtiene el nombre del archivo
lcFile = LOWER(FULLPATH(laFileList[lnPtr, 1]))
*--- Insert into cursor if .EXE, .ICO or .DLL
IF INLIST(LOWER(JUSTEXT(lcFile)),"dll","exe","ico")
INSERT INTO Recursive (cFile) VALUES (lcFile)
ENDIF
ENDIF
ENDFOR
*--- Regresa al directorio padre.
CHDIR ..
ENDFUNC
IMPORTANTE:
Este procedimiento muestra cómo extraer los iconos asociados a algunos archivos. Antes de utilizar estos iconos en sus aplicaciones, debe estar seguro de que tiene los derechos para hacerlo. ¡ Lea detenidamente lo normado en EULA para estas aplicaciones antes de utilizarlas !
¡ Espero que lo disfrute !