Autor Beitrag
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Mi 02.04.03 15:01 
Wenn wir von speziellen Ordnern reden meinen wir Verzeichnisse wie den Favoritenordner, Desktopordner, Send-To-Ordner usw. Also Ordner die bei jedem Rechner und bei jedem angemeldeten Benutzer wo anders im Dateisystem liegen kann. Den kompletten Pfad zu diesen Ordnern steckt auch teilweise in der Registry. Da sich diese Pfade laut Microsoft ändern können soll man die Funktion SHGetSpecialFolderLocation benutzen.

Die Funktion Suche im MSDN SHGETSPECIALFOLDERLOCATION bekommt unter anderem als Parameter eine Folder-Id übergeben. Diese Folder-Id gibt an von welchem spezial Ordner wir den Pfad haben möchten. Die Funktion und die entsprechenden Folder-Ids (Konstanten) sind in der Unit ShlObj.pas definiert. Weiter unten findes Du zwei Konstanten die die Borländer wohl vergessen haben zu definieren. In der MSDN findet ihr die Beschreibung der einzelnen Konstanten. Den Pfad bekommen wir durch den Aufruf von SHGetSpecialFolderLocation nicht als String zurück sondern in einer sogenannten ItemIDList. Um jetzt von dieser sogenannten ItemIdList auf einen String zu kommen benutzen wir die Funktion Suche im MSDN SHGETPATHFROMIDLIST.

Hier nun ein Beispiel für den Aufruf der beiden Funktionen um den Pfad vom Favoritenordner zubekommen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var
  pIdL: PItemIDList;
  Path: Array [0..Max_Path] Of Char;
Begin
  // ItemIdList für den Favorites Ordner holen
  SHGetSpecialFolderLocation (0, CSIDL_FAVORITES, pIdL);

  // ItemIdList in String umwandeln lassen
  SHGetPathFromIDList (pIDL, Path);

  // String (Verzeichnis) in Messagebox anzeigen lassen
  MessageDlg (Path, mtInformation, [mbOK], 0);
End;

Die Funktion SHGetSpecialFolderLocation belegt automatisch für die Variable pIdL Speicher. Allerdings müssen wir uns darum kümmern das dieser Speicher wieder freigegeben wird. Da es sich hier um einen fremden Speicherbereich handelt können wir diesen nicht einfach mit FreeMem (pIdl); freigeben. Wir benutzen deshalb das Speicherverwaltungsinterface IMalloc (in Unit ActiveX.pas definiert) um den Speicher wieder freizugeben:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
Var
  {...}
  Allocator: IMalloc;
Begin
  {...}
  If Succeeded (SHGetMalloc (Allocator)) Then 
    Begin
      Allocator.Free (pIdL); 
      {$IFDEF VER100} 
      Allocator.Release; 
      {$ENDIF} 
    End;
End

Das wars!

Alles in allem könnte nun eine universell einsetzbare Funktion wie folgt implementiert sein:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
Uses
  ActiveX, ShlObj;

Function GetSpecialFolder (aFolder: Integer): String;
var
  pIdL: PItemIDList;
  Path: Array [0..Max_Path] Of Char;
  Allocator: IMalloc;
Begin
  // ItemIdList für den Ordner holen
  SHGetSpecialFolderLocation (0, aFolder, pIdL);

  // ItemIdList in String umwandeln lassen
  SHGetPathFromIDList (pIDL, Path);

  // Speicher wieder freigeben
  If Succeeded (SHGetMalloc (Allocator)) Then
    Begin
      Allocator.Free (pIdL);
      {$IFDEF VER100}
      Allocator.Release;
      {$ENDIF}
    End;

  Result := Path;
End;

Ein Aufruf dieser Funktion könnte wie folgt sein:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TForm1.Button1Click(Sender: TObject);
begin
  MessageDlg (GetSpecialFolder (CSIDL_FAVORITES), mtInformation, [mbOK], 0);
end;


In der Unit ShlObj.pas fehlen noch zwei wichtige Folder-Ids. Wenn man diese braucht musst Du diese selbst definieren:
ausblenden Delphi-Quelltext
1:
2:
3:
Const
  CSIDL_LOCAL_APPDATA  = $001C;
  CSIDL_COMMON_APPDATA = $0023;


Moderiert von user profile iconTino: Hinweis von user profile iconMartin1966 eingebaut.

Für diesen Beitrag haben gedankt: Xion