Using PIDLs and Display Names
This section presents an example illustrating how to retrieve the location of
a special folder, walk an item identifier list, and use the
IShellFolder interface to retrieve display names. The example is a console application
that prints the display names of the folders a user would have to open to get to
the Programs folder. To display them, the application would carry out these
steps:
- Retrieve the PIDL (obtain a pointer to an item identifier list) for the
Programs folder by using the SHGetSpecialFolderLocation function.
- Bind to the desktop folder (retrieve the folder's IShellFolder interface) by using the SHGetDesktopFolder function.
- Walk the item identifier list and process elements as follows: print the
subfolder's display name, bind to the subfolder, and release the parent folder's IShellFolder interface.
Before carrying out any of the preceding steps, the application uses the
SHGetMalloc function to retrieve a pointer to the shell's
IMalloc interface, which it saves in the following global variable.
// Global pointer to the shell's IMalloc interface.
LPMALLOC g_pMalloc;
The following example shows the application's
main function. This function carries out all of the steps described previously,
although it calls the application-defined GetNextItemID and CopyItemID functions
to walk the item identifier list and the application-defined PrintStrRet
function to print the display names. Code for these application-defined functions is
shown following the code for the main function.
// main - the application's entrypoint function
int __cdecl main()
{
LPITEMIDLIST pidlPrograms;
LPSHELLFOLDER pFolder;
// Get the shell's allocator.
if (!SUCCEEDED(SHGetMalloc(&g_pMalloc)))
return 1;
// Get the PIDL for the Programs folder.
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL,
CSIDL_PROGRAMS, &pidlPrograms))) {
// Start with the desktop folder.
if (SUCCEEDED(SHGetDesktopFolder(&pFolder))) {
LPITEMIDLIST pidl;
// Process each item identifier in the list.
for (pidl = pidlPrograms; pidl != NULL;
pidl = GetNextItemID(pidl)) {
STRRET sName;
LPSHELLFOLDER pSubFolder;
LPITEMIDLIST pidlCopy;
// Copy the item identifier to a list by itself.
if ((pidlCopy = CopyItemID(pidl)) == NULL)
break;
// Display the name of the subfolder.
if (SUCCEEDED(pFolder->lpVtbl->GetDisplayNameOf(
pFolder, pidlCopy, SHGDN_INFOLDER,
&sName)))
PrintStrRet(pidlCopy, &sName);
// Bind to the subfolder.
if (!SUCCEEDED(pFolder->lpVtbl->BindToObject(
pFolder, pidlCopy, NULL,
&IID_IShellFolder, &pSubFolder))) {
g_pMalloc->lpVtbl->Free(g_pMalloc, pidlCopy);
break;
}
// Free the copy of the item identifier.
g_pMalloc->lpVtbl->Free(g_pMalloc, pidlCopy);
// Release the parent folder and point to the
// subfolder.
pFolder->lpVtbl->Release(pFolder);
pFolder = pSubFolder;
}
// Release the last folder that was bound to.
if (pFolder != NULL)
pFolder->lpVtbl->Release(pFolder);
}
// Free the PIDL for the Programs folder.
g_pMalloc->lpVtbl->Free(g_pMalloc, pidlPrograms);
}
// Release the shell's allocator.
g_pMalloc->lpVtbl->Release(g_pMalloc);
return 0;
}
Following is the GetNextItemID function. Given a pointer to an element in an
item identifier list, the function returns a pointer to the next element (or
NULL if there are no more elements). The
main function calls this function to walk the item identifier list for the
Programs folder.
// GetNextItemID - points to the next element in an item identifier
// list.
// Returns a PIDL if successful or NULL if at the end of the list.
// pdil - previous element
LPITEMIDLIST GetNextItemID(LPITEMIDLIST pidl)
{
// Get the size of the specified item identifier.
int cb = pidl->mkid.cb;
// If the size is zero, it is the end of the list.
if (cb == 0)
return NULL;
// Add cb to pidl (casting to increment by bytes).
pidl = (LPITEMIDLIST) (((LPBYTE) pidl) + cb);
// Return NULL if it is null-terminating or a pidl otherwise.
return (pidl->mkid.cb == 0) ? NULL : pidl;
}
Following is the CopyItemID function. Given a pointer to an element in an item
identifier list, the function allocates a new list containing only the
specified element followed by a terminating zero. The
main function uses this function to create single-element PIDLs, which it passes
to
IShellFolder member functions.
// CopyItemID - creates an item identifier list containing the first
// item identifier in the specified list.
// Returns a PIDL if successful or NULL if out of memory.
LPITEMIDLIST CopyItemID(LPITEMIDLIST pidl)
{
// Get the size of the specified item identifier.
int cb = pidl->mkid.cb;
// Allocate a new item identifier list.
LPITEMIDLIST pidlNew = (LPITEMIDLIST)
g_pMalloc->lpVtbl->Alloc(g_pMalloc, cb + sizeof(USHORT));
if (pidlNew == NULL)
return NULL;
// Copy the specified item identifier.
CopyMemory(pidlNew, pidl, cb);
// Append a terminating zero.
*((USHORT *) (((LPBYTE) pidlNew) + cb)) = 0;
return pidlNew;
}
The
IShellFolder::GetDisplayNameOf member function returns a display name in a
STRRET structure. The display name may be returned in one of three ways, which is
specified by the
uType member of the
STRRET structure. The
main function calls the following PrintStrRet function to print the display name.
// PrintStrRet - prints the contents of a STRRET structure.
// pidl - PIDL containing the display name if STRRET_OFFSET
// lpStr - address of the STRRET structure
- oid PrintStrRet(LPITEMIDLIST pidl, LPSTRRET lpStr)
{
LPSTR lpsz;
int cch;
switch (lpStr->uType) {
case STRRET_WSTR:
cch = WideCharToMultiByte(CP_OEMCP, WC_DEFAULTCHAR,
lpStr->pOleStr, -1, NULL, 0, NULL, NULL);
lpsz = (LPSTR) g_pMalloc->lpVtbl->Alloc(g_pMalloc, cch);
if (lpsz != NULL) {
WideCharToMultiByte(CP_OEMCP, WC_DEFAULTCHAR,
lpStr->pOleStr, -1, lpsz, cch, NULL, NULL);
printf("%s\n", lpsz);
g_pMalloc->lpVtbl->Free(g_pMalloc, lpsz);
}
break;
case STRRET_OFFSET:
printf("%s\n", ((char *) pidl) + lpStr->uOffset);
break;
case STRRET_CSTR:
printf("%s\n", lpStr->cStr);
break;
}
}
- Software for developers
-
Delphi Components
.Net Components
Software for Android Developers
- More information resources
-
MegaDetailed.Net
Unix Manual Pages
Delphi Examples
- Databases for Amazon shops developers
-
Amazon Categories Database
Browse Nodes Database