Jump to content
softtouch

Desktop path crossplatform?

Recommended Posts

Is there a single function to retrieve the path to the Desktop which works on Windows and macOS?

Share this post


Link to post
4 minutes ago, softtouch said:

Is there a single function to retrieve the path to the Desktop which works on Windows and macOS?

It appears there is not a single function "out of the box", but it wouldn't be too difficult to implement. TPath.GetHomePath is supposed to return /Users/<username> on macOS:

 

https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Standard_RTL_Path_Functions_across_the_Supported_Target_Platforms

 

So appending "Desktop" should be reliable.

 

For Windows you'd need to do a bit more work. TPath.GetDocumentsPath on Windows gives, for example: C:\Users\<username>\Documents, so you could remove the Documents part and add Desktop 🙂

 

Share this post


Link to post
1 hour ago, Dave Nottage said:

It appears there is not a single function "out of the box", but it wouldn't be too difficult to implement. TPath.GetHomePath is supposed to return /Users/<username> on macOS:

 

https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Standard_RTL_Path_Functions_across_the_Supported_Target_Platforms

 

So appending "Desktop" should be reliable.

 

For Windows you'd need to do a bit more work. TPath.GetDocumentsPath on Windows gives, for example: C:\Users\<username>\Documents, so you could remove the Documents part and add Desktop 🙂

 

Thanks, I thought there might be a single function somewhere in IOUtils, but apparently not. All other path are available via IOUtils, just the desktop path not.

Share this post


Link to post

We use this function (I modified it here to avoid using external references, but I think it will be correct as written here):

 

function OSGetUserDesktopPath: string;
begin
{$ifdef MSWINDOWS}
  winApiUtils.GetFolderPath(CSIDL_DESKTOPDIRECTORY,Result);
  result := result+TPath.PathSeparator;
{$elseif defined(OSX)}
  Result := TPath.GetHomePath+TPath.PathSeparator+'Desktop'+TPath.PathSeparator;
{$elseif defined(IOS)}
  Assert(false, 'OSGetUserDesktopPath not implemented on IOS');
  Result := '';
{$elseif defined(ANDROID)}
  Assert(false, 'OSGetUserDesktopPath not implemented on ANDROID');
  Result := '';
{$else}
  {$Message Error 'Missing Target'}
{$endif}
end;

 

Edited by Hans♫

Share this post


Link to post
8 hours ago, Hans♫ said:

We use this function (I modified it here to avoid using external references, but I think it will be correct as written here):

 


function OSGetUserDesktopPath: string;
begin
{$ifdef MSWINDOWS}
  winApiUtils.GetFolderPath(CSIDL_DESKTOPDIRECTORY,Result);
  result := result+TPath.PathSeparator;
{$elseif defined(OSX)}
  Result := TPath.GetHomePath+TPath.PathSeparator+'Desktop'+TPath.PathSeparator;
{$elseif defined(IOS)}
  Assert(false, 'OSGetUserDesktopPath not implemented on IOS');
  Result := '';
{$elseif defined(ANDROID)}
  Assert(false, 'OSGetUserDesktopPath not implemented on ANDROID');
  Result := '';
{$else}
  {$Message Error 'Missing Target'}
{$endif}
end;

 

Yes, that seems to be the only way at the moment. Thanks for that!

Share this post


Link to post
8 hours ago, Hans♫ said:

We use this function (I modified it here to avoid using external references, but I think it will be correct as written here):

Small nitpicks..

  • you can't use {$ELSEIF} with {$IFDEF}, you would need to use {$ELSE}{$IFDEF} instead. Otherwise, use {$IF} in order to use {$ELSEIF}.
  • I would suggest using RTL functions to handle the path delimiters.
function OSGetUserDesktopPath: string;
begin
{$if defined(MSWINDOWS)}
  winApiUtils.GetFolderPath(CSIDL_DESKTOPDIRECTORY, Result);
  Result := InclueTrailingPathDelimiter(Result);
{$elseif defined(OSX)}
  Result := TPath.Combine(TPath.GetHomePath, 'Desktop');
  Result := IncludeTrailingPathDelimiter(Result);
{$elseif defined(IOS)}
  Assert(false, 'OSGetUserDesktopPath not implemented on IOS');
  Result := '';
{$elseif defined(ANDROID)}
  Assert(false, 'OSGetUserDesktopPath not implemented on ANDROID');
  Result := '';
{$else}
  {$Message Error 'Missing Target'}
{$ifend}
end;

 

  • Like 1

Share this post


Link to post
Quote

HELP SYSTEM: Legacy IFEND (Delphi)

The $ELSEIF directive allows multi-part conditional blocks where at most one of the conditional blocks will be taken. $ELSEIF is a combination of a $ELSE and a $IF.

...

Before the XE4 release, $IF statements could only be terminated with $IFEND, and the $IFDEF, $IFNDEF, $IFOPT directives could only be terminated with $ENDIF.

...

At the XE4 release, the Delphi compilers were changed to accept either $IFEND or $ENDIF to close $IF statements. Before XE4, only $IFEND could be used to close $IF statements. The $LEGACYIFEND directive allows you to restore the old behavior, which is useful if your code is emitting E2029 related to nested $IF and $IFDEF statements.

There is not problem at all, just each one use your way!

about {$ELSEIF} is the same... win who arrives at first!

{$DEFINE hello1 }
{$DEFINE hello2 }
{$DEFINE hello3 }

procedure TForm1.FormCreate(Sender: TObject);
begin
{$IF DEFINED(hello1)}
  ShowMessage('hello1')
{$ELSEIF DEFINED(hello2)}
  ShowMessage('hello2')
{$ELSEIF DEFINED(hello3)}
  ShowMessage('hello3')
{$ELSE}
  ShowMessage('hello ELSE')
{$ENDIF}
end;

 

Edited by programmerdelphi2k

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×