Delphi получить путь к папке - PullRequest
9 голосов
/ 03 января 2012

Я работаю с Delphi 7 и хочу узнать путь к моей директории .. / All Users / Documents .
Я обнаружил следующий код

uses shlobj, ...

function GetMyDocuments: string;
 var
  r: Bool;
  path: array[0..Max_Path] of Char;
 begin
  r := ShGetSpecialFolderPath(0, path, CSIDL_Personal, False) ;
  if not r then 
    raise Exception.Create('Could not find MyDocuments folder location.') ;
  Result := Path;
 end;

Работает нормально, но не поддерживает CSIDL_COMMON_DOCUMENTS, который возвращает желаемый путь.

Более того, согласно MS CSIDL больше не должен использоваться, вместо этого используйте KNOWNFOLDERID .
И мне нужно работать с этим приложением на нескольких ОС (только окна),

Как я могу это сделать?
Помощь приветствуется:)

Ответы [ 4 ]

5 голосов
/ 03 января 2012

На мой взгляд, нет ничего плохого в том, чтобы звонить SHGetSpecialFolderPath, передавая CSIDL_COMMON_DOCUMENTS. Если вам нужна поддержка XP, вы не можете использовать известные идентификаторы папок. Вы можете написать код, который использует известные идентификаторы папок в Vista и более поздних версиях и использовать CSIDL в более ранних системах Но зачем? MS сделал это для вас с SHGetSpecialFolderPath.

3 голосов
/ 03 января 2012

Разве вы не должны использовать ShGetFolderPath из shell32.dll? Это предполагает использование Windows 2000 с IE5 или новее.

вам нужно добавить shlobj к строке использования для кода, который его использует.

Поскольку в источнике нет определения SHGetFolderPath, вы можете использовать следующее перед кодом, который его использует:

function SHGetFolderPath(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWORD; pszPath: PChar): HResult; stdcall; external 'shfolder.dll' name 'SHGetFolderPathA';

Delphi 7 не использует широкую версию процедуры, поэтому вы можете использовать этот код.

2 голосов
/ 05 декабря 2013

В соответствии с рекомендациями Embarcadero в этом документе: VistaUACandDelphi.pdf

Uses SHFolder;

function GetSpecialFolder (CSIDL: Integer; ForceFolder: Boolean = FALSE): string;
CONST SHGFP_TYPE_CURRENT = 0;
VAR i: Integer;
begin
 SetLength(Result, MAX_PATH);
 if ForceFolder
 then ShGetFolderPath(0, CSIDL OR CSIDL_FLAG_CREATE, 0, 0, PChar(Result))= S_ok
 else ShGetFolderPath(0, CSIDL, 0, 0, PChar(Result));
 i:= Pos(#0, Result);
 if i> 0
 then SetLength(Result, pred(i));

 Result:= Trail (Result);
end;

Используйте его следующим образом:

s:= GetSpecialFolder(CSIDL_LOCAL_APPDATA, true);
2 голосов
/ 03 января 2012

Как уже сказал Дэвид, используйте функцию SHGetSpecialFolderPath. Vista и W7 сделают преобразование CSIDL / папки за вас. Если вы хотите использовать более новый API, это должно сработать: Обратите внимание, что это будет работать только с Vista.

unit Unit1;

interface

uses
  Windows, ActiveX, Forms, SysUtils, OleAuto, Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;


type
 TShGetKnownFolderPath = function(const rfid: TGUID; dwFlags: DWord; hToken: THandle; out ppszPath: PWideChar): HResult; stdcall;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function ShGetKnownFolderPath(const rfid: TGUID; dwFlags: DWord; hToken: THandle; out ppszPath: PWideChar): HResult;

var Shell: HModule;
    Fn: TShGetKnownFolderPath;

begin
 Shell := LoadLibrary('shell32.dll');
 Win32Check(Shell <> 0);
 try
  @Fn := GetProcAddress(Shell, 'SHGetKnownFolderPath');
  Win32Check(Assigned(Fn));
  Result := Fn(rfid, dwFlags, hToken, ppszPath);
 finally
  FreeLibrary(Shell);
 end;
end;

function GetPublicDocuments: string;
 var
  ret: HResult;
  Buffer: PWideChar;
begin
  ret := ShGetKnownFolderPath(StringToGuid('{ED4824AF-DCE4-45A8-81E2-FC7965083634}'), 0, 0, Buffer) ;
  OleCheck(ret);
  try
   Result := Buffer;
  finally
    CoTaskMemFree(Buffer);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 ShowMessage(GetPublicDocuments);
end;

end.
...