class CIconExtractor
{
public:
CIconExtractor()
: m_pImage(NULL)
{
}
HRESULT LoadIconFromApp(LPCWSTR pszFileName, CPngImage ** ppImage);
private:
CPngImage * m_pImage;
private:
static BOOL CALLBACK EnumIconProcInit(
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName,
LONG_PTR lParam);
BOOL EnumIconProc(
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName);
HRESULT GetResourceBytes(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, CAtlArray
HRESULT LoadIconFromGroup(HMODULE hModule, CAtlArray
};
///////////////////////////////////////////////////////////////////////////////
//
HRESULT CIconExtractor::LoadIconFromApp(LPCWSTR pszFileName, CPngImage ** ppImage)
{
HRESULT hr = S_OK;
HMODULE hExe; // handle to existing .EXE file
BOOL bRet;
// Load the .EXE file that contains an icon.
hExe = LoadLibraryEx(pszFileName, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (hExe == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}
bRet = EnumResourceNames(hExe, RT_GROUP_ICON, EnumIconProcInit, (LONG_PTR)(void*)this);
if(!m_pImage)
{
if(!bRet)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
hr = E_FAIL;
}
goto Cleanup;
}
*ppImage = m_pImage;
m_pImage = NULL;
Cleanup:
// Clean up.
if(hExe)
{
FreeLibrary(hExe);
}
if(m_pImage)
{
delete m_pImage;
m_pImage = NULL;
}
return hr;
}
BOOL CALLBACK CIconExtractor::EnumIconProcInit(
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName,
LONG_PTR lParam)
{
CIconExtractor * pThis = (CIconExtractor*)lParam;
return pThis->EnumIconProc(hModule, lpszType, lpszName);
}
BOOL CIconExtractor::EnumIconProc(
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName)
{
HRESULT hr = S_OK;
CAtlArray
IFC(GetResourceBytes(hModule, lpszType, lpszName, arResGroup));
IFC(LoadIconFromGroup(hModule, arResGroup));
Cleanup:
SetLastError(NO_ERROR);
return FALSE;
}
HRESULT CIconExtractor::GetResourceBytes(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName, CAtlArray
{
HRESULT hr = S_OK;
HGLOBAL hResLoad; // handle to loaded resource
HRSRC hRes; // handle/ptr. to res. info. in hExe
HANDLE hUpdateRes; // update resource handle
void *pbRes; // pointer to resource data
DWORD cbRes;
// Locate the icon resource in the .EXE file.
hRes = FindResource(hModule, lpszName, lpszType);
if (hRes == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}
// Load the icon
hResLoad = LoadResource(hModule, hRes);
if (hResLoad == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}
cbRes = SizeofResource(hModule, hRes);
// Lock the dialog box into global memory.
pbRes = LockResource(hResLoad);
if (pbRes == NULL)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}
arRes.SetCount(cbRes);
CopyMemory(arRes.GetData(), pbRes, cbRes);
Cleanup:
return hr;
}
// descriptor for the icon group
#pragma pack( push )
#pragma pack( 2 )
typedef struct
{
BYTE bWidth; // Width, in pixels, of the image
BYTE bHeight; // Height, in pixels, of the image
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
} GRPICONDIRENTRY, *LPGRPICONDIRENTRY;
typedef struct
{
WORD idReserved; // Reserved (must be 0)
WORD idType; // Resource type (1 for icons)
WORD idCount; // How many images?
GRPICONDIRENTRY idEntries[1]; // The entries for each image
} GRPICONDIR, *LPGRPICONDIR;
typedef struct
{
BYTE bWidth; // Width, in pixels, of the image
BYTE bHeight; // Height, in pixels, of the image
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 dwBytesOffset; // the ID
} ICONHEADER, *LPICONHEADER;
#pragma pack( pop )
HRESULT CIconExtractor::LoadIconFromGroup(HMODULE hModule, CAtlArray
{
HRESULT hr = S_OK;
GRPICONDIR * pDir;
WORD i;
GRPICONDIRENTRY * pCur = NULL;
GRPICONDIRENTRY * pBest = NULL;
CAtlArray
HICON hIcon = NULL;
if(arRes.GetCount() < sizeof(GRPICONDIR))
{
hr = E_FAIL;
goto Cleanup;
}
pDir = (GRPICONDIR *)(void*)arRes.GetData();
if(pDir->idCount < 1 || arRes.GetCount() < sizeof(GRPICONDIR) + (pDir->idCount - 1) * sizeof(GRPICONDIRENTRY))
{
hr = E_FAIL;
goto Cleanup;
}
//
// find best icon
//
pCur = pBest = &pDir->idEntries[0];
for(i = 0; i < pDir->idCount; i++)
{
pCur = &pDir->idEntries[i];
if(pCur->wBitCount > pBest->wBitCount)
{
pBest = pCur;
}
else if(pCur->bWidth > pBest->bWidth)
{
pBest = pCur;
}
}
//
// load best icon
//
IFC(GetResourceBytes(hModule, RT_ICON, MAKEINTRESOURCE(pBest->nID), arIcon));
hIcon = CreateIconFromResource(arIcon.GetData(), arIcon.GetCount(), TRUE, 0x00030000);
if(!hIcon)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Cleanup;
}
{
CMyImage WndImage;
if(pBest->wBitCount == 0x20)
{
CMyIcon::Load(arIcon.GetData(), arIcon.GetCount(), WndImage);
}
else
{
CIconToImageConverter cnv;
IFC(cnv.GetImage(hIcon, WndImage));
goto Cleanup;
}
m_pImage = new CPngImage;
if(m_pImage == NULL)
{
goto Cleanup;
}
m_pImage->Encode(WndImage);
}
Cleanup:
if(hIcon)
{
DestroyIcon(hIcon);
}
return hr;
}
No comments:
Post a Comment