【问题标题】:TreeView add Shell IconsTreeView 添加外壳图标
【发布时间】:2014-11-17 02:08:21
【问题描述】:

我已经创建了树视图,可以在其中添加一些项目。基本上,我想以树状查看所有目录和文件,并带有与之关联的图标。 所以我有这些功能:

  1. 将项目添加到树视图

    HTREEITEM AddItemToTree(HWND hwndTree, char *text, int nLevel)
    {
        TVINSERTSTRUCT tvins;
        static HTREEITEM hPrev = (HTREEITEM)TVI_FIRST;
        static HTREEITEM hRootItem = NULL;
        static HTREEITEM hPrevLev2Item = NULL;
        AddIconToTree(hwndTree, text); //////////// THIS IS THE FUNCTION BELOW...
        tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIS_STATEIMAGEMASK;
        tvi.iImage = 0;
        tvi.iSelectedImage = 0;
        tvi.pszText = GetFileNameFromPath(text);
        tvins.hInsertAfter = hPrev;
        tvins.item = tvi;
    
        if(nLevel == 1)
        {
            tvins.hParent = TVI_ROOT;
        }
        else if(nLevel == 2)
        {
            tvins.hParent = hRootItem;
        }
        else
        {
            TVITEM tviSetup;
            tviSetup.hItem = hPrev;
            tviSetup.mask = TVIF_PARAM;
            TVITEM * tviLocal = &tviSetup;
            TreeView_GetItem(hwndTree, tviLocal);
    
            if(nLevel > tviLocal->lParam)
            {
                tvins.hParent = hPrev;
            }
            else
            {
                HTREEITEM hPrevLocal = TreeView_GetParent(hwndTree, hPrev);
                tviLocal->hItem = hPrevLocal;
                TreeView_GetItem(hwndTree, tviLocal);
                for(int i = nLevel; i <= tviLocal->lParam;)
                {
                    HTREEITEM hPrevLocalTemp = TreeView_GetParent(hwndTree, hPrevLocal);
                    hPrevLocal = hPrevLocalTemp;
                    tviLocal->hItem = hPrevLocal;
                    TreeView_GetItem(hwndTree, tviLocal);
                }
                tviLocal->mask = TVIF_TEXT;
                TreeView_GetItem(hwndTree, tviLocal);
                tvins.hParent = hPrevLocal;
    
            }
        }
    
        hPrev = (HTREEITEM)SendMessage(hwndTree, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
    
        if(hPrev == 0)
        {
            return false;
        }
        if(nLevel == 1)
        {
            hRootItem = hPrev;
        }
    
        return hPrev;
    }
    
  2. 向树形视图添加图标:

    int AddIconToTree(HWND hwndTree, char *strPath)
    {
        SHFILEINFO sfi;
        memset(&sfi, 0, sizeof(sfi));
        SHGetFileInfo(strPath, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON);
        int index = sfi.iIcon;
    
        ICONINFO iconinfo;
        GetIconInfo(sfi.hIcon, &iconinfo);
        HBITMAP hBitmap = iconinfo.hbmColor;
        DestroyIcon(sfi.hIcon);
    
        himg = ImageList_Create(16, 16, ILC_COLOR32, 1, 1);
        int iImageList = ImageList_Add(himg, hBitmap, NULL);
        DeleteObject(hBitmap);
    
        //TreeView_SetImageList(hwndTree, himg, TVSIL_NORMAL);
        SendMessage(hwndTree, TVM_SETIMAGELIST, (WPARAM)TVSIL_NORMAL, (LPARAM)(HIMAGELIST)himg);
        MessageBox(hwnd, strPath, "Path:", MB_OK); /* Because of this msgbox I found out what is
        really happening, because without it everything I have seen when I run the program was
        treeview with icon of the last file, which was folder...So blank icon.*/
        return index;
    }
    

我的主要问题是,当我设置一些图标时,它不仅设置为我所期望的一个项目,而且设置在树视图中的所有项目上。所以基本上每个项目的图标都会被新项目的图标覆盖。顺便说一句,如果我想获取文件夹的图标,我需要使用FILE_ATTRIBUTE_DIRECTORY... 就是这样了。 任何帮助将不胜感激! 提前谢谢你:-)

【问题讨论】:

    标签: c++ listview winapi treeview icons


    【解决方案1】:

    在您的AddIconToTree 函数中,您每次都在创建一个全新的图像列表,其中只有一个图标。您需要维护相同的图像列表并向其中添加其他图标,而不是为每个项目重新创建它。

    或者,您可以使用SHGetImageList 函数获取shell 图像列表的句柄,然后将其直接分配给树。如果您不需要将任何自己的图像添加到树的图像列表中,这是一种显示文件和文件夹的系统图标的更简单方法,因为 shell 图像列表会为您处理所有这些。

    // To initialise the tree's image list - do this one time only
    HIMAGELIST himg;
    if (SUCCEEDED(SHGetImageList(SHIL_SMALL, IID_IImageList, reinterpret_cast<void**>(&himg))))
        SendMessage(hwndTree, TVM_SETIMAGELIST, (WPARAM)TVSIL_NORMAL, (LPARAM)himg);
    

    那么你的AddIconToTree 函数就变成了:

    int AddIconToTree(HWND hwndTree, char *strPath)
    {
        SHFILEINFO sfi;
        memset(&sfi, 0, sizeof(sfi));
    
        // SHGFI_SYSICONINDEX will return the icon's index within the shell image list
        SHGetFileInfo(strPath, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi),
            SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
        return sfi.iIcon;
    }
    

    当您实际将项目添加到列表时,请确保将索引分配给该项目:

    tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIS_STATEIMAGEMASK;
    tvi.iImage = tvi.iSelectedImage = AddIconToTree(hwndTree, text);
    

    【讨论】:

    • 感谢您的快速回复!好吧,我已经尝试过SHGetImageList ,但不是很成功。使用它我根本没有看到任何图标。
    • 伙计,你应该得到一枚巨大的金牌!有用!非常感谢!真的很感激 :) 不幸的是,我没有足够的声誉来投票,但至少我可以将您的答案标记为解决方案 :) 再次感谢您!
    猜你喜欢
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    • 2016-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多