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
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.