Как установить отображаемое имя папки, например, с помощью "SHGetSetFolderCustomSettings()"?

Похоже, SHGetSetFolderCustomSettings позволяет установить значок, всплывающую подсказку, шаблон веб-представления и прочее, но я не смог найти, как установить LocalizedResourceName в ассоциированном desktop.ini (см. структуру SHFOLDERCUSTOMSETTINGS).

Поэтому я сейчас пишу desktop.ini напрямую, однако это сопровождается оговоркой: Explorer не обновляет свои представления должным образом, даже когда вы говорите ему обновить с помощью F5 или Ctrl + R.

Это то, что я хочу написать, используя Python (хотя не-Python-код должен быть меньшей проблемой):

[.ShellClassInfo]
LocalizedResourceName=My Folder Name
InfoTip=A customized folder

Любые идеи, как установить имя папки и правильно обновить ее в Проводнике?

Я пробовал с SHChangeNotify(SHCNE_ALLEVENTS, SHCNF_PATH, path, path), но это не похоже на обновление отображаемого имени (а также с SHCNE_RENAMEFOLDER, SHCNE_RENAMEITEM, SHCNE_UPDATEDIR, SHCNE_UPDATEITEM).

(Худший подход, вероятно, будет редактировать desktop.ini дважды... один раз напрямую, затем с этой функцией API... скорее не то, что я хочу).

О том, почему (я думаю, по крайней мере один из вас спросит):

Я храню данные проекта, используя GUID в качестве имен папок.

Однако пользователь должен увидеть понятное имя, которое также можно использовать для сортировки (и, возможно, даже сможет редактировать его, не вмешиваясь во внутреннее имя). Кроме того, низкоуровневая структура файловой системы должна быть обратно совместима с более старыми версиями программного обеспечения.

1 ответ

Используйте простой вызов IShellFolder.SetNameOf:

procedure UpdateLocalizedResourceName(const ADirectory, ANewResourceName: UnicodeString);
var
  Desktop: IShellFolder;
  Eaten: DWORD;
  DirIDList1, Child, NewChild: PItemIDList;
  Attr: DWORD;
  Folder: IShellFolder;
begin
  OleCheck(SHGetDesktopFolder(Desktop));
  try
    Attr := 0;
    OleCheck(Desktop.ParseDisplayName(0, nil, PWideChar(ADirectory), Eaten, DirIDList1, Attr));
    try
      OleCheck(SHBindToParent(DirIDList1, IShellFolder, Pointer(Folder), Child));
      try
        OleCheck(Folder.SetNameOf(0, Child, PWideChar(ANewResourceName), SHGDN_INFOLDER, NewChild));
        CoTaskMemFree(NewChild);
      finally
        Folder := nil;
      end;
    finally
      CoTaskMemFree(DirIDList1);
    end;
  finally
    Desktop := nil;
  end;
end;

ОБНОВИТЬ

Важное замечание! Параметр LocalizedResourceName должен существовать в desktop.ini перед вызовом UpdateLocalizedResourceName. В противном случае функция SetNameOf завершается ошибкой.

Другие вопросы по тегам