CListViewCtrl 中的重复图标

Duplicated icons in CListViewCtrl

我知道主要问题来自递归调用FindFile()。通过递归调用此函数,我的 i 变为 0。但我不明白如何解决此问题。

如果可能,请提供有关如何在不完全重新设计以下所有功能的情况下修复此错误的建议。或者提供一个 link,您可以在其中阅读 CListViewCtrl.

中有关图标正确初始化的信息
void Finder::FindFile(CString szPath)
{
    HIMAGELIST hSmall{};
    CFindFile F;
    CString S = szPath + TEXT("\*.*");
    int i = 0;
    BOOL bFlag = F.FindFile(S);
    if (!bFlag)
    {
        MessageBox(TEXT("Error"), TEXT("File not found"), 0);
    }
    else
    {
        do
        {
            if (F.IsDots() == TRUE)
            {
                continue;
            }
            else
            {
                if (F.IsDirectory() == TRUE)
                {
                    View_List(F.GetFileName(), i, F.GetFilePath());
                    i++;
                    FindFile(F.GetFilePath());
                }
                else
                {
                    View_List(F.GetFileName(), i, F.GetFilePath());
                    i++;
                }
            }
        } while (F.FindNextFileW());
        F.Close();
        InitListViewImage(i, S);
    }
}

void Finder::View_List(CString name, int i, CString path)
{
    CString nameWithoutEx=std::get<0>(Split(name));
    CString extention= std::get<1>(Split(name));
    lvItem.mask = LVIF_IMAGE | LVIF_TEXT;
    lvItem.state = 0;
    lvItem.stateMask = 0;
    lvItem.iItem = i;
    lvItem.iImage = i;
    lvItem.iSubItem = 0;
    lvItem.pszText = (LPWSTR)nameWithoutEx.GetString();
    lvItem.cchTextMax = nameWithoutEx.GetLength();
    myListView.InsertItem(&lvItem);
    myListView.SetItemText(i, 1, extention.GetString());
    myListView.SetItemText(i, 2, path.GetString());
}

std::tuple<CString, CString> Finder::Split(CString buf)
{
    CString tmp = buf;
    if (buf.Find(TEXT(".")) == -1)
    {
        return { buf.GetString(),TEXT("Directory") };
    }
    else
    {
        int index = buf.Find(TEXT("."))+1;
        if (buf.Find(TEXT("."),index) != -1)
        {
            while (buf.Find(TEXT("."), index) != -1)
            {
                index = buf.Find(TEXT("."), index)+1;
            }
        }
        buf.Delete(index-1, buf.GetLength());
        tmp.Delete(0, index-1);
        return{ buf.GetString(),tmp.GetString() };
    }
}


BOOL Finder::InitListViewImage(int size, CString path)
{
    CFindFile F;
    HIMAGELIST hSmall;
    SHFILEINFO lp{};
    hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, size, 1);
    bool hFind = F.FindFile(path);
    if (!hFind)
    {
        MessageBox(TEXT("Error"), TEXT("File not found"), MB_OK | MB_ICONWARNING);
    }
    else
    {
        do
        {
            if (F.IsDots() == TRUE)
            {
                continue;
            }
            DWORD num = GetFileAttributesW(F.GetFilePath());
            SHGetFileInfoW(F.GetFilePath(), num, &lp, sizeof(lp), SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_USEFILEATTRIBUTES);
            ImageList_AddIcon(hSmall, lp.hIcon);
            DestroyIcon(lp.hIcon);
        } while (F.FindNextFileW());
        F.Close();
    }
    myListView.SetImageList(hSmall, 1);
    return TRUE;
}

您需要将 i 的值作为对 FindFile 的引用传递,这样当您递归调用它时,该值会继续递增。

void Finder::FindFile(CString szPath, int& i)
{
    HIMAGELIST hSmall{};
    CFindFile F;
    CString S = szPath + TEXT("\*.*");
//    int i = 0;  <-- not declared here, as it is now an argument
    BOOL bFlag = F.FindFile(S);
    if (!bFlag)
    {
        MessageBox(TEXT("Error"), TEXT("File not found"), 0);
    }
    else
    {
        do
        {
            if (F.IsDots() == TRUE)
            {
                continue;
            }
            else
            {
                if (F.IsDirectory() == TRUE)
                {
                    View_List(F.GetFileName(), i, F.GetFilePath());
                    i++;
                    FindFile(F.GetFilePath(), i); // <-- pass i to the recursive function
                }
                else
                {
                    View_List(F.GetFileName(), i, F.GetFilePath());
                    i++;
                }
            }
        } while (F.FindNextFileW());
        F.Close();
        InitListViewImage(i, S);
    }
}

当您从主函数或任何地方调用 FindFile 时,您需要给它一个变量作为起点,例如

main()
{
    int i = 0;
    FindFile("C:\", i);
}