You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改IFileDialog中AddPlace添加的文件夹显示名称?

问题描述

使用IFileDialog接口实现自定义文件对话框并添加Places时,遇到两个路径末尾文件夹名称相同的Place在“Application Links”下均显示为“MyAppName”,无法区分。需求是为Place设置自定义显示名称:

  • Place 1:显示名称“My application files”,对应路径C:\Users\Me\OneDrive\Documents\MyAppName
  • Place 2:显示名称“Shared application files”,对应路径C:\Users\Public\Documents\MyAppName

尝试用SHSetTemporaryPropertyForItem设置PKEY_FileName等属性未生效,相关代码如下:

// Code above here sets nameW to the Place name, and pathW to its full path
// These are both CStringW variables

// Create the IShellItem for the folder 
CComPtr<IShellItem> folder;
SHCreateItemFromParsingName(pathW, NULL, IID_PPV_ARGS(&folder));

// This section is trying to change what is displayed... but doesn't work!
PROPVARIANT pv = {0};
PropVariantInit(&pv);
pv.vt = VT_LPWSTR;
pv.pwszVal = nameW.GetBuffer();
// Here, I have tried various other properties such as PKEY_FileDescription, PKEY_FolderNameDisplay, etc. 
SHSetTemporaryPropertyForItem(folder, PKEY_FileName, pv);

// Add the place
_FileDialog->AddPlace(folder, FDAP_TOP);
解决方案

要实现自定义Place的显示名称,需解决两个核心问题:使用正确的属性键,以及正确处理字符串内存管理,具体方案如下:

方案一:修正SHSetTemporaryPropertyForItem调用

关键要点

  1. 使用正确的属性键:IFileDialog的Place列表读取的是PKEY_ItemNameDisplay属性,而非PKEY_FileName或其他属性,这是之前设置无效的主要原因。
  2. 正确管理字符串内存:不能直接将CStringW::GetBuffer()的结果赋值给PROPVARIANT的pwszVal,因为PropVariantClear会尝试释放该内存,而CStringW的内存由自身管理,会导致内存错误。需通过CoTaskMemAlloc分配独立内存并复制字符串。

修正后的代码

// 假设nameW和pathW已正确赋值为CStringW类型
CComPtr<IShellItem> folder;
SHCreateItemFromParsingName(pathW, NULL, IID_PPV_ARGS(&folder));

PROPVARIANT pv = {0};
PropVariantInit(&pv);
pv.vt = VT_LPWSTR;

// 分配内存并复制自定义名称
const int nameLen = nameW.GetLength();
pv.pwszVal = static_cast<LPWSTR>(CoTaskMemAlloc((nameLen + 1) * sizeof(WCHAR)));
if (pv.pwszVal)
{
    wcscpy_s(pv.pwszVal, nameLen + 1, nameW.GetString());
    // 设置正确的显示名称属性
    SHSetTemporaryPropertyForItem(folder, PKEY_ItemNameDisplay, pv);
}

// 将自定义Place添加到对话框
_FileDialog->AddPlace(folder, FDAP_TOP);

// 清理PROPVARIANT,释放分配的内存
PropVariantClear(&pv);

方案二:使用IShellLink包装目标路径

如果方案一仍不生效,可以通过创建IShellLink对象来包装目标文件夹路径,直接设置链接的显示名称,再转换为IShellItem添加到Place列表:

// 假设nameW和pathW已正确赋值为CStringW类型
CComPtr<IShellLinkW> shellLink;
HRESULT hr = shellLink.CoCreateInstance(CLSID_ShellLink);
if (SUCCEEDED(hr))
{
    // 设置目标文件夹路径
    shellLink->SetPath(pathW);
    // 设置自定义显示名称
    shellLink->SetDescription(nameW);

    // 将IShellLink转换为IShellItem
    CComPtr<IPersistFile> persistFile;
    hr = shellLink.QueryInterface(&persistFile);
    if (SUCCEEDED(hr))
    {
        CComPtr<IShellItem> folder;
        hr = SHCreateItemFromObject(persistFile, NULL, IID_PPV_ARGS(&folder));
        if (SUCCEEDED(hr))
        {
            // 添加到Place列表
            _FileDialog->AddPlace(folder, FDAP_TOP);
        }
    }
}

内容的提问来源于stack exchange,提问作者Liam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:32:22