2010-05-30 4 views
1

Я делаю хлебную крошку в Delphi и имею некоторые проблемы с сортировкой раскрывающихся хлебных крошек.Сортировка элементов оболочки, таких как windows explorer

Как ни странно, даже 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 Гиддингсом мне удалось придумать с этим решением:

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; 

Рой M Клевер

+0

Не могли бы вы объяснить поведение сортировки \ функции, которые вы хотите, возможно, с примером. –

+0

Hi chibacity, Я хочу, чтобы он сортировался, поэтому я получаю тот же результат, что и при нажатии на тот же элемент палитры в Vista Explorer. Но поскольку Vista не является следствием, я хочу иметь системные папки сверху, а затем обычные папки и внизу zip-файлы (папки) ... Я хочу иметь более организованный вид выпадающих меню. Теперь это выглядит немного испорченным. Я вижу, могу ли я добавить изображение к моему вопросу ... –

+0

Я не знаком с этим использованием «последовательного», и словарь не помогает мне это понять. Можете ли вы разъяснить? –

ответ

2

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

+0

Хм ... Я хочу, чтобы решение работало в любой версии Windows. Итак, вы считаете, что просто сортировать предметы, используя pidls предметов? Ну, я пошел попробовать ... Я даже не думал об этом как о решении. –

+0

Большое спасибо за ваше решение, оно отлично работает. При попытке проверить это было только то, что мне пришлось добавить SmallInt перед результатом из IShellfolder.CompareIds. function ComparePIDLs (Item1, Item2: Pointer): Integer; begin Результат: = SmallInt (IShellFld.CompareIDs (0, Item1, Item2)); конец; –