IExtractIcon - when to set the icon ?

IExtractIcon - when to set the icon ?

Post by martin curti » Thu, 03 Aug 2000 04:00:00



hi there,

i want each of my subfolders to have different icons.

to achieve this in the shell view list, i explicitly call
IExtractIcon::GetIconLocation for each pidl in my enumerated list.  it's a
simple matter to then derive the icon required for that pidl - all works
well.

in the tree, i note the pidl of the folder within which GetUIObjectOf is
called and check that in IExtractIcon::GetIconLocation.  this works fine
when stepping into my subfolders, but if i go back and select a folder's
ancestor, the icon that is being displayed is incorrect.

is there a generally accepted way of approaching this problem and a
recommended strategy for displaying per-folder icons ?

tia

martin

 
 
 

IExtractIcon - when to set the icon ?

Post by Scott Seel » Tue, 08 Aug 2000 04:00:00


Martin,

You've run into an area of the NSEs that really stinks.  Fortunately,
workarounds do exist.  I cover this exact issue on pages 309-311 of my book,
Windows Shell Programming.  "What's it say?" you ask.  Basically, you've run
into an issue with Explorer's caching mechanism.  First off, you have to let
Explorer cache the icons (shell team, correct me if I'm wrong here-- but
this is what the behavior appears to be).  If you tell it not to, it's
behavior becomes erratic and unpredictable.  If I remember correctly,
Explorer will eventually crash.  So, you let Explorer cache the icons-- big
deal.  This presents you with a new problem: What do you do if you developed
a library that does most of the work for you?  When I developed multiple
NSEs using the same library/wizard, I discovered that when I changed the
icons around I didn't always get the correct icons for the various NSEs.
Whichever NSE opened first got its icons reflected in the other NSE.  A
workaround exists here too.

For your application object (CWinApp derived, maybe?), declare a few UINT
member variables (NOT STATIC!!!).  In InitInstance(), initialize them like
so: m_yourIcon = (UINT)AfxGetApp()->LoadIcon( ICON_ID); You are casting the
HICON to a UINT.  You'll see why in a moment.

Then, to be a good C++ encapsulator, add a getter (no setter!) to your
CWinApp derived class.

For your IExtractIcon::Extract()/GetIconLocation() implementation do
something like this:

STDMETHODIMP CNSEIcon::Extract(LPCTSTR pszFile,
    UINT nIconIndex, HICON *phiconLarge,
    HICON *phiconSmall, UINT nIconSize)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());

    // Load the large version
    *phiconLarge = reinterpret_cast<HICON>( nIconIndex );

    // Load the small version
    *phiconSmall = reinterpret_cast<HICON>( nIconIndex );
    return S_OK;

Quote:}

STDMETHODIMP CNSEIcon::GetIconLocation(UINT   uFlags,
    LPTSTR szIconFile, UINT cchMax,
    int *piIndex, UINT *pwFlags)
{
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    // Tell the caller that the icon is
    // allocated on a per-folder basis.
    CNSEApp* pApp =
        dynamic_cast<CNSEApp*>(AfxGetApp());

    *pwFlags |= GIL_NOTFILENAME;
    switch( m_type )
    {
    case PIDL_FOLDER:
        *piIndex = (( uFlags & GIL_OPENICON )
            ? pApp->OpenIcon() : pApp->ClosedIcon() );
        break;
    case PIDL_DATAITEM:
        *piIndex = IDI_DATA;
        break;
    }

    return S_OK;

Quote:}

You have to load the icon into memory when the DLL is first loaded.  If you
don't the behavior will not work as intended.  I have no idea why a LoadIcon
works fine in InitInstance() but does not good in
ExtractIcon/GetIconLocation.  Voodoo programming is sometimes necessary:(


Quote:> hi there,

> i want each of my subfolders to have different icons.

> to achieve this in the shell view list, i explicitly call
> IExtractIcon::GetIconLocation for each pidl in my enumerated list.  it's a
> simple matter to then derive the icon required for that pidl - all works
> well.

> in the tree, i note the pidl of the folder within which GetUIObjectOf is
> called and check that in IExtractIcon::GetIconLocation.  this works fine
> when stepping into my subfolders, but if i go back and select a folder's
> ancestor, the icon that is being displayed is incorrect.

> is there a generally accepted way of approaching this problem and a
> recommended strategy for displaying per-folder icons ?

> tia

> martin


 
 
 

IExtractIcon - when to set the icon ?

Post by martin curti » Thu, 10 Aug 2000 04:00:00


hi scott,

many thanks, that's spot on :)

Quote:> You have to load the icon into memory when the DLL is first loaded.  If
you
> don't the behavior will not work as intended.  I have no idea why a
LoadIcon
> works fine in InitInstance() but does not good in
> ExtractIcon/GetIconLocation.

possibly some form of cache management issue ?

Quote:>Voodoo programming is sometimes necessary:(

voodoo programming keeps us one step ahead of the young guns :)

martin