Getting Friendly Names and Icons

As binary data structures, item IDs aren't much fun to look at or easy to remember. You need to get a friendlier name for an object when you display it to the user. Fortunately, each item in a folder has a display name and two icons associated with it. (One icon is displayed when the item is selected, and the other is displayed when the item is not selected.)

The code you just saw retrieved each item's display name and its icons
by calling application-defined functions. The GetName function gets the object's friendly name by using the IShellFolder::GetDisplayNameOf member function. If necessary, GetName converts the display name to Unicode characters, filling a buffer that is either allocated by the task allocator or specified by the application. It then returns a pointer to this buffer. Otherwise, GetName simply returns the offset to the display name in the identifier.

BOOL CMfcenumView::GetName (LPSHELLFOLDER lpsf,
LPITEMIDLIST lpi,
DWORD dwFlags, LPSTR lpFriendlyName)
{
BOOL bSuccess = TRUE;
STRRET str;

if (NOERROR == lpsf->GetDisplayNameOf (lpi, dwFlags, &str))
{
switch (str.uType)
{
case STRRET_WSTR:
WideCharToMultiByte (CP_ACP, // code page
0 // dwFlags
str.pOleStr, // lpWideCharStr
-1, // cchWideChar
lpFriendlyName, // lpMultiByteStr
sizeof (lpFriendlyName), // cchMultiByte
NULL, // lpDefaultChar
NULL); // lpUsedDefaultChar
break;

case STRRET_OFFSET:
lstrcpy (lpFriendlyName, (LPSTR)lpi + str.uOffset);
break;

case STRRET_CSTR:
lstrcpy (lpFriendlyName, (LPSTR) str.cStr);
break;

default:
bSuccess = FALSE;
break;
}
}

else
bSuccess = FALSE;

return bSuccess;
}

You can use the IShellFolder::SetNameOf member function to change the display name of a file object or folder. One side effect of changing the display name is that the item ID also changes.

Another application-defined function gets the selected and unselected icons for the item. You need these icons when adding the item to the tree view control so that the control can display the item's status correctly. This function fills in the iImage and iSelectedImage members of the tree view item passed in (in the second parameter) with the unselected icon image and the selected icon image, respectively. The GetIcon function, shown in this code, simply calls the SHGetFileInfo function to retrieve the correct icon:

void CMfcenumView::GetNormalAndSelectedIcons (
LPITEMIDLIST lpifq, LPTV_ITEM lptvitem)
{
// Don't check the return value here.
// If GetIcon() fails, you're in big trouble.
lptvitem->iImage = GetIcon (lpifq,
SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

lptvitem->iSelectedImage = GetIcon (lpifq,
SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_OPENICON);

return;
}

int CMfcenumView::GetIcon (LPITEMIDLIST lpi, UINT uFlags)
{
SHFILEINFO sfi;

SHGetFileInfo ((LPCSTR)lpi, 0, &sfi, sizeof (SHFILEINFO), uFlags);

return sfi.iIcon;
}