1

I am making a bread crumb bar in Delphi and having some problems regarding sorting the dropdown of the bread crumbs.

Strangely enough, even Vista is not consequent when showing these items.

I have tried many ways to figure out what is system folders, what is zip files and what is normal folders. It seems like an easy task but so far I have not found any good way of doing it.

One way is to use TypeDisplayName from TSHFileinfo but these are localized names so I can not be sure they will be in correct order in every language.

Here is the code I use to fill the menu:

  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);

Any solution for how to get the correct sorting order? It is strange there is no way in dwAttributes of TSHFileInfo to tell if a folder is a system folder.

Thanks to Keith Giddings I managed to come up with this solution:

  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

4

1 に答える 1

2

How about using IShellFolder.CompareIds on all the pidls of your enumerated objects. That should allow you to put them in the same order as explorer does no matter which version of windows and whatever UI language.

于 2010-05-30T15:12:40.387 に答える