windows-nt/Source/XPSP1/NT/shell/ext/cabview/xicon.cpp
2020-09-26 16:20:57 +08:00

208 lines
4.6 KiB
C++

//*******************************************************************************************
//
// Filename : XIcon.cpp
//
// Implementation file for CIconTemp and CXIcon
//
// Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
//
//*******************************************************************************************
#include "Pch.H"
#include "ThisDll.H"
#include "Unknown.H"
#include "XIcon.H"
class CIconTemp : public CObjTemp
{
public:
CIconTemp() : CObjTemp() {}
CIconTemp(HICON hi) : CObjTemp() {Attach(hi);}
~CIconTemp() {if (m_hObj) DestroyIcon(Detach());}
operator HICON() const {return((HICON)m_hObj);}
HICON Attach(HICON hObjNew) {return((HICON)CObjTemp::Attach((HANDLE)hObjNew));}
HICON Detach() {return((HICON)CObjTemp::Detach());}
} ;
BOOL CXIcon::Init(HWND hwndLB, UINT idiDef)
{
m_hwndLB = hwndLB;
m_cimlLg.Create(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 8);
m_cimlSm.Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 8);
HICON hIcon = LoadIcon(g_ThisDll.GetInstance(), MAKEINTRESOURCE(idiDef));
return(m_cimlLg && m_cimlSm && AddIcon(hIcon)>=0);
}
UINT CXIcon::GetIDString(LPTSTR pszIDString, UINT uIDLen,
LPCTSTR szIconFile, int iIndex, UINT wFlags)
{
static const TCHAR szIDFmt[] = TEXT("\"%s\" %d %08x");
TCHAR szIDString[MAX_PATH + 2*ARRAYSIZE(szIDFmt)];
int iRet = wsprintf(szIDString, szIDFmt, szIconFile, iIndex, wFlags);
lstrcpyn(pszIDString, szIDString, uIDLen);
return(iRet + 1);
}
int CXIcon::GetCachedIndex(LPCTSTR szIconFile, int iIndex, UINT wFlags)
{
TCHAR szIDString[MAX_PATH*2];
GetIDString(szIDString, ARRAYSIZE(szIDString), szIconFile, iIndex, wFlags);
int iLB = ListBox_FindStringExact(m_hwndLB, -1, szIDString);
if (iLB < 0)
{
return(-1);
}
return (int)((INT_PTR)ListBox_GetItemData(m_hwndLB, iLB));
}
int CXIcon::CacheIcons(HICON hiLarge, HICON hiSmall,
LPCTSTR szIconFile, int iIndex, UINT wFlags)
{
CIconTemp ciLarge(hiLarge);
CIconTemp ciSmall(hiSmall);
if (!hiLarge || !hiSmall)
{
return(-1);
}
TCHAR szIDString[MAX_PATH*2];
GetIDString(szIDString, ARRAYSIZE(szIDString), szIconFile, iIndex, wFlags);
int iLB = ListBox_AddString(m_hwndLB, szIDString);
if (iLB < 0)
{
return(-1);
}
int iLarge = AddIcon(ciLarge, AI_LARGE);
if (iLarge >= 0)
{
int iSmall = AddIcon(ciSmall, AI_SMALL);
if (iSmall >= 0)
{
if (iLarge == iSmall)
{
// Should always happen;
ListBox_SetItemData(m_hwndLB, iLB, iLarge);
return(iLarge);
}
ImageList_Remove(m_cimlSm, iSmall);
}
ImageList_Remove(m_cimlLg, iLarge);
}
ListBox_DeleteString(m_hwndLB, iLB);
return(-1);
}
HRESULT CXIcon::ExtractIcon(LPCTSTR szIconFile, int iIndex, UINT wFlags,
HICON *phiconLarge, HICON *phiconSmall, DWORD dwSizes)
{
return(E_NOTIMPL);
}
int CXIcon::GetIcon(IShellFolder *psf, LPCITEMIDLIST pidl)
{
int iImage = -1;
IExtractIcon *pxi;
HRESULT hres = psf->GetUIObjectOf(NULL, 1, &pidl, IID_IExtractIcon, NULL, (LPVOID *)&pxi);
if (FAILED(hres))
{
return(0);
}
CEnsureRelease erExtractIcon(pxi);
TCHAR szIconFile[MAX_PATH];
int iIndex;
UINT wFlags = 0;
hres = pxi->GetIconLocation(GIL_FORSHELL,
szIconFile, ARRAYSIZE(szIconFile), &iIndex, &wFlags);
if (FAILED(hres))
{
return(0);
}
//
// if GIL_DONTCACHE was returned by the icon handler, dont
// lookup the previous icon, assume a cache miss.
//
if (!(wFlags & GIL_DONTCACHE))
{
iImage = GetCachedIndex(szIconFile, iIndex, wFlags);
}
// if we miss our cache...
if (iImage == -1)
{
HICON hiconLarge = NULL;
HICON hiconSmall = NULL;
int cxIcon = GetSystemMetrics(SM_CXICON);
int cxSmIcon = GetSystemMetrics(SM_CXSMICON);
// try getting it from the Extract member fuction
hres = pxi->Extract(szIconFile, iIndex, &hiconLarge, &hiconSmall,
MAKELONG(cxIcon, cxSmIcon));
// S_FALSE means can you please do it
if (hres == S_FALSE)
{
hres = ExtractIcon(szIconFile, iIndex, wFlags,
&hiconLarge, &hiconSmall, MAKELONG(cxIcon, cxSmIcon));
}
if (SUCCEEDED(hres))
{
// Let CacheIcons check and destroy the hicon's
iImage = CacheIcons(hiconLarge, hiconSmall, szIconFile, iIndex, wFlags);
}
// if we failed in any way pick a default icon
if (iImage == -1)
{
if (wFlags & GIL_SIMULATEDOC)
{
iImage = 0; // II_DOCUMENT;
}
else if ((wFlags & GIL_PERINSTANCE) && PathIsExe(szIconFile))
{
iImage = 0; // II_APPLICATION;
}
else
{
iImage = 0; // II_DOCNOASSOC;
}
}
}
if (iImage < 0)
{
iImage = 0; // II_DOCNOASSOC;
}
return(iImage);
}