![]() |
![]() |
| Paypal | FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
|||||||
| Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
|
Herramientas | Buscar en Tema | Desplegado |
|
#1
|
||||
|
||||
|
Pasar un HICON a un TIcon o a un archivo
Determinadas APIs como ExtractAssociatedIcon, devuelven un manejador HICON. Cuando queremos cargar la
imagen del Handle hIcon en un componente TIcon, la forma más directa es: Código:
Icon->Handle = hIcon; Para solventar el inconveniente he escrito una función que consigue un bloque de memoria con una imagen de un archivo.ico a partir de un Handle HICON de Windows. Este Buffer puede usarse para salvar directamente el icono en un archivo.ico o para pasar la imagen a un TIcon mediante un TMemoryStream. El código permite elegir el número de bits de color (bitCount) con el que trabajaremos, este será de 1, 4, 8, 24, ó 32. Pasamos al código. En primer lugar publico un archivo cabecera con las definiciones y estructuras necesarias. Veréis que alinea al compilador a Word dato muy importante. Este archivo lo he denominado Iconos.h: Código:
#ifndef iconosH
#define iconosH
#pragma pack( push )
#pragma pack( 2 )
typedef struct
{
BYTE bWidth; // Width of the image
BYTE bHeight; // Height of the image (times 2)
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
BYTE bReserved; // Reserved
WORD wPlanes; // Color Planes
WORD wBitCount; // Bits per pixel
DWORD dwBytesInRes; // how many bytes in this resource?
WORD nID; // the ID
} MEMICONDIRENTRY, *LPMEMICONDIRENTRY, GRPICONDIRENTRY, *LPGRPICONDIRENTRY;
typedef struct
{
WORD idReserved; // Reserved
WORD idType; // resource type (1 for icons)
WORD idCount; // how many images?
MEMICONDIRENTRY idEntries[1]; // the entries for each image
} MEMICONDIR, *LPMEMICONDIR, GRPICONDIR, *LPGRPICONDIR;
// These next two structs represent how the icon information is stored
// in an ICO file.
typedef struct
{
BYTE bWidth; // Width of the image
BYTE bHeight; // Height of the image (times 2)
BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
BYTE bReserved; // Reserved
WORD wPlanes; // Color Planes
WORD wBitCount; // Bits per pixel
DWORD dwBytesInRes; // how many bytes in this resource?
DWORD dwImageOffset; // where in the file is this image
} ICONDIRENTRY, *LPICONDIRENTRY;
typedef struct
{
WORD idReserved; // Reserved
WORD idType; // resource type (1 for icons)
WORD idCount; // how many images?
ICONDIRENTRY idEntries[1]; // the entries for each image
} ICONDIR, *LPICONDIR;
typedef struct
{
BITMAPINFOHEADER icHeader; // DIB header
RGBQUAD icColors[1]; // Color table
BYTE icXOR[1]; // DIB bits for XOR mask
BYTE icAND[1]; // DIB bits for AND mask
} ICONIMAGE, *LPICONIMAGE;
#pragma pack( pop )
//---------------------------------------------------------------------------
#endif
Código:
# include "Iconos.h"
//---------------------------------------------------------------------------
long
NColors(WORD bitCount)
{
if (bitCount == 1 || bitCount == 4 || bitCount == 8)
return 1 << bitCount;
else if (bitCount >= 24)
return 0;
return -1;
}
//---------------------------------------------------------------------------
// Devuelve una imagen de archivo.ico para poder guardar en disco....
// Reserva la memoria necesaria devolviendo en Size el Tamaño
// Requiere liberar luego la memoria con VirtualFree(Mem, 0, MEM_RELEASE);
void* hIconToMem(HICON hIcon, int BitCountPerPixel, int* Size)
{
// Localizo la información del icono y su tamaño en un fichero.ico
HDC hDC = ::GetDC(NULL); // ScreenDC
ICONINFO IconInfo;
BITMAP bmpAND={0};
BITMAP bmpXOR={0};
bool I = GetIconInfo(hIcon, &IconInfo);
GetObject(IconInfo.hbmMask, sizeof(BITMAP), &bmpAND);
GetObject(IconInfo.hbmColor, sizeof(BITMAP), &bmpXOR);
if(BitCountPerPixel==0) BitCountPerPixel=bmpXOR.bmPlanes*bmpXOR.bmBitsPixel;
int RawDataSizeAND=((((bmpAND.bmWidth*bmpAND.bmBitsPixel)+31) & ~31) >> 3)*bmpAND.bmHeight;
int RawDataSizeXOR=((((bmpXOR.bmWidth*BitCountPerPixel)+31) & ~31) >> 3)*bmpXOR.bmHeight;
int RawDataSize = RawDataSizeAND + RawDataSizeXOR;
int PalSize=(BitCountPerPixel>8 ? 0 :1 << BitCountPerPixel)<<2; // RGBQUAD 4
int AllSize= sizeof(ICONDIR)+sizeof(BITMAPINFOHEADER)+PalSize+RawDataSizeAND+RawDataSizeXOR;
int Width = bmpAND.bmWidth;
int Height = bmpAND.bmHeight;
// Reservo memoria para el fichero
BYTE* FileIconMem = (BYTE*)VirtualAlloc(0, AllSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
ICONDIR* IconDir = (ICONDIR*)FileIconMem;
// Obtengo los Bits de cada parte Mask y Color
BITMAPINFO bmiAND;
BITMAPINFO *bmiICON = (BITMAPINFO*)(FileIconMem + sizeof(ICONDIR));
LPVOID lpBitsXOR = (BITMAPINFO*)(FileIconMem + sizeof(ICONDIR) + sizeof(BITMAPINFOHEADER) + PalSize);
LPVOID lpBitsAND = (BITMAPINFO*)((BYTE*)lpBitsXOR + RawDataSizeXOR);
// Preparo la cabecera del Icon
IconDir->idReserved = 0;
IconDir->idType = 1;
IconDir->idCount = 1;
IconDir->idEntries[0].bWidth = Width;
IconDir->idEntries[0].bHeight = Height;
IconDir->idEntries[0].bColorCount = NColors(BitCountPerPixel);
IconDir->idEntries[0].bReserved = 0;
IconDir->idEntries[0].wPlanes = 0; // Color Planes
IconDir->idEntries[0].wBitCount = 0;//BitCountPerPixel; // Bits per pixel
IconDir->idEntries[0].dwBytesInRes = AllSize-sizeof(ICONDIR); // How many bytes in this resource?
IconDir->idEntries[0].dwImageOffset = sizeof(ICONDIR); // Where in the file is this image?
LPICONIMAGE IconImage = (LPICONIMAGE)(bmiICON);
memset(IconImage, 0, sizeof(BITMAPINFOHEADER));
IconImage->icHeader.biSize = sizeof(BITMAPINFOHEADER);
IconImage->icHeader.biWidth = Width;
IconImage->icHeader.biHeight = Height;
IconImage->icHeader.biPlanes = 1;
IconImage->icHeader.biBitCount = BitCountPerPixel;
IconImage->icHeader.biSizeImage = RawDataSize;
// Preparo BITMAPINFOHEADER para la Mascara (bmiAND)
memcpy(&bmiAND, bmiICON, sizeof(BITMAPINFOHEADER));
bmiAND.bmiHeader.biSizeImage = RawDataSizeAND;
bmiAND.bmiHeader.biBitCount = 1;
bmiAND.bmiHeader.biClrUsed = 1;
bmiAND.bmiHeader.biClrImportant = 1;
// Recupero los bits de cada hBitmap del icono
GetDIBits(hDC, IconInfo.hbmColor, 0, Height, lpBitsXOR, bmiICON, DIB_RGB_COLORS);
GetDIBits(hDC, IconInfo.hbmMask, 0, Height, lpBitsAND, &bmiAND, DIB_RGB_COLORS);
// Sumo las dos alturas de ambos bitmaps del icono
IconImage->icHeader.biHeight = Height*2;
ReleaseDC(0, hDC);
// Salida
*Size = AllSize;
return FileIconMem;
}
Código:
TIcon *Icon = new TIcon;
Icon->LoadFromFile("MI_ICONO.ICO");
// Convertimos el HICON a imagen en memoria del .ico
int Size;
void* FileIconMem = hIconToMem(Icon->Handle, 32, &Size);
HANDLE hFile=CreateFile("FilePath.ico", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwWritten;
WriteFile(hFile, FileIconMem, Size, &dwWritten, 0);
CloseHandle(hFile);
VirtualFree(FileIconMem, 0, MEM_RELEASE);
// Lo recuperamos para ver que ha pasado
Icon->LoadFromFile("FilePath.ico");
Image1->Picture->Icon->Assign(Icon);
Código:
// Creo un MemoryStream TMemoryStream* Stream = new TMemoryStream; // Leo el mapa del hIcon deseado int Size; void* FileIconMem = hIconToMem(hIcon, 32, &Size); // lo paso al MemoryStream Stream->Write(FileIconMem, Size); Stream->Position = 0; // Libero el mapa VirtualFree(FileIconMem, 0, MEM_RELEASE); // Creo el icono con la imagen del hIcon TIcon *Icon = new TIcon; Stream->Position = 0; // Para situar le puntero de lectura al principio del Stream Icon->LoadFromStream(Stream); // Cargo la imagen del Stream Saludos. |
|
|
|