Using the IShellFolder interface

Started by
5 comments, last by Yann L 21 years, 5 months ago
OK, so I would like to enumerate available desktop folders, including some virtual ones. Pretty much like the explorer tree: ''My Computer'' with all it''s subfolders, drives, user defined desktop folders, ''My Documents'', etc, and the network neighbourhood. But not things like printers or trashcan. I''ll also need additional information about each entry, ie. filepath and icon. Working mostly under Unix, I''m not very familiar with Windows COM programming. As far as I got on MSDN, the IShellFolder interface seems to be the way to go. But there is not much indepth information available, the whole thing expects you to be pretty proficient with MFC and/or COM (which I am not). Does anyone have a short code snippet on how to use IShellFolder ? A short pseudocode framework would be enough to get me started. Thanks ! / Yann
Advertisement
this "short" (untested) code snippet should give you file paths of desktop entities:

  CComPtr<IShellFolder> psf;SHGetDesktopFolder(&psf);CComPtr<IEnumIDList> penum;psf->EnumObjects(HwndForUserInteraction, SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN, &penum);LPITEMIDLIST pidl;ULONG fetched;while (penum->Next(1, &pidl, &fetched) == NOERROR) {	// pidl has the pidl of current object relative to psf	// this will get its path	// first, get absolute pidl	LPITEMIDLIST sf_pidl;	// since we used desktop folder, we can use SHGetSpecialFolderLocation to get its pidl	// you probably want to move this call out of the loop	SHGetSpecialFolderLocation(HwndForUserInteraction, CSIDL_DESKTOP, &sf_pidl);	// if you don''t want to use ILCombine, you''ll have to read up on pidls and concatenating them manually	// not really pleasant	// some source code is in mssdk\Samples\winui\Shell\SampView\PidlMgr.Cpp	LPITEMIDLIST absolute_pidl = ILCombine(sf_pidl, pidl);	// get path from absolute pidl	TCHAR Path[MAX_PATH];	SHGetPathFromIDList(absolute_pidl, Path);	// can use IShellFolder::GetAttributesOf for more info	// free pidls	SHFree(pidl);	SHFree(absolute_pidl);	SHFree(sf_pidl);	// or if you don''t want to use SHFree, use	CComPtr<IMalloc> pmalloc;	SHGetMalloc(&pmalloc);	pmalloc->Free(pidl);	pmalloc->Free(absolute_pidl);	pmalloc->Free(sf_pidl);}// CComPtr will call Release for everything  

now if you want to get icons, that''s trickier. i can think of a way that requires hooking into explorer.exe and getting things out of desktop''s imagelist, based on Jeffrey Richter''s Desktop Item Position Saver (DIPS) application. if you''re interested, i''ll dig out my cd and post source to that thingy.
You can get icon info via ShGetFileInfo. Here''s my example which enumerates the desktop (MakeIconList is my func, not the shells.) I have other examples if needed:

  static BOOL MakeDTopList( HWND hWnd, HWND hWndProgman, tdDTopProps *pProps, tdDTopRTime *pRTime, HBITMAP *phBitmap ){    tdShelIcons myIcons;     myIcons.iNumIcons = 0;    myIcons.phIcon    = NULL;     BOOL bSmal = pProps->myShelProps.bUseSmal;     SHFILEINFO    fi;    LPMALLOC      pMem    = NULL;    LPSHELLFOLDER pDTF    = NULL;    LPENUMIDLIST  pEIL    = NULL;    LPITEMIDLIST  pDTIcon = NULL;     if( SHGetMalloc(&pMem) == NOERROR ) {        if( SHGetDesktopFolder(&pDTF) == NOERROR ) {            if( pDTF->EnumObjects(hWnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &pEIL) == NOERROR ) {                while( pEIL->Next(1, &pDTIcon, NULL) == NOERROR ) {                    myIcons.iNumIcons++;                    if( SHGetFileInfo((LPCTSTR)pDTIcon, 0, &fi, sizeof(fi), SHGFI_PIDL | SHGFI_ICON | (bSmal ? SHGFI_SMALLICON : SHGFI_LARGEICON)) ) {                        myIcons.phIcon = (HICON *)realloc(myIcons.phIcon, sizeof(HICON)*myIcons.iNumIcons);                        myIcons.phIcon[myIcons.iNumIcons-1] = fi.hIcon;                    }                    pMem->Free(pDTIcon);                }                pEIL->Release();            }            pDTF->Release();        }        pMem->Release();    }     BOOL bReturn = MakeIconList(hWnd, &pProps->myShelProps, &myIcons, &pProps->mySkin.myShelSkin, phBitmap);     pRTime->iNumIcons = myIcons.iNumIcons;     if( myIcons.phIcon )        free(myIcons.phIcon);     return bReturn;}  
Thanks for the fast replies, they''re very helpful. I''ll try it out tonight and report back.

Cheers !

/ Yann
For background info and additional code snippets, you might also find this url helpful: Shell Explorer''s Cookbook


"Beautiful maiden," answered Candide, "when a man is in love, is jealous, and has been flogged by the Inquisition, he becomes lost to all reflection."
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Great, it works. Thanks for the help everybody.

Lessbread, that''s a pretty interesting site. Definitely goes into my bookmarks.
quote:Original post by Yann L
Lessbread, that''s a pretty interesting site. Definitely goes into my bookmarks.


I thought so too - just the right amount of detail.

One thing to note about bookmarking that site, check that the bookmark''s name ends up "Shell Explorer''s Cookbook" and if it doesn''t you might want to change it. Mozilla names bookmarks using a page''s title - and the title of that page is "Contents". Needlesstosay, that name doesn''t make it easy to find the mark again. The problem might not manifest with other browsers (YMMV).



"Beautiful maiden," answered Candide, "when a man is in love, is jealous, and has been flogged by the Inquisition, he becomes lost to all reflection."
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man

This topic is closed to new replies.

Advertisement