9 de marzo de 2007

Extraer íconos de archivos EXE- DLL e ICO con GdiplusX

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 !

No hay comentarios. :

Publicar un comentario