2012-01-03 48 views
8

Tôi đang làm việc với Delphi 7 và tôi muốn tìm ra đường dẫn của thư mục ../All Users/Documents của mình.
Tôi đã xem qua đoạn mã saudelphi nhận đường dẫn thư mục

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; 

Nó hoạt động tốt nhưng nó không hỗ trợ CSIDL_COMMON_DOCUMENTS mà trả về con đường mong muốn.

Hơn nữa, theo MS CSIDL không còn được sử dụng thay vì sử dụng KNOWNFOLDERID.
Và tôi cần phải làm việc ứng dụng này trên nhiều hệ điều hành (chỉ cửa sổ).

Tôi làm cách nào để thực hiện việc này?
Trợ giúp được đánh giá cao :)

Trả lời

5

Theo quan điểm của tôi, không có gì sai khi gọi SHGetSpecialFolderPath qua số CSIDL_COMMON_DOCUMENTS. Nếu bạn cần hỗ trợ XP thì bạn không thể sử dụng các ID thư mục đã biết. Bạn có thể viết mã sử dụng các ID thư mục đã biết trên Vista và lên, và quay trở lại CSIDL trên các hệ thống trước đó. Nhưng tại sao lại bận tâm? MS đã làm điều đó cho bạn với SHGetSpecialFolderPath.

+0

Tôi không thể tìm thấy 'CSIDL_COMMON_DOCUMENTS' dece leration trong tệp 'Shlobj.pas' của tôi. – Shirish11

+2

Nó có giá trị $ 002E bạn sẽ phải khai báo hằng số trong mã của bạn –

3

Bạn không được phép sử dụng ShGetFolderPath từ shell32.dll? Điều này giả định sử dụng windows 2000 với IE5 hoặc mới hơn.

bạn cần thêm shlobj vào dòng sử dụng cho mã sử dụng.

Vì không có định nghĩa cho SHGetFolderPath trong nguồn, bạn có thể sử dụng sau đây trước khi mã mà sử dụng nó:

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

Delphi 7 không tận dụng các phiên bản Wide của thói quen, vì vậy bạn có thể sử dụng mã này.

+0

Tôi có 'shlobj' tại khoản sử dụng của tôi và tôi không thể tìm thấy ' ShGetFolderPath' trong Delphi 7. – Shirish11

+0

Ah, ShGetFolderPath mới hơn .dcu của bạn - Tôi sẽ cập nhật câu trả lời với thay đổi cho tệp của bạn nên cho phép nó hoạt động – Petesh

2

Như David đã nêu, hãy sử dụng hàm SHGetSpecialFolderPath. Vista và W7 sẽ thực hiện chuyển đổi CSIDL/Thư mục cho bạn. Nếu bạn muốn sử dụng API mới hơn, Điều này nên để lừa: Xin lưu ý rằng điều này sẽ chỉ hoạt động từ 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

Theo đề xuất của Embarcadero trong doc này: 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ử dụng nó như thế này:

s:= GetSpecialFolder(CSIDL_LOCAL_APPDATA, true); 
Các vấn đề liên quan