Fórum Como pegar o PATH do desktop conforme o SO atual #225385
12/04/2004
0
Como pegar o PATH do desktop conforme o SO atual
E se possivel... não só p PATH e sim Meus Documentos, Diretorio do SO e etc etc
Isso para Win9x, MÉ, NT, 2000m XP
:shock:
E se possivel... não só p PATH e sim Meus Documentos, Diretorio do SO e etc etc
Isso para Win9x, MÉ, NT, 2000m XP
:shock:
Kristian
Curtir tópico
+ 0
Responder
Posts
12/04/2004
Martins_vicente
Caro kristian,
Encontrei a matéria abaixo num fórum internacional sobre delphi. Ela fala sobre a chamada a uma API do windows para obter o PATH de várias pastas do sistema.
Obs.: Eu li... mas não consegui fazer o exemplo funcionar... caso você consiga me dê um alô!
===============================================
Path / directory name for ´My Computer´
Christian Piene Gundersen <j.c.p.gundersen@jusstud.uio.no>
This is a rather complicated matter, so if it isn´t vital to your application, I suggest that you spend your time better than digging into it. However, I´ll try to point you in the right direction.
The windows 32 operating system is based on a shell which uses virtual folders, like ´my computer´, ´desktop´ and ´recycle bin´. Some of these folders are part of the physical file system. That is they have a corresponding directory in the file system. This is the case with ´desktop´ and ´recycle bin´. These directories can be used as InitialDir for the TOpenDialog, but first you have to get their physical location, which can be different on different computers. To get the physical location of these folders, you have to use some special API calls (see example below). Other folders, like ´my computer´ and ´printers´ are not part of the file system - they are only virtual. I´ve noticed that you can browse to these folders using the TOpenDialog, but I don´t think they can be used as InitialDir.
Virtual folders are (a bit simplified) of the type SHITEMID (item identifier). They are normally accessed using pointers to item identifiers list (PIDL). To get the PIDL of a special folder, you can use the SHGetSpecialFolder function. The physical location of the corresponding directory can then be obtained by passing the PIDL to the GetPathFromIDList function. If the folder is part of the file system, the function will return the path as a string (which can be used as InitialDir). But if you want the OpenDialog to start in a folder that is only virtual (like ´my computer´), you´ll have to make it accept a PIDL as InitialDir, which I don´t think it will. My guess is that the TOpenDialog uses PIDLs when browsing, but only accepts physical directories as InitialDir.
Here is an example that shows how to get the ´recent documents´ path and use it as InitialDir:
--------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
PIDL: Pointer;
Path: LPSTR;
const
CSIDL_RECENT = $0008;
begin
Path := StrAlloc(MAX_PATH);
SHGetSpecialFolderLocation(Handle, CSIDL_RECENT, @PIDL);
if SHGetPathFromIDList(PIDL, Path) then // returns false if folder isn´t
part of file system
begin
OpenDialog1.InitialDir := Path;
OpenDialog1.Execute;
end;
StrDispose(Path);
end;
--------------------------------------------------------------------------------
I think you´ll have to write a wrapper for these API calls. They are found in shell32.dll. The best advice I can give you if you want to dig into this is to study the ShlObj.h file. I don´t program in C myself, but I found it very useful.
Some constants you may need:
--------------------------------------------------------------------------------
CSIDL_DESKTOP = $0000;
CSIDL_PROGRAMS = $0002;
CSIDL_CONTROLS = $0003;
CSIDL_PRINTERS = $0004;
CSIDL_PERSONAL = $0005;
CSIDL_STARTUP = $0007;
CSIDL_RECENT = $0008;
CSIDL_SENDTO = $0009;
CSIDL_BITBUCKET = $000a;
CSIDL_STARTMENU = $000b;
CSIDL_DESKTOPDIRECTORY = $0010;
CSIDL_DRIVES = $0011; // My Computer
CSIDL_NETWORK = $0012;
CSIDL_NETHOOD = $0013;
CSIDL_FONTS = $0014;
CSIDL_TEMPLATES = $0015;
Encontrei a matéria abaixo num fórum internacional sobre delphi. Ela fala sobre a chamada a uma API do windows para obter o PATH de várias pastas do sistema.
Obs.: Eu li... mas não consegui fazer o exemplo funcionar... caso você consiga me dê um alô!
===============================================
Path / directory name for ´My Computer´
Christian Piene Gundersen <j.c.p.gundersen@jusstud.uio.no>
This is a rather complicated matter, so if it isn´t vital to your application, I suggest that you spend your time better than digging into it. However, I´ll try to point you in the right direction.
The windows 32 operating system is based on a shell which uses virtual folders, like ´my computer´, ´desktop´ and ´recycle bin´. Some of these folders are part of the physical file system. That is they have a corresponding directory in the file system. This is the case with ´desktop´ and ´recycle bin´. These directories can be used as InitialDir for the TOpenDialog, but first you have to get their physical location, which can be different on different computers. To get the physical location of these folders, you have to use some special API calls (see example below). Other folders, like ´my computer´ and ´printers´ are not part of the file system - they are only virtual. I´ve noticed that you can browse to these folders using the TOpenDialog, but I don´t think they can be used as InitialDir.
Virtual folders are (a bit simplified) of the type SHITEMID (item identifier). They are normally accessed using pointers to item identifiers list (PIDL). To get the PIDL of a special folder, you can use the SHGetSpecialFolder function. The physical location of the corresponding directory can then be obtained by passing the PIDL to the GetPathFromIDList function. If the folder is part of the file system, the function will return the path as a string (which can be used as InitialDir). But if you want the OpenDialog to start in a folder that is only virtual (like ´my computer´), you´ll have to make it accept a PIDL as InitialDir, which I don´t think it will. My guess is that the TOpenDialog uses PIDLs when browsing, but only accepts physical directories as InitialDir.
Here is an example that shows how to get the ´recent documents´ path and use it as InitialDir:
--------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
PIDL: Pointer;
Path: LPSTR;
const
CSIDL_RECENT = $0008;
begin
Path := StrAlloc(MAX_PATH);
SHGetSpecialFolderLocation(Handle, CSIDL_RECENT, @PIDL);
if SHGetPathFromIDList(PIDL, Path) then // returns false if folder isn´t
part of file system
begin
OpenDialog1.InitialDir := Path;
OpenDialog1.Execute;
end;
StrDispose(Path);
end;
--------------------------------------------------------------------------------
I think you´ll have to write a wrapper for these API calls. They are found in shell32.dll. The best advice I can give you if you want to dig into this is to study the ShlObj.h file. I don´t program in C myself, but I found it very useful.
Some constants you may need:
--------------------------------------------------------------------------------
CSIDL_DESKTOP = $0000;
CSIDL_PROGRAMS = $0002;
CSIDL_CONTROLS = $0003;
CSIDL_PRINTERS = $0004;
CSIDL_PERSONAL = $0005;
CSIDL_STARTUP = $0007;
CSIDL_RECENT = $0008;
CSIDL_SENDTO = $0009;
CSIDL_BITBUCKET = $000a;
CSIDL_STARTMENU = $000b;
CSIDL_DESKTOPDIRECTORY = $0010;
CSIDL_DRIVES = $0011; // My Computer
CSIDL_NETWORK = $0012;
CSIDL_NETHOOD = $0013;
CSIDL_FONTS = $0014;
CSIDL_TEMPLATES = $0015;
Responder
Gostei + 0
11/06/2016
Linscomt Silva
Faz tempo que postaram mas vou por o exemplo que fiz no XE8 não testei nos anteriores, caso queiram então adaptem:
{
Essas constantes são encontrado na unit "Winapi.ShlObj" ,
então não precisam declarar, só a unit caso não seja declarada automaticamente.
CSIDL_DESKTOP = $0000;
CSIDL_PROGRAMS = $0002;
CSIDL_CONTROLS = $0003;
CSIDL_PRINTERS = $0004;
CSIDL_PERSONAL = $0005;
CSIDL_STARTUP = $0007;
CSIDL_RECENT = $0008;
CSIDL_SENDTO = $0009;
CSIDL_BITBUCKET = $000a;
CSIDL_STARTMENU = $000b;
CSIDL_DESKTOPDIRECTORY = $0010;
CSIDL_DRIVES = $0011; // My Computer
CSIDL_NETWORK = $0012;
CSIDL_NETHOOD = $0013;
CSIDL_FONTS = $0014;
CSIDL_TEMPLATES = $0015;
}
function pegarpath(H:HWND; CSIDL:integer):string;
var
//PIDL: Pointer; //não precisa só está para lembrar o anterior
Pitm:PItemIDList; //criei por pedir variavel identica coisa de XE*, D7 dava para adaptar com pointer, tem uma explicação mas não agora
//Path: LPSTR; //não precisa só está para lembrar o anterior
PathW:PWideChar; //
//PathAns:AnsiString; // não precisa foi um teste meu
begin
//Path := pansichar(StrAlloc( 127 )); // não precisa , foi para lembrar
PathW := StrAlloc( MAX_PATH );
SHGetSpecialFolderLocation( H, CSIDL, Pitm);
if SHGetPathFromIDList(Pitm, PathW ) then // returns false if folder isn´t retorna falso se não existir a pasta/diretório
//Part of file system
begin
//OpenDialog1.InitialDir := Path; // não precisa , foi para lembrar use se quiser
//OpenDialog1.Execute; // não precisa , foi para lembrar use se quiser
result := PathW;
end;
StrDispose(PathW);
end;
Estou usando assim
function pegarpath(H:HWND; CSIDL:integer):string;
var
PIDL: Pointer;
Pitm:PItemIDList;
PathW:PWideChar;
begin
PathW := StrAlloc( MAX_PATH );
SHGetSpecialFolderLocation( H, CSIDL, Pitm);
if SHGetPathFromIDList(Pitm, PathW ) then
result := PathW
else
result := '##DiretorioNIL';
StrDispose(PathW);
end;
e chamando assim
procedure BotaoExec;
begin
edit.text := pegarpath( Handle, CSIDL_FONTS );
end;
{
Essas constantes são encontrado na unit "Winapi.ShlObj" ,
então não precisam declarar, só a unit caso não seja declarada automaticamente.
CSIDL_DESKTOP = $0000;
CSIDL_PROGRAMS = $0002;
CSIDL_CONTROLS = $0003;
CSIDL_PRINTERS = $0004;
CSIDL_PERSONAL = $0005;
CSIDL_STARTUP = $0007;
CSIDL_RECENT = $0008;
CSIDL_SENDTO = $0009;
CSIDL_BITBUCKET = $000a;
CSIDL_STARTMENU = $000b;
CSIDL_DESKTOPDIRECTORY = $0010;
CSIDL_DRIVES = $0011; // My Computer
CSIDL_NETWORK = $0012;
CSIDL_NETHOOD = $0013;
CSIDL_FONTS = $0014;
CSIDL_TEMPLATES = $0015;
}
function pegarpath(H:HWND; CSIDL:integer):string;
var
//PIDL: Pointer; //não precisa só está para lembrar o anterior
Pitm:PItemIDList; //criei por pedir variavel identica coisa de XE*, D7 dava para adaptar com pointer, tem uma explicação mas não agora
//Path: LPSTR; //não precisa só está para lembrar o anterior
PathW:PWideChar; //
//PathAns:AnsiString; // não precisa foi um teste meu
begin
//Path := pansichar(StrAlloc( 127 )); // não precisa , foi para lembrar
PathW := StrAlloc( MAX_PATH );
SHGetSpecialFolderLocation( H, CSIDL, Pitm);
if SHGetPathFromIDList(Pitm, PathW ) then // returns false if folder isn´t retorna falso se não existir a pasta/diretório
//Part of file system
begin
//OpenDialog1.InitialDir := Path; // não precisa , foi para lembrar use se quiser
//OpenDialog1.Execute; // não precisa , foi para lembrar use se quiser
result := PathW;
end;
StrDispose(PathW);
end;
Estou usando assim
function pegarpath(H:HWND; CSIDL:integer):string;
var
PIDL: Pointer;
Pitm:PItemIDList;
PathW:PWideChar;
begin
PathW := StrAlloc( MAX_PATH );
SHGetSpecialFolderLocation( H, CSIDL, Pitm);
if SHGetPathFromIDList(Pitm, PathW ) then
result := PathW
else
result := '##DiretorioNIL';
StrDispose(PathW);
end;
e chamando assim
procedure BotaoExec;
begin
edit.text := pegarpath( Handle, CSIDL_FONTS );
end;
Responder
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)