Subj. Нет ли где готовых вариантов?
(Windows-платформа, если это критично)
			
		Модератор: Модераторы
alexs писал(а):А в чём проблема?
FindFirst+FindNext и рекурсия вам в руки...
program PrintFolders;
{$APPTYPE CONSOLE}
{$mode Delphi}{$H+}
{ Консольное приложение выводит дерево папок
c помощью пространства имён оболочки Windows.}
uses
  Windows, SysUtils,ActiveX, ShlObj, ComObj;
const
  SHCONTF_FOLDERS = $20;
  SHCONTF_NONFOLDERS = $40;
  SHCONTF_INCLUDEHIDDEN = $80;
  SHGDN_NORMAL  = $0;
  SHGDN_INFOLDER  = $1;
  SHGDN_INCLUDE_NONFILESYS = $2000;
//------------------------------------------------------------------------------
{ вывод в консоль}
procedure AppendLog(const Text: string);
var
  s:string;
begin
  SetLength(s, Length(text));
  if not CharToOemA(PChar(text), PChar(s)) then s := text;
  WriteLn(s);
end;
//------------------------------------------------------------------------------
{ сдвигаем вывод для отображения иерархии }
procedure WriteLevel(Count: Integer);
var
  s: string;
begin
  s := StringOfChar(' ', Count);
  Write( s );
end;
var
  Malloc: IMalloc;
  desktop, InitShellDir: IShellFolder;
  pidlItself: PItemIDList;
  Level, CountFolder: Integer;
  CharsDone, dwAttributes, StartTime:DWORD;
  InitPath:WideString;
//------------------------------------------------------------------------------
{ получаем имя }
function GetDisplayName( pidl: PItemIDList; const STRT: STRRET ): string;
var
  P:PChar;
begin
  with STRT do
  case uType of
    STRRET_CSTR   : SetString(Result, STRT.cStr,   Length(STRT.cStr));
    STRRET_OFFSET : begin
                       P  := @PiDL.mkid.abID[STRT.uOffset - SizeOf(PiDL.mkid.cb)];
                       SetString(Result, P, PIDL.mkid.cb - STRT.uOffset);
                    end;
    STRRET_WSTR   : begin
                       Result     :=  STRT.pOleStr;
                       Malloc.Free(STRT.pOleStr);
                    end;
    end;
end;
//------------------------------------------------------------------------------
{ основная процедура обхода дерева вызывается рекурсивно }
procedure ShowFolder(folder: IShellFolder);
var
  pidlChild: PItemIDList;
  STRT: STRRET;
  Iterator: IEnumIDList;
  celtFetched: ULONG;
  child: IShellFolder;
begin
  OleCheck(folder.EnumObjects( 0 , SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN, Iterator ));
  try
    Inc(Level);
    While Iterator.Next( 1, pidlChild, celtFetched ) = NOERROR do
      try
        Olecheck(folder.GetDisplayNameOf( pidlChild, SHGDN_INFOLDER or SHGDN_INCLUDE_NONFILESYS, STRT ));
        WriteLevel(Level );
        Inc(CountFolder);
        AppendLog( GetDisplayName( pidlChild, STRT ) );
        OleCheck(folder.BindToObject( pidlChild, nil, IID_IShellFolder, Pointer(child) ));
        try
        ShowFolder( child );
        except
          // обработак ошибок
          on E:EOleException do
            AppendLog('***** EOleException:  [$'+IntToHex(E.ErrorCode, 8)+'] '+E.Message);
          on E:Exception do
            AppendLog('***** Exception: [$'+IntToHex(GetLastError, 8)+'] '+E.Message);
        end;
        child := nil;
      finally
        Malloc.Free( pidlChild );
      end;
  finally
    Dec(Level);
  end;
end;
//==============================================================================
{  НАЧАЛО }
begin
  if Paramcount > 0 then
    InitPath := ParamStr(1) else
    InitPath := ExtractFilePath(ParamStr(0));
  try
  (*
      Установка CoInitFlags имеет смысл в файлах проекта (*.dpr, *.lpr)
      и только перед инициализацией ComObj,
      в создаваемых потоках следует вызывать CoInitializeEx();
  *)
  CoInitFlags := COINIT_MULTITHREADED;  
  StartTime := GetTickCount;
  OleCheck(SHGetMalloc( Malloc ));
  try
    OleCheck(SHGetDesktopFolder( desktop ));
      try
        OleCheck(desktop.ParseDisplayName( 0, nil, PWideChar(InitPath), CharsDone,  pidlItself, dwAttributes ));
        try
          OleCheck(desktop.BindToObject(pidlItself, nil, IID_IShellFolder, InitShellDir));
          AppendLog(InitPath);
          ShowFolder( InitShellDir );
        finally
            InitShellDir := nil;         //< перед выходом лучше явно освободить
        end;
      finally
        Malloc.Free(pidlItself);
        desktop := nil;
      end;
    finally
      Malloc := nil;
    end;
  except
          on E:EOleException do
            AppendLog('***** EOleException:  [$'+IntToHex(E.ErrorCode, 8)+'] '+E.Message);
          on E:Exception do
            AppendLog('***** Exception: [$'+IntToHex(GetLastError, 8)+'] '+E.Message);
  end;
  Writeln;
  AppendLog(Utf8ToAnsi('* ГОТОВО * ')); // ух уж этот UTF8 ...
  AppendLog(Format(Utf8ToAnsi('Найдено папок %d  за %f сек. '), [CountFolder, (GetTickCount - StartTime) / 1000]));
  Writeln;
  AppendLog(Utf8ToAnsi('Для завершения нажмите ВВОД ...'));
  readln;
end.
Ism писал(а):Это привязка к Винде, нехорошо.
Вот как работать правильно с обходом файлов http://freepascal.ru/forum/viewtopic.php?t=9259
rxt писал(а):Ism писал(а):Это привязка к Винде, нехорошо.
Вот как работать правильно с обходом файлов viewtopic.php?t=9259
- Вам следует внимательно перечитать пост ТС, а для holy war о кросплатформенности завести отдельный топик.
 - Вам следует научиться передавать параметры в процедурах и функциях прежде, чем выкладывать код и судить: где правильно, а где не правильно.
 
(Windows-платформа, если это критично)
Padre_Mortius писал(а): к коду от Ism есть небольшие уточнения, но хотелось бы от вас получить более подробные претензии.
Вернуться в Free Pascal Compiler
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1