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. |
|
|
|