GARANTIR DESCONTO

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:


Kristian

Kristian

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;


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;
Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar