Delphi获取文件夹路径

10

我正在使用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

此外,根据微软的说法,应该停止使用CSIDL,而应使用KNOWNFOLDERID。同时,我需要在多个操作系统上(仅限Windows)使用此应用程序。

我该如何做?
感谢您的帮助 :)

4个回答

7

在我看来,调用SHGetSpecialFolderPath并传递CSIDL_COMMON_DOCUMENTS是没有问题的。如果你需要支持XP,则无法使用已知文件夹ID。你可以编写代码,在Vista和更高版本上使用已知文件夹ID,在早期系统上则回退到CSIDL。但是,为什么要费心呢?MS已经为您准备好了SHGetSpecialFolderPath


我在我的“Shlobj.pas”文件中找不到“CSIDL_COMMON_DOCUMENTS”声明。 - Shirish11
2
它有价值$002E,你将不得不在你的代码中声明这个常量。 - David Heffernan

4
你应该使用来自shell32.dll的ShGetFolderPath,这假设你在使用带有IE5或更新版本的Windows 2000。
对于使用它的代码,你需要将shlobj添加到uses行中。
由于源代码中没有SHGetFolderPath的定义,因此可以在使用它的代码之前使用以下内容:
function SHGetFolderPath(hwnd: HWND; csidl: Integer; hToken: THandle; dwFlags: DWORD; pszPath: PChar): HResult; stdcall; external 'shfolder.dll' name 'SHGetFolderPathA';

Delphi 7没有使用Wide版本的例程,因此您可以使用此代码。


我在使用Delphi 7时,在uses子句中有“shlobj”,但是找不到“ShGetFolderPath”。 - Shirish11
啊,ShGetFolderPath 比你的 .dcu 新 - 我会更新答案并更改你的文件,这样应该可以让它工作。 - Anya Shenanigans

2

正如David所说,使用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.

2

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接