Ver Mensaje Individual
  #7  
Antiguo 22-12-2008
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Reputación: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Aprovecho un ratito para publicar otra parte:

Explicado los conceptos preliminares y la enumeración de recursos, pasamos a la extracción se los recursos. He escrito dos funciones bastante similares.

La primera, ExtractResIconFromModule, extrae un grupo de imágenes de la sección de recursos de un ejecutable o dll. La extracción es un buffer que contiene el binario del resource. La segunda, GetFileMemIconFromModule, hace lo propio pero en un buffer imagen de un archivo.ico. De cada uno se estos buffer se podrá extraer, entonces, una imagen de un icono individual, pero esto lo realizarán otras funciones.

ExtractResIconFromModule, extrae un grupo de imágenes en un buffer de memoria con cabecera GRPICONDIR (o MEMICONDIR) con las entradas a cada imagen y estas. Este buffer puede usarse para pasar el recurso entero tipo RT_GROUP_ICON a una dll o ejecutable. Esto lo realizará otra función, AddIconToExe.
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;
}
Y para ilustrar el uso de esta función voy a colocar el código de AddIconToExe, que añade el recurso extraído con ExtractResIconFromModule, en un ejecutable o una dll:

Código:
//---------------------------------------------------------------------------
// grpIconDir : Buffer con el recurso del tipo RT_GROUP_ICON extraido con  ExtractResIconFromModule
// DestinoExe: Nombre de un ejecutable o dll
// ResName: Nombre que se le dará al recurso añadico al ejecutable o dll
// BorraIconResPrevio: Si es trae se borraran los recursos previos RT_GROUP_ICON del ejecutable o dll
bool  AddIconToExe(LPGRPICONDIR grpIconDir, char *DestinoExe, char* ResName, bool BorraIconResPrevio)
{
   LPGRPICONDIRENTRY IconEntry;
   LPICONIMAGE  IconImage;
   LPBYTE lpResLock;
   bool Result = true;

   if(!grpIconDir) return false;
   if(!DestinoExe || !*DestinoExe) return false;
   if(!ResName || !*ResName) return false;

   // Crea espacio para las cabeceras del icono recurso
   int HeaderSize = sizeof(GRPICONDIR)+(sizeof(GRPICONDIRENTRY)*(grpIconDir->idCount-1));

   HANDLE hUpdateRes = BeginUpdateResource(DestinoExe, BorraIconResPrevio);
   // Localizo la primera imagen del icono a pasar al .exe
   IconImage = (LPICONIMAGE)((BYTE*)grpIconDir + sizeof(GRPICONDIR) + (sizeof(GRPICONDIRENTRY)*(grpIconDir->idCount-1)));
   for(int n=0; n<grpIconDir->idCount; n++){
     lpResLock = (BYTE*)LockResource(IconImage);
     // Abrir el fichero donde añadir el icono.
     if (hUpdateRes != NULL){
       // Actualizar el resource destino
       Result &= UpdateResource(hUpdateRes,
         RT_ICON,
         MAKEINTRESOURCE(grpIconDir->idEntries[n].nID),
         MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
         lpResLock,
         grpIconDir->idEntries[n].dwBytesInRes);
     }
     // Localizo la siguiente Imagen
     IconImage = (LPICONIMAGE)((BYTE*)IconImage + grpIconDir->idEntries[n].dwBytesInRes);
   }

   // Y la grabamos como "indice" o cabecera de grupo de iconos
   Result &= UpdateResource(hUpdateRes, RT_GROUP_ICON,
        ResName,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
        grpIconDir, HeaderSize);

   // Escribir los cambios y cerrar.
   Result &= EndUpdateResource(hUpdateRes, FALSE);

   return Result;
}
Y para terminar de ilustrar estas funciones, propongo esta otra que hace uso de las dos:
Código:
//------------------------------------------------------------------------------
// Pasa todas las imágenes del primer Grupo Icono (principal por defecto del ejecutable)
// de un exe (o dll) a otro
bool AddIconToExe(char *FuenteExe, char *DestinoExe, char* ResName, bool BorraIconResPrevio)
{
    bool Result;
    BYTE* Buffer;
    int Size;    
    LPGRPICONDIR grpIconDir;
    HMODULE hModule;
    hModule = LoadLibrary(FuenteExe);

    // Calculo el tamaño necesario para el Buffer
    ExtractResIconFromModule (hModule, 0, 0, &Size);
    Buffer = new BYTE[Size];

    // Extraigo del ejecutable (hModule) el primer grupo de iconos que obtengo en el Buffer
    ExtractResIconFromModule(hModule, 0, Buffer, &Size);
    grpIconDir  = (LPGRPICONDIR)Buffer;
    
    FreeLibrary(hModule);
    if(grpIconDir)  // Si el Buffer es válido
       Result = AddIconToExe(grpIconDir, DestinoExe, ResName, BorraIconResPrevio);
    else   // Si el buffer no es válido
       Result = false;

    // Libero la memoria del Grupo de iconos antes de retornar.
    delete [] Buffer;
   
    return Result;
}
En el siguiente post publicaré el modo de guardar en un archivo, un Grupo de Iconos con las funciones GetFileMemIconFromModule y SaveResIconToFile.

Saludos.

PD: Edito para añadir otro ejemplo: AddIconToExe

Última edición por escafandra fecha: 23-12-2008 a las 01:47:11.
Responder Con Cita