Using the Browser Geolocation (GPS) Feature from Delphi with WebView4Delphi (WebView2)
This article explains how to use the browser’s Geolocation (GPS) feature
(navigator.geolocation.getCurrentPosition) from Delphi XE4 and later
by integrating WebView4Delphi (WebView2).
(1)Introduction
On Windows 10, install the Microsoft WebView2 Runtime from
https://developer.microsoft.com/microsoft-edge/webview2/.
This guide assumes that WebView4Delphi has already been downloaded
(https://github.com/salvadordf/WebView4Delphi) and installed.
The file WebView2Loader.dll is also required (included with WebView4Delphi).
(2)Creating and Saving the Project
Launch the Delphi IDE and select "File" → "Windows VCL Application – Delphi".
Then choose "File" → "Save All (Ctrl+Shift+S)" to create a folder for the project and
save both the unit (Unit1) and the project (Project1).
Next, select "Project" → "Build Project1 (Shift+F9)" to compile it once in advance
(this generates the necessary output folders).
Inside the project folder, create a files directory under
win32\debug.
In win32\debug\files, create an HTML file named index.html
and save it in UTF‑8 encoding.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
window.addEventListener("load",function(){
console.log("event:loaded");
});
function get_location_gps(){
if(navigator.geolocation){
//Get the current geolocation
navigator.geolocation.getCurrentPosition(
function(pos){
//Called when geolocation is successfully obtained
var posLatitude=pos.coords.latitude;
var posLongitude=pos.coords.longitude;
console.log("gps:"+posLatitude+","+posLongitude);
},
function(err){
// Called when geolocation fails
// If the user denies permission → "User denied Geolocation"
// If there is no internet connection → "Network error. Check DevTools console for more information."
console.log("error:"+err.message);
},
//Geolocation options
{
//Maximum age (ms) of a cached position. 0 = always get the current position.
maximumAge:0,
//Maximum time (ms) allowed to obtain the position
timeout:3000,
//true = request high‑accuracy location, false = lower accuracy is acceptable
enableHighAccuracy:true,
}
);
}else{
console.log("error:disabled");
}
}
</script>
</body>
</html>
(3)Designing the Form
Place the following components on the form by dragging and dropping them from the Tool Palette:
one TButton, one TMemo, one TWVBrowser, and one TWVWindowParent.
(4)Writing the Source Code
Double‑click Button1 on the form to open its event handler and add the source code.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
uWVWinControl, uWVWindowParent, uWVBrowserBase, uWVBrowser,
uWVTypes, uWVConstants, uWVTypeLibrary, uWVLoader, uWVInterfaces,
uWVCoreWebView2Args, uWVLibFunctions, uWVCoreWebView2CookieList,
uWVCoreWebView2Cookie, uWVCoreWebView2HttpRequestHeaders,
uWVCoreWebView2, System.Json;
type
TForm1 = class(TForm)
WVBrowser1: TWVBrowser;
WVWindowParent1: TWVWindowParent;
Button1: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure WVBrowser1AfterCreated(Sender: TObject);
procedure WVBrowser1DevToolsProtocolEventReceived(Sender: TObject;
const aWebView: ICoreWebView2;
const aArgs: ICoreWebView2DevToolsProtocolEventReceivedEventArgs;
const aEventName: wvstring; aEventID: Integer);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses System.JSON.Serializers, System.IOUtils;
procedure TForm1.Button1Click(Sender: TObject);
begin
Button1.Enabled:=False;
//Start JavaScript geolocation retrieval
WVBrowser1.ExecuteScript('get_location_gps()',1);
end;
procedure TForm1.FormCreate(Sender: TObject);
var ct:integer;
begin
Button1.Enabled:=False;
Button1.Caption:='Get Location';
Memo1.Lines.Clear;
WVWindowParent1.Browser:=WVBrowser1;
if GlobalWebView2Loader.InitializationError then
begin
ShowMessage(GlobalWebView2Loader.ErrorMessage);
end
else
begin
ct:=0;
while (ct<20) and (not GlobalWebView2Loader.Initialized) do
begin
sleep(500);
Application.ProcessMessages;
inc(ct);
end;
if GlobalWebView2Loader.Initialized then
begin
WVBrowser1.CreateBrowser(WVWindowParent1.Handle);
// Note:
// Changing the User-Agent to a non-WebView value allows Google login.
WVBrowser1.UserAgent:=
'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'+
' AppleWebKit/537.36 (KHTML, like Gecko)'+
' Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53';
end
else
begin
ShowMessage('WebView2 initialization failed');
end;
end;
end;
procedure TForm1.WVBrowser1AfterCreated(Sender: TObject);
begin
//Required
WVWindowParent1.UpdateSize;
//Map the local "files" directory to the virtual host "https://demo"
WVBrowser1.CoreWebView2.SetVirtualHostNameToFolderMapping(
'demo',
PWideChar(ExtractFilePath(Application.ExeName)+'files'),
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW
);
//Enable console usage
WVBrowser1.CallDevToolsProtocolMethod(
'Console.enable',
'{}', 0
);
// When a console message is output,
// trigger OnDevToolsProtocolEventReceived with EventID = 1
WVBrowser1.SubscribeToDevToolsProtocolEvent('Console.messageAdded',1);
//Display the local ".\files\index.html"
WVBrowser1.Navigate('https://demo/index.html');
end;
procedure TForm1.WVBrowser1DevToolsProtocolEventReceived(Sender: TObject;
const aWebView: ICoreWebView2;
const aArgs: ICoreWebView2DevToolsProtocolEventReceivedEventArgs;
const aEventName: wvstring; aEventID: Integer);
type
TJsonMsg=record
column:Integer;
level:String;
line:Integer;
source:String;
text:String;
url:String;
end;
TJsonMessage=record
message:TJsonMsg;
end;
var pwc:PWideChar;
s:TJsonSerializer;
res:TJsonMessage;
begin
if aEventID=1 then
begin
aArgs.Get_ParameterObjectAsJson(pwc);
s:=TJsonSerializer.Create;
res:=s.Deserialize<TJsonMessage>(pwc);
if res.message.text='event:disabled' then
begin
Memo1.Lines.Add('This device cannot retrieve geolocation.');
Button1.Enabled:=False;
end
else if res.message.text='event:loaded' then
begin
Button1.Enabled:=True;
end
else if pos('error:',res.message.text,1)=1 then
begin
Memo1.Lines.Add('Error:'+res.message.text.Substring(6));
Button1.Enabled:=True;
end
else if pos('gps:',res.message.text,1)=1 then
begin
Memo1.Lines.Add('Latitude / Longitude:'+res.message.text.Substring(4));
//ar:=res.message.text.Substring(4).split([',']);
Memo1.Lines.Add(
'https://www.google.com/maps/@'+
res.message.text.Substring(4)+',18z?hl=ja&entry=ttu'
);
Button1.Enabled:=True;
end
end;
end;
initialization
var cachepath:string;
begin
cachepath:=ExtractFilePath(Application.ExeName) + 'cache';
// Delete cache
if DirectoryExists(cachepath) then TDirectory.Delete(cachepath,true);
// Load and initialize GlobalWebView2Loader
GlobalWebView2Loader := TWVLoader.Create(nil);
//Specify the folder for cache, cookies, etc.
GlobalWebView2Loader.UserDataFolder := cachepath;
GlobalWebView2Loader.StartWebView2;
end;
end.
(5)Copying "WebView2Loader.dll" to the Executable Folder
Copy the file:
C:\Program Files (x86)\Embarcadero\Studio\22.0\Redist\win32\WebView2Loader.dll
into the same folder as your application’s executable
(Project Folder → Win32\Debug).
| (A) "Debug" build "Windows 32‑bit" |
ProjectFolder\Win32\Debug |
| (B) "Debug" build "Windows 64‑bit" |
ProjectFolder\Win64\Debug |
| (C) "Release" build "Windows 32‑bit" |
ProjectFolder\Win32\Release |
| (D) "Release" build "Windows 64‑bit" |
ProjectFolder\Win64\Release |
(6)Running the Application
If your PC does not have a built‑in GPS module, make sure it is connected to the Internet.
In that case, the browser will provide an approximate location based on network information.
Select “Run” → “Run” to start the application.
After a short moment, the “Get Location (Button1)” button will become enabled.
Click the "Get Location (Button1)" button.
If a dialog appears asking for permission to access your current location, click "Allow".
When the geolocation request succeeds, the latitude and longitude will be displayed.
