代码之家  ›  专栏  ›  技术社区  ›  c00000fd

具有ofn_allowmultipselect的cfiledialog快捷方式的结果不正确

  •  2
  • c00000fd  · 技术社区  · 7 年前

    有人能告诉我我在这里做错了什么吗?

    MFC项目,我正在使用 CFileDialog 要让用户选择多个文件,例如:

    CFileDialog fd(TRUE, NULL, NULL,
        OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ALLOWMULTISELECT, 
        NULL, this);
    
    if(fd.DoModal() == IDOK)
    {
        //Multi-selection
        CString strPaths;
        POSITION fileNamesPosition = fd.GetStartPosition();
    
        while(fileNamesPosition != NULL)
        {
            if(!strPaths.IsEmpty())
                strPaths += L"\n";
    
            strPaths += fd.GetNextPathName(fileNamesPosition);
        }  
    
        AfxMessageBox(strPaths);
    }
    

    如果说,有两个快捷方式文件:

    shortcut_1.lnk 引用的文件: "D:\Folder\Project_B\Release\Name of Project B.exe"

    shortcut_2.lnk 那是指 "D:\Folder\Project_A\Release\Name of Project A.exe"

    如果我从上面代码生成的“文件打开”对话框中选择这两个选项,我的结果 strPaths 变成以下错误:

    D:\Folder\Project_A\Release\Name of Project A.exe
    D:\Folder\Project_A\Release\Name of Project B.exe
    

    第二条路错了!

    2 回复  |  直到 7 年前
        1
  •  4
  •   zett42    7 年前

    使用 GetStartPosition() GetNextPathName() 功能一团糟。首先,他们使用老式的API which depends on a correct return buffer size defined via OPENFILENAME struct . MFC 小心点!正如您的问题所显示的,它还存在链接问题,即使缓冲区大小足够大。

    省去头痛,用 Vista+ API ,可通过 CFileDialog::GetIFileOpenDialog() .

    下面是一个工作代码示例:

    CFileDialog fd( TRUE, NULL, NULL,
        OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_ALLOWMULTISELECT,
        NULL, nullptr );
    
    if (fd.DoModal() == IDOK)
    {
        //Multi-selection
        CString strPaths;
    
        CComPtr<IFileOpenDialog> piod = fd.GetIFileOpenDialog();
        ASSERT( piod );
    
        CComPtr<IShellItemArray> pResults;
        if( SUCCEEDED( piod->GetResults( &pResults ) ) )
        {
            DWORD count = 0; pResults->GetCount( &count );
            for( DWORD i = 0; i < count; ++i )
            {
                CComPtr<IShellItem> pItem;
                if( SUCCEEDED( pResults->GetItemAt( i, &pItem ) ) )
                {
                    CComHeapPtr<wchar_t> pPath;
                    if( SUCCEEDED( pItem->GetDisplayName( SIGDN_FILESYSPATH, &pPath ) ) )
                    {
                        if( !strPaths.IsEmpty() )
                            strPaths += L"\n";
                        strPaths += pPath;
                    }
                }
            }
        }
    
        AfxMessageBox( strPaths );
    }
    
        2
  •  2
  •   Remy Lebeau    7 年前

    听上去像个虫子 CFileDialog .

    通常,返回的路径是当前显示的目录路径和选定文件名的串联。如果是 lnk 文件,也许 文件对话框 只提取目标文件名并将其连接到 LNK 文件,而不仅仅返回 LNK 文件。很难说没有看到的实际源代码 文件对话框 .

    为了避免这种行为,可以包括 OFN_NODEREFERENCELINKS 在调用对话框时标记,以便获得实际 LNK 文件,然后您可以使用 IShellLink 在对话框被取消后。

    推荐文章