convert from HICON to file

本文介绍了一种从模块文件中读取并写入图标资源的方法。通过定义特定的数据结构,实现图标资源的加载、内存管理和文件输出等功能。代码示例展示了如何使用这些函数来处理图标资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

come from http://www.vckbase.com/vckbase/vckbase12/vc/nonctrls/gdi_17/1217001.htm

//h

#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;
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;
#pragma pack( pop )

typedef struct
{
 UINT   Width, Height, Colors; // Width, Height and bpp
 LPBYTE   lpBits;                // ptr to DIB bits
 DWORD   dwNumBytes;            // how many bytes?
 LPBITMAPINFO lpbi;                  // ptr to header
 LPBYTE   lpXOR;                 // ptr to XOR image bits
 LPBYTE   lpAND;                 // ptr to AND image bits
} ICONIMAGE, *LPICONIMAGE;
typedef struct
{
 BOOL  bHasChanged;                     // Has image changed?
 TCHAR  szOriginalICOFileName[MAX_PATH]; // Original name
 TCHAR  szOriginalDLLFileName[MAX_PATH]; // Original name
 UINT  nNumImages;                      // How many images?
 ICONIMAGE IconImages[1];                   // Image entries
} ICONRESOURCE, *LPICONRESOURCE;

typedef struct
{
 LPCTSTR     szFileName;
 HINSTANCE hInstance;
 LPTSTR     lpID;
} EXEDLLICONINFO, *LPEXEDLLICONINFO;

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;

 

LPICONRESOURCE ReadIconFromModuleFile(LPCTSTR szFileName,LPCTSTR lpID);
void FreeICONRESOURCE(LPICONRESOURCE pRsIcon);

BOOL WriteIconToICOFile(LPICONRESOURCE lpIR, LPCTSTR szFileName);

// cpp

#define WIDTHBYTES(bits)      ((((bits) + 31)>>5)<<2)

WORD DIBNumColors( LPSTR lpbi )
{
 WORD wBitCount;
 DWORD dwClrUsed;

 dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;

 if (dwClrUsed)
  return (WORD) dwClrUsed;

 wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;

 switch (wBitCount)
 {
 case 1: return 2;
 case 4: return 16;
 case 8: return 256;
 default:return 0;
 }
 return 0;
}

WORD PaletteSize( LPSTR lpbi )
{
 return ( DIBNumColors( lpbi ) * sizeof( RGBQUAD ) );
}
LPSTR FindDIBBits( LPSTR lpbi )
{
 return ( lpbi + *(LPDWORD)lpbi + PaletteSize( lpbi ) );
}

DWORD BytesPerLine( LPBITMAPINFOHEADER lpBMIH )
{
 return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);
}

BOOL AdjustIconImagePointers( LPICONIMAGE lpImage )
{
 // Sanity check
 if( lpImage==NULL )
  return FALSE;
 // BITMAPINFO is at beginning of bits
 lpImage->lpbi = (LPBITMAPINFO)lpImage->lpBits;
 // Width - simple enough
 lpImage->Width = lpImage->lpbi->bmiHeader.biWidth;
 // Icons are stored in funky format where height is doubled - account for it
 lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2;
 // How many colors?
 lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes * lpImage->lpbi->bmiHeader.biBitCount;
 // XOR bits follow the header and color table
 lpImage->lpXOR = (LPBYTE)FindDIBBits((LPSTR)lpImage->lpbi);
 // AND bits follow the XOR bits
 lpImage->lpAND = lpImage->lpXOR + (lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER)(lpImage->lpbi)));
 return TRUE;
}

LPICONRESOURCE ReadIconFromModuleFile(LPCTSTR lpFileName,LPCTSTR lpID )
{
 LPICONRESOURCE lpIR = NULL;
 HINSTANCE hLibrary = NULL;

 BOOL bRetValue = FALSE;
 do
 {
  hLibrary = LoadLibraryEx(lpFileName, NULL, LOAD_LIBRARY_AS_DATAFILE);
  if(hLibrary == NULL)
  {
   break;
  }

  EXEDLLICONINFO EDII;
  EDII.szFileName = lpFileName;
  EDII.hInstance = hLibrary;

  if(lpID == NULL)
  {
   break;
  }

  HRSRC hRsrc = NULL;
  hRsrc = ::FindResource(hLibrary, lpID, RT_GROUP_ICON);
  if(hRsrc == NULL)
  {
   break;
  }

  HGLOBAL hGlobal = NULL;
  hGlobal = ::LoadResource(hLibrary, hRsrc);
  if(hGlobal == NULL)
  {
   break;
  }

  LPMEMICONDIR lpIcon = NULL;
  lpIcon = (LPMEMICONDIR)LockResource(hGlobal);
  if(lpIcon == NULL)
  {
   break;
  }

  lpIR = (LPICONRESOURCE)malloc(sizeof(ICONRESOURCE) + (lpIcon->idCount - 1) * sizeof(ICONIMAGE));
  if(lpIR == NULL)
  {
   break;
  }

  lpIR->nNumImages = lpIcon->idCount;
  _tcscpy(lpIR->szOriginalDLLFileName, lpFileName);
  _tcscpy(lpIR->szOriginalICOFileName, TEXT(""));

  UINT uIndex = 0;
  for (uIndex=0; uIndex<lpIR->nNumImages; uIndex++)
  {
   hRsrc = ::FindResource(hLibrary, MAKEINTRESOURCE(lpIcon->idEntries[uIndex].nID), RT_ICON);
   if(hRsrc == NULL)
    break;
   hGlobal = ::LoadResource(hLibrary, hRsrc);
   if(hGlobal == NULL)
    break;
   lpIR->IconImages[uIndex].dwNumBytes = SizeofResource(hLibrary, hRsrc);
   lpIR->IconImages[uIndex].lpBits = (LPBYTE)malloc(lpIR->IconImages[uIndex].dwNumBytes);
   memcpy(lpIR->IconImages[uIndex].lpBits, ::LockResource(hGlobal), lpIR->IconImages[uIndex].dwNumBytes);

   if(!AdjustIconImagePointers(&(lpIR->IconImages[uIndex])))
    break;
  }

  bRetValue = (uIndex == lpIR->nNumImages);
 } while(0);

 if(!bRetValue)
 {
  FreeICONRESOURCE(lpIR);
  lpIR = NULL;
 }

 if(hLibrary != NULL)
 {
  ::FreeLibrary(hLibrary);
  hLibrary = NULL;
 }

 return lpIR;
}

void FreeICONRESOURCE(LPICONRESOURCE pRsIcon)
{
 if(pRsIcon != NULL)
 {
  DWORD dwIndex = 0;
  for(dwIndex=0; dwIndex<pRsIcon->nNumImages; dwIndex++)
  {
   free(pRsIcon->IconImages[dwIndex].lpBits);
   pRsIcon->IconImages[dwIndex].lpBits = NULL;
  }
  free(pRsIcon);
  pRsIcon = NULL;
 }
}

BOOL WriteICOHeader( HANDLE hFile, UINT nNumEntries )
{
 WORD    Output;
 DWORD dwBytesWritten;

 // Write 'reserved' WORD
 Output = 0;
 if( ! WriteFile( hFile, &Output, sizeof( WORD ), &dwBytesWritten, NULL ) )
  return FALSE;
 // Did we write a WORD?
 if( dwBytesWritten != sizeof( WORD ) )
  return FALSE;
 // Write 'type' WORD (1)
 Output = 1;
 if( ! WriteFile( hFile, &Output, sizeof( WORD ), &dwBytesWritten, NULL ) )
  return FALSE;
 // Did we write a WORD?
 if( dwBytesWritten != sizeof( WORD ) )
  return FALSE;
 // Write Number of Entries
 Output = (WORD)nNumEntries;
 if( ! WriteFile( hFile, &Output, sizeof( WORD ), &dwBytesWritten, NULL ) )
  return FALSE;
 // Did we write a WORD?
 if( dwBytesWritten != sizeof( WORD ) )
  return FALSE;
 return TRUE;
}
DWORD CalculateImageOffset( LPICONRESOURCE lpIR, UINT nIndex )
{
 DWORD dwSize;
 UINT    i;

 // Calculate the ICO header size
 dwSize = 3 * sizeof(WORD);
 // Add the ICONDIRENTRY's
 dwSize += lpIR->nNumImages * sizeof(ICONDIRENTRY);
 // Add the sizes of the previous images
 for(i=0;i<nIndex;i++)
  dwSize += lpIR->IconImages[i].dwNumBytes;
 // we're there - return the number
 return dwSize;
}

BOOL WriteIconToICOFile(LPICONRESOURCE lpIR, LPCTSTR szFileName)
{
 HANDLE     hFile;
 UINT        i;
 DWORD     dwBytesWritten;

 // open the file
 if( (hFile = CreateFile( szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE )
 {
  return FALSE;
 }
 // Write the header
 if( ! WriteICOHeader( hFile, lpIR->nNumImages ) )
 {
  CloseHandle( hFile );
  return FALSE;
 }
 // Write the ICONDIRENTRY's
 for( i=0; i<lpIR->nNumImages; i++ )
 {
  ICONDIRENTRY    ide;

  // Convert internal format to ICONDIRENTRY
  ide.bWidth = lpIR->IconImages[i].Width;
  ide.bHeight = lpIR->IconImages[i].Height;
  ide.bReserved = 0;
  ide.wPlanes = lpIR->IconImages[i].lpbi->bmiHeader.biPlanes;
  ide.wBitCount = lpIR->IconImages[i].lpbi->bmiHeader.biBitCount;
  if( (ide.wPlanes * ide.wBitCount) >= 8 )
   ide.bColorCount = 0;
  else
   ide.bColorCount = 1 << (ide.wPlanes * ide.wBitCount);
  ide.dwBytesInRes = lpIR->IconImages[i].dwNumBytes;
  ide.dwImageOffset = CalculateImageOffset( lpIR, i );
  // Write the ICONDIRENTRY out to disk
  if( ! WriteFile( hFile, &ide, sizeof( ICONDIRENTRY ), &dwBytesWritten, NULL ) )
   return FALSE;
  // Did we write a full ICONDIRENTRY ?
  if( dwBytesWritten != sizeof( ICONDIRENTRY ) )
   return FALSE;
 }
 // Write the image bits for each image
 for( i=0; i<lpIR->nNumImages; i++ )
 {
  DWORD dwTemp = lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage;

  // Set the sizeimage member to zero
  lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage = 0;
  // Write the image bits to file
  if( ! WriteFile( hFile, lpIR->IconImages[i].lpBits, lpIR->IconImages[i].dwNumBytes, &dwBytesWritten, NULL ) )
   return FALSE;
  if( dwBytesWritten != lpIR->IconImages[i].dwNumBytes )
   return FALSE;
  // set it back
  lpIR->IconImages[i].lpbi->bmiHeader.biSizeImage = dwTemp;
 }
 CloseHandle( hFile );
 return TRUE;
}

 

// call

#include "SSIconMan.h"
TCHAR g_lpFirstID[256] = {0};
UINT g_uFirstID = 0;
//////////////////////////////////////////////////////////////////////////
BOOL CALLBACK MyEnumProcedure( HANDLE  hModule, LPCTSTR  lpszType, LPTSTR  lpszName, LONG  lParam ) 
{
 TCHAR szBuffer[256];
 LONG    nIndex = LB_ERR;
 LPTSTR lpID = NULL;

 // Name is from MAKEINTRESOURCE()
 if(IS_INTRESOURCE(lpszName))
 {
  _stprintf( szBuffer, TEXT("Icon [%d]"), (DWORD)lpszName );
  g_uFirstID = (UINT)lpszName;
 }
 else
 {
  // Name is string
  _tcscpy(g_lpFirstID, lpszName);
  _stprintf( szBuffer, TEXT("Icon [%s]"), lpID );
 }

 ::MessageBox(::GetActiveWindow(), szBuffer, lpID, MB_OK);

 return TRUE;
}

 CString strDistFile;
 GetDlgItemText(IDC_EDIT_DIST, strDistFile);

 HINSTANCE hLibrary = ::LoadLibraryEx( strDistFile, NULL, LOAD_LIBRARY_AS_DATAFILE );
 if(hLibrary == NULL)
 {
  AfxMessageBox(TEXT("Not a Valid Module"));
  return;
 }

 g_uFirstID = 0;
 memset(g_lpFirstID, 0, sizeof(g_lpFirstID));

 EnumResourceNames(hLibrary, RT_GROUP_ICON, (ENUMRESNAMEPROC )MyEnumProcedure, (LPARAM)GetSafeHwnd());

 if(_tcslen(g_lpFirstID) <= 0 && g_uFirstID <= 0)
 {
  FreeLibrary(hLibrary);
  hLibrary = NULL;

  AfxMessageBox(TEXT("No Resource"));
  return;
 }
 FreeLibrary(hLibrary);
 hLibrary = NULL;

 LPICONRESOURCE lpIR = ReadIconFromModuleFile(strDistFile, /*MAKEINTRESOURCE(ID_APP_ABOUT)*/
  g_uFirstID > 0 ? MAKEINTRESOURCE(g_uFirstID) : g_lpFirstID);
 if(lpIR == NULL)
 {
  AfxMessageBox(TEXT("Read Icon failed"));
  return;

 }
 BOOL bRetValue = WriteIconToICOFile(lpIR, TEXT("D://IconNew.ico"));
 if(!bRetValue)
 {
  AfxMessageBox(TEXT("Write Icon failed"));
 }else{
  AfxMessageBox(TEXT("Write Icon successed"));
 }

 FreeICONRESOURCE(lpIR);
 lpIR = NULL;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值