[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now


CImageList containing windows system icons

Posted on 2004-10-24
Medium Priority
Last Modified: 2013-11-20

I'm writing an app that involves the selection and manipulation of files using a CTreeCtrl.  I would very much like to have icons next to each item in the tree e.g. icons for folders and icons for the associated files eg. Icons that depict a text document etc - as in windows explorer.

Can anyone tell me how to do this?

Many Thanks

Question by:csuog
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2

Expert Comment

ID: 12395300
First, draw the icons on a single bitmap, one by one next to each other. Make each icon same size, eg 16x16 pixels. Have the image saved as bmp. Add the image to the application resources. Then somewhere duing initialization (for example your treeviews OnInitialUpdate()) create the imagelist and give ot to the treectrl

like this:

m_pIconImageList = new CImageList;
m_pIconImageList->Create( IDB_ICONS  , 16 , 1 , RGB(255,0,255) );
m_tree.SetImageList( m_pIconImageList, TVSIL_NORMAL );

where IDB_ICONS is the resource id of you icon bitmap, and RGB(255,0,255) is the transparent color - in this case pink.

Then when inserting items in the tree control do:

m_tree.InsertItem( "SomeNode" , 0 , 1 );

The 0 is the unselected image, and the 1 is the selected image for the node.

A great way to draw good icons is to use a vector based graphics program. I used openoffice's draw. Then when done, I zoom in close to the icon (mabe around 300x300 pixels, not important as long as it is quite big) and take a screenshot. The icon is then resized to 16x16 in a graphics program, I use irfanview. The resizing gives you nice small smooth looking icons which are difficult to draw by hand.
LVL 16

Accepted Solution

nonubik earned 750 total points
ID: 12399290
You need also to do some shell programming in order to get the proper icons.

Here's an excerpt from a class the does populate a checkboxed tree with folders and proper icons (starting from 'Desktop' item)

      LPITEMIDLIST pidlTemp = (LPITEMIDLIST) pidl;

      // Calculate size of list.
      UINT cb = pidl->mkid.cb + sizeof(pidl->mkid.cb);

      LPITEMIDLIST pidlRet = (LPITEMIDLIST)g_pMalloc->Alloc(cb);
      if (pidlRet)
            CopyMemory(pidlRet, pidl, cb);
      return pidlRet;

// CTargetTree message handlers

void CTargetTree::Populate(HTREEITEM hItem /*= NULL*/)
      LPITEMIDLIST      pidlDesktop;
      HRESULT                  hr;
      STRRET                  strDispName;
      TCHAR                  szDisplayName[100];

      //LPSHELLVIEW            pShellView;
      // // Get a pointer to the Desktop's IShellFolder interface. //

      hr = SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidlDesktop);
      hr = m_pSHDesktopFolder->GetDisplayNameOf(pidlDesktop, SHGDN_INFOLDER, &strDispName);
      hr = StrRetToBuf(&strDispName, pidlDesktop, szDisplayName, sizeof(szDisplayName));

      SHFILEINFO      sfi;
      HIMAGELIST      hDesktop = (HIMAGELIST)SHGetFileInfo((LPCTSTR)pidlDesktop, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

            CImageList      *pIL = CImageList::FromHandle(hDesktop);

            SetImageList(pIL, TVSIL_NORMAL);
            hItem = InsertItem(szDisplayName, sfi.iIcon, sfi.iIcon);

      CImageList      *pIl2 = GetImageList(TVSIL_STATE);
      IMAGEINFO      imgInfo;
      ZeroMemory(&imgInfo, sizeof(imgInfo));
      pIl2->GetImageInfo(0, &imgInfo);
      pIl2->Add(LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_CHECK_GRAY)));

      PopulateSubItem(m_pSHDesktopFolder, hItem);


      Expand(hItem, TVE_EXPAND);

void CTargetTree::PopulateSubItem(LPSHELLFOLDER pSHFolder, HTREEITEM hParent, int iDepth)
      LPITEMIDLIST      pIdl;
      LPENUMIDLIST      pEnumFolders;
      //SHFILEINFO            sfi;
      //HIMAGELIST            hDesktop;
      HRESULT                  hr;
      CImageList            *pIL;
      STRRET                  strDispName;
      TCHAR                  szDisplayName[MAX_PATH],szFullName[MAX_PATH];
      HTREEITEM            hItem;
      SFGAOF                  rgf = SFGAO_HASSUBFOLDER;
      _FolderData            *pFolderData;

      hr = pSHFolder->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN, &pEnumFolders);


      hr = pEnumFolders->Next(1, &pIdl, NULL);

      while(SUCCEEDED(hr) && (hr != S_FALSE))
            rgf = -1;
            hr = pSHFolder->GetAttributesOf(1, (LPCITEMIDLIST*)&pIdl, &rgf);

            //special case for Control Panel -> skip
            if(rgf  == 0xa0000004)
                  hr = pEnumFolders->Next(1, &pIdl, NULL);

            //if we have a folder
            if((rgf & SFGAO_FOLDER) && !(rgf & SFGAO_LINK))
                  hr = pSHFolder->GetDisplayNameOf(pIdl, SHGDN_INFOLDER, &strDispName);
                  hr = StrRetToBuf(&strDispName, pIdl, szDisplayName, sizeof(szDisplayName));

                  hr = pSHFolder->GetDisplayNameOf(pIdl, SHGDN_NORMAL | SHGDN_FORPARSING, &strDispName);
                  hr = StrRetToBuf(&strDispName, pIdl, szFullName, sizeof(szFullName));
//                  if((rgf & 0xf080014c) != 0xf080014c)
//                        hDesktop = (HIMAGELIST)SHGetFileInfo((LPCTSTR)pIdl, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_ICON);
//                  else
//                        hDesktop = (HIMAGELIST)SHGetFileInfo(szFullName, 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX | SHGFI_SMALLICON);

                  LPEXTRACTICON      pIcon;
                  hr = pSHFolder->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pIdl, IID_IExtractIcon, NULL, (void**)&pIcon);
                        TCHAR      szIconLoc[300];
                        int            iIndex;
                        UINT      uFlags;
                        HICON      hSmall,hLarge;

                        hr = pIcon->GetIconLocation(GIL_FORSHELL, szIconLoc, 300, &iIndex, &uFlags);
                        hr = pIcon->Extract(szIconLoc, iIndex, &hLarge, &hSmall, 16);

                        pIL = GetImageList(TVSIL_NORMAL);
                              pIL = new CImageList;
                              pIL->Create(16, 16, ILC_COLOR32, 0, 4);
                        int      iIdx = pIL->GetImageCount()-1;
                        SetImageList(pIL, TVSIL_NORMAL);
                        hItem = InsertItem(szDisplayName, iIdx, iIdx, hParent);
                        //check children
                        int      iCheck = GetCheck(hParent);
                        if(iCheck == eChecked)
                              SetCheck(hItem, iCheck);

                        //if the item is on excluded, will be unchecked (MUST be done after the above check ;)
                        //if the item is on scan folders, will be checked
                        CheckItemOnPopulate(hItem, szFullName);

                  pIL = CImageList::FromHandle(hDesktop);
                  SetImageList(pIL, TVSIL_NORMAL);
                  hItem = InsertItem(szDisplayName, sfi.iIcon, sfi.iIcon, hParent);
                  SetItemData(hItem, NULL);
                  //SHGetPathFromIDList(pIdl, szDisplayName);

                  pFolderData = new _FolderData;
                  pFolderData->pIdl = MakeCopy(pIdl);
                  pFolderData->pSHF = pSHFolder;
                  SetItemData(hItem, (DWORD_PTR)pFolderData);

                  //if it has subfolders
                  if((m_iDepth <= iDepth) && (rgf & SFGAO_HASSUBFOLDER))
                        LPSHELLFOLDER      pSHSubFolder;
                        hr = pSHFolder->BindToObject(pIdl, NULL, IID_IShellFolder, (void**)&pSHSubFolder);
                              if(m_iDepth < iDepth)
                                    PopulateSubItem(pSHSubFolder, hItem);

                              //for my computer (and others) do extra stuff
                              DoExtraStuff(szFullName, hItem);
            hr = pEnumFolders->Next(1, &pIdl, NULL);


void CTargetTree::OnTvnItemexpanding(NMHDR *pNMHDR, LRESULT *pResult)
      LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
      HTREEITEM      hItem = pNMTreeView->itemNew.hItem;
      if(pNMTreeView->action == TVE_EXPAND)
                  CWaitCursor      cw;            
                  HTREEITEM      hChild = GetChildItem(hItem);

                              _FolderData      *pFD = (_FolderData*)GetItemData(hChild);

                                          LPSHELLFOLDER      pSHSubFolder;
                                          HRESULT hr = pFD->pSHF->BindToObject(pFD->pIdl, NULL, IID_IShellFolder, (void**)&pSHSubFolder);
                                                PopulateSubItem(pSHSubFolder, hChild, 1);
                        hChild = GetNextSiblingItem(hChild);

      *pResult = 0;
LVL 16

Expert Comment

ID: 12816986
Was not my answer satisfactory?

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Here is how to use MFC's automatic Radio Button handling in your dialog boxes and forms.  Beginner programmers usually start with a OnClick handler for each radio button and that's just not the right way to go.  MFC has a very cool system for handli…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses

656 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question