Сортировка объектов оболочки как Windows Explorer

Я делаю панель панировочных сухарей в Delphi и имею некоторые проблемы относительно сортировки выпадающих из панировочных сухарей.

Странно достаточно даже Vista не последовательна при показе этих объектов.

Я попробовал много способов выяснить то, что является системными папками, что является zip-файлами и что является нормальными папками. Это походит на легкую задачу, но до сих пор я не нашел хорошего способа сделать его.

Один путь состоит в том, чтобы использовать TypeDisplayName от TSHFileinfo, но они локализуются имена, таким образом, я не могу быть уверен, что они будут в правильном порядке на каждом языке.

Вот код, который я использую для заполнения меню:

  bool:= IsDesktop(SelectedPIDL);
  if bool then
    OleCheck(SHGetDesktopFolder(CurFolder))
  else
    OleCheck(DesktopShellFolder.BindToObject(SelectedPIDL, nil, IID_IShellFolder, Pointer(CurFolder)));
  if CurFolder.EnumObjects(0, SHCONTF_FOLDERS, EnumIDList) = NOERROR then
  begin
    while EnumIDList.Next(1, CurPidl, Fetched) = S_OK do
    begin
      FName:= GetDisplayName(CurFolder, CurPidl, SHGDN_NORMAL);
      Text:= GetPIDLNameForAddressBar(CurFolder, CurPidl);
      if bool then
        Text:= PSpecialFolderItem(SpecialFolders[0]).Name + '\' + Text;
      if Text[Length(Text)] <> '\' then
        Text:= Text + '\';
      NewPidl:= ConcatPIDLs(SelectedPIDL, CurPidl);
      SHGetFileInfo(PChar(NewPidl), 0, SFI, SizeOf(SFI), SHGFI_ATTRIBUTES or SHGFI_PIDL or
        SHGFI_SYSICONINDEX or SHGFI_TYPENAME);

      n:= SFI.dwAttributes;
      MenuList.Add(GetAttr(n) + FName);

      AddMenuItem(Text, FName, SFI.iIcon);
      CoTaskMemFree(CurPidl);
      CoTaskMemFree(NewPidl);
    end;
  end;
  CoTaskMemFree(SelectedPIDL);

Какое-либо решение для того, как получить корректный порядок сортировки? Странно, что нет никакого пути в dwAttributes TSHFileInfo, чтобы сказать, является ли папка системной папкой.

Благодаря Keith Giddings мне удалось предложить это решение:

  PidlList:= TList.Create;
  // Add PIDLs for sorting
  bool:= IsDesktop(SelectedPIDL);
  if bool then
    OleCheck(SHGetDesktopFolder(IShellFld))
  else
    OleCheck(DesktopShellFolder.BindToObject(SelectedPIDL, nil, IID_IShellFolder, Pointer(IShellFld)));
  if IShellFld.EnumObjects(0, SHCONTF_FOLDERS, EnumIDList) = NOERROR then
    while EnumIDList.Next(1, CurPidl, Fetched) = S_OK do
      PidlList.Add(CurPidl);
  // Sort it ...
  PidlList.Sort(ComparePIDLs);
  // Get display name and icon for item
  for i:= 0 to PidlList.Count - 1 do
  begin
    CurPidl:= PidlList[i];
    FName:= GetDisplayName(IShellFld, CurPidl, SHGDN_NORMAL);
    Text:= GetPIDLNameForAddressBar(IShellFld, CurPidl);
    if bool then
      Text:= PSpecialFolderItem(SpecialFolders[0]).Name + '\' + Text;
    if Text[Length(Text)] <> '\' then
      Text:= Text + '\';
    NewPidl:= ConcatPIDLs(SelectedPIDL, CurPidl);
    SHGetFileInfo(PChar(NewPidl), 0, SFI, SizeOf(SFI), SHGFI_ATTRIBUTES or SHGFI_PIDL or
      SHGFI_SYSICONINDEX or SHGFI_TYPENAME);
    AddMenuItem(Text, FName, SFI.iIcon);
    CoTaskMemFree(NewPidl);
  end;
  CoTaskMemFree(SelectedPIDL);
  for i:= PidlList.Count - 1 downto 0 do
  begin
    CoTaskMemFree(PidlList[i]);
    PidlList.Delete(i);
  end;
  // We are done free it
  PidlList.Free;

function ComparePIDLs(Item1, item2: Pointer): Integer;
begin
  Result:= SmallInt(IShellFld.CompareIDs(0, Item1, Item2));
end;

Roy M Klever

1
задан Sheng Jiang 蒋晟 2 June 2010 в 21:45
поделиться

1 ответ

Как насчет использования IShellFolder.CompareIds на всех pidl ваших перечисляемых объектов. Это должно позволить вам разместить их в том же порядке, что и проводник, независимо от того, какая версия окон и какой язык пользовательского интерфейса.

2
ответ дан 3 September 2019 в 00:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: