D'habitude, j'utilise: ShellExecute(0, 'OPEN', PChar(edtURL.Text), '', '', SW_SHOWNORMAL);
Comment puis-je avoir le même comportement (ouvrir un lien dans le navigateur par défaut) sur toutes les plateformes (Windows et OSX)?
Dans le forum de discussion FireMonkey, j'ai trouvé ce code pour une question à propos de NSWorkspace.URLForApplicationToOpenURL:
uses
Posix.Stdlib;
....
_system(PAnsiChar('open ' + ACommand));
(pas testé par moi)
Mise à jour : Posix n'étant pas disponible sous Windows, il n'est pas possible d'écrire une solution utilisant les mêmes appels de système d'exploitation sur toutes les plateformes. Je suggère de déplacer ce code dans une unité centrale 'XPlatform' qui contient des fichiers IFDEF POSIX, etc.
En ce qui concerne la réponse de mjn , j’ai écrit l’unité suivante. Je l'ai testé avec succès sur Windows, mais je n'ai pas d'OSX pour le tester sur cette plate-forme. Si quelqu'un peut confirmer que cela fonctionne, j'apprécierais.
unit fOpen;
interface
uses
{$IFDEF MSWINDOWS}
Winapi.ShellAPI, Winapi.Windows;
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
Posix.Stdlib;
{$ENDIF POSIX}
type
TMisc = class
class procedure Open(sCommand: string);
end;
implementation
class procedure TMisc.Open(sCommand: string);
begin
{$IFDEF MSWINDOWS}
ShellExecute(0, 'OPEN', PChar(sCommand), '', '', SW_SHOWNORMAL);
{$ENDIF MSWINDOWS}
{$IFDEF POSIX}
_system(PAnsiChar('open ' + AnsiString(sCommand)));
{$ENDIF POSIX}
end;
end.
et je l'appelle comme ça:
TMisc.Open('https://stackoverflow.com/questions/7443264/how-to-open-an-url-with-the-default-browser-with-firemonkey-cross-platform-applic');
Pour toutes les plateformes (Windows, MacOs, iOS et Android), vous pouvez utiliser l'unité que j'ai écrite pour mon blog
unit u_urlOpen;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes,
System.Variants,
{$IF Defined(IOS)}
macapi.helpers, iOSapi.Foundation, FMX.helpers.iOS;
{$ELSEIF Defined(Android)}
Androidapi.JNI.GraphicsContentViewText,
Androidapi.JNI.Net,
Androidapi.JNI.App,
Androidapi.helpers;
{$ELSEIF Defined(MACOS)}
Posix.Stdlib;
{$ELSEIF Defined(MSWINDOWS)}
Winapi.ShellAPI, Winapi.Windows;
{$ENDIF}
type
tUrlOpen = class
class procedure Open(URL: string);
end;
implementation
class procedure tUrlOpen.Open(URL: string);
{$IF Defined(Android)}
var
Intent: JIntent;
{$ENDIF}
begin
{$IF Defined(Android)}
Intent := TJIntent.Create;
Intent.setAction(TJIntent.JavaClass.ACTION_VIEW);
Intent.setData(StrToJURI(URL));
tandroidhelper.Activity.startActivity(Intent);
// SharedActivity.startActivity(Intent);
{$ELSEIF Defined(MSWINDOWS)}
ShellExecute(0, 'OPEN', PWideChar(URL), nil, nil, SW_SHOWNORMAL);
{$ELSEIF Defined(IOS)}
SharedApplication.OpenURL(StrToNSUrl(URL));
{$ELSEIF Defined(MACOS)}
_system(PAnsiChar('open ' + AnsiString(URL)));
{$ENDIF}
end;
end.
Code XE2 C++ testé avec succès (Windows 7 64 et OSX Lion), améliorations mineures. Merci Whiler, la douleur est finie :)
#include <fmx.h>
// ---------------------------------------------------------------------------
#ifdef _WIN32
#include <shellapi.h>
#endif// Windows
#ifdef TARGET_OS_MAC
#include <Posix.Stdlib.hpp>
#endif // Mac
void OpenCommand(String _sCommand) {
#ifdef _Windows
String open = "open";
ShellExecute(0, open.w_str(), _sCommand.c_str(), NULL, NULL, SW_SHOWNORMAL);
#endif // Windows
#ifdef TARGET_OS_MAC
system(AnsiString("open " + AnsiString(_sCommand)).c_str());
#endif // Mac
}
Et maintenant une version C++ (code OSx non testé, pas aussi sûr du _POSIX #def):
#ifdef _Windows
#include <Winapi.Windows.hpp>
#endif // _Windows
#ifdef _POSIX
#include <Posix.Stdlib.h>
#endif // _POSIX
void OpenCommand(String _sCommand)
{
#ifdef _Windows
ShellExecute(0, _T("open"), _sCommand.c_str(), _T(""), _T(""), SW_SHOWNORMAL);
#endif // _Windows
#ifdef _POSIX
_system(AnsiString("open " + AnsiString(_sCommand)).c_str());
#endif // _POSIX
}
Comme @NicoBlu l'a mentionné, la solution acceptée semble tronquer l'URL après la première occurrence de '&'. Voici ce qui fonctionne pour moi sans troncature:
uses Macapi.AppKit, Macapi.Foundation, Macapi.Helpers;
// ...
procedure OpenLinkInDefaultBrowser(const Link: string);
var URL : NSURL;
Workspace : NSWorkspace;
begin
URL := TNSURL.Wrap(TNSURL.OCClass.URLWithString(StrToNSStr(Link)));
Workspace := TNSWorkspace.Wrap(TNSWorkspace.OCClass.sharedWorkspace);
Workspace.openURL(URL);
end;
_system(PAnsiChar('open ' + AnsiString(sCommand)));
not works si la chaîne d'URL (sCommand
) inclut le caractère esperluette (&
), nécessaire pour spécifier plusieurs arguments dans la chaîne de requête.
URL envoyé à def. Le navigateur dans OSX (Safari) est tronqué à la première occurrence de &
.
LEncodedString : String;
begin
LEncodedString := TIdURI.URLEncode('http://www.malcolmgroves.com');
sharedApplication.openURL(StringToNSURL(LEncodedString));
end;