Delphi + Google Map Api: Using Polyline causes "Script Error" - delphi

I've just started programming in Delphi and I have a problem with Google Map Api. I want to have a form with google map and draw lines on it(coordinates from db). Unfortunately when I try to put a 'Polyline' on a map the error occurs an error.
Line: 0
Char: 0
Error: Script error
Code: 0
Url: https://maps.googleapis.com/maps-api-v3/api/js/29/14b/intl/pl_ALL/poly.js
Have no idea how to fix it.
FYI I'm using RAD Studio 10.2 and using TWebBrowser component.
My code:
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.OleCtrls, SHDocVw, MSHTML ;
type
TForm2 = class(TForm)
WebBrowser1: TWebBrowser;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
Doc: Variant;
HTMLWindow2: IHTMLWindow2;
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
var
HTMLStr: AnsiString =
'<!DOCTYPE html>' +
'<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">' +
' <head>' +
' <meta http-equiv="X-UA-Compatible" content="IE=edge" /> ' +
' <style>' +
' #map {' +
' height: 400px;' +
' width: 100%;' +
' }' +
' </style>' +
' </head>' +
' <body>' +
' <h3>My Google Maps Demo</h3>' +
' <div id="map"></div>' +
' <script src="https://maps.googleapis.com/maps/api/js?v=3&key=***&callback=initMap"></script>'+
' <script>'+
' function initMap() {' +
' var map = new google.maps.Map(document.getElementById("map"), {' +
' zoom: 3,' +
' center: {lat: 0, lng: -180},' +
' mapTypeId: "terrain"' +
' });' +
' var flightPlanCoordinates = [' +
' {lat: 37.772, lng: -122.214},' +
' {lat: 21.291, lng: -157.821},' +
' {lat: -18.142, lng: 178.431},' +
' {lat: -27.467, lng: 153.027}' +
' ];' +
' var flightPath = new google.maps.Polyline({' +
' path: flightPlanCoordinates,' +
' geodesic: true,' +
' strokeColor: "#FF0000",' +
' strokeOpacity: 1.0,' +
' strokeWeight: 2' +
' });' +
' flightPath.setMap(map);' +
' }' +
' </script>' +
' </body>' +
'</html>';
procedure TForm2.FormCreate(Sender: TObject);
begin
if NOT Assigned(WebBrowser1.Document) then
WebBrowser1.Navigate('about:blank');
Doc := WebBrowser1.Document;
Doc.Clear;
Doc.Write(HTMLStr);
Doc.Close;
HTMLWindow2 := (WebBrowser1.Document as IHTMLDocument2).parentWindow;
end;
end.

To get your sample to run there are two needed changes:
1) Swap the script tags
Put the line script src="https://maps.googleapis.com/.... after the next script block. Your initMap function needs to be loaded before you load the google maps api. Otherwise it looks for the initMap function and cannot find it.
Once you make that change you will see the map loaded without the line. But then you will see an error on top of the map stating the browser is not supported.
The error message is not clear when run run this in Delphi. But if you save your embed HTML text out to a file and open in Chrome you can see this error message in the javascript console.
2) Enable IE 11 mode for the embedded TWebBrowser.
In my project I was never able to get the doctype or meta tags to get IE to behave properly. However, setting the emulation mode registry flag did work. The flag needs to be set based on your executable file name. I use a value of
"11000": IE11. Webpages containing standards-based !DOCTYPE directives are
displayed in IE11 edge mode. Default value for IE11.
Information on the registry key is in the MDSN help page: Internet Feature Controls (B..C), under the Browser Emulation section.
You can also see some discussion in this StackOverflow post "How to have Delphi TWebbrowser component running in IE9 mode?"
Make sure you pay attention to the registry location. Because this is Local Machine you need to be under the WOW6432Node if your application is 32 bit running on a 64 bit OS.
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION
Add a DWORD value with your exe name (like "project1.exe") and a value of 11000.

Related

Delphi JCL Debug missing stack frame entries for JDBG

I use following code to dump stack frame at the moment of an exception:
...
var
FTraceList: TStringList;
...
procedure TTraceForm.LogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean);
begin
...
StackList := JclCreateStackList(false, 0, Caller(0, false));
try
FTraceList.Add('');
FTraceList.Add('Stack trace at the moment of the exception:');
StackList.AddToStrings(FTraceList, true, true, true, true);
finally
Stacklist.Free;
end;
end;
But it behaves differently in Debug and Release mode.
For an intended exception (exception for testing purposes) in main form's OnKeyDown when compiling in Debug mode (Delphi debug info) the result is:
Stack trace at the moment of the exception:
(00591276){Main.exe } [00992276] DlgTraceException.TTraceForm.LogException (Line 162, "DlgTraceException.pas" + 55) + $4
(0058B8FF){Main.exe } [0098C8FF] JclDebug.JclCreateStackList + $17
(00591281){Main.exe } [00992281] DlgTraceException.TTraceForm.LogException (Line 162, "DlgTraceException.pas" + 55) + $F
(00582AE3){Main.exe } [00983AE3] JclHookExcept.TNotifierItem.DoNotify + $43
(00582CCB){Main.exe } [00983CCB] JclHookExcept.DoExceptNotify + $CF
(00582DAD){Main.exe } [00983DAD] JclHookExcept.HookedExceptObjProc + $1D
(0000606F){Main.exe } [0040706F] System.#HandleAnyException + $33
(00598DE3){Main.exe } [00999DE3] Main.TMainForm.FormKeyDown (Line 658, "Main.pas" + 2) + $7
And this I get in Release mode (JCL debug info added to binary with JCL Debug Expert):
Stack trace at the moment of the exception:
(0053BA27){Main.exe } [0093CA27] DlgTraceException.TTraceForm.LogException + $377
(00536427){Main.exe } [00937427] JclDebug.JclCreateStackList + $17
(0053BA32){Main.exe } [0093CA32] DlgTraceException.TTraceForm.LogException + $382
(0052D60B){Main.exe } [0092E60B] JclHookExcept.TNotifierItem.DoNotify + $43
(0052D7F3){Main.exe } [0092E7F3] JclHookExcept.DoExceptNotify + $CF
(0052D8D5){Main.exe } [0092E8D5] JclHookExcept.HookedExceptObjProc + $1D
(0000606F){Main.exe } [0040706F] System.#HandleAnyException + $33
In second case FormKeyDown entry is missing. Is there somebody who knows why this is happening? I would like to know the entire stack trace in release mode as well.
After playing a bit with compiler options (toggling them on and off) I could isolate the cause. The stack frame has been optimized out. When I turned Optimization off the FormKeyDown call was recorded even in Release mode. The Stack Frames generation option mentioned in comments above did not influence the results.
Of course I'll keep optimizations on in release mode. It will be harder to find the cause of the exception but there is other info about it JCL debug provides which should be (hopefully) sufficient to find the cause of the exception.

Cordova geolocation.getCurrentPosition Works in Monaca iPhone Debugger But Not With Built iOS App

navigator.geolocation.getCurrentPosition Cordova API method works with the Monaca Debugger/ App Emulator installed on my iPhone, but freezes in the built iOS version on the same phone.
I added the following to the config.xml but it didn't fix the problem.
<feature name="Geolocation">
<param name="ios-package" value="CDVLocation" />
</feature>
I just tried to reproduce your problem. Unfortunately you posted less information. So i set up a new cordova project:
cordova create geolocationTest com.example.com geolocationTest
cd geolocationTest
cordova platform add ios
cordova plugin add cordova-plugin-geolocation
cordova build
Then i moved into that folder and edited the index.html. I added this code:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log("navigator.geolocation works well");
}
After that i added the Example from the Geolocation-Plugin Documentation:
// onSuccess Callback
// This method accepts a Position object, which contains the
// current GPS coordinates
//
var onSuccess = function(position) {
alert('Latitude: ' + position.coords.latitude + '\n' +
'Longitude: ' + position.coords.longitude + '\n' +
'Altitude: ' + position.coords.altitude + '\n' +
'Accuracy: ' + position.coords.accuracy + '\n' +
'Altitude Accuracy: ' + position.coords.altitudeAccuracy + '\n' +
'Heading: ' + position.coords.heading + '\n' +
'Speed: ' + position.coords.speed + '\n' +
'Timestamp: ' + position.timestamp + '\n');
};
// onError Callback receives a PositionError object
//
function onError(error) {
alert('code: ' + error.code + '\n' +
'message: ' + error.message + '\n');
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
That all worked fine for me. So the problem has to be anywhere in your code. You should provide more information.
I think I've found the problem. iOS8 requires the following in the app plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSLocationAlwaysUsageDescription</key>
<string></string>
and locationManager.requestAlwaysAuthorization or locationManager.requestWhenInUseAuthorization needs to be called before navigator.geolocation.getCurrentPosition is called.
The following explains the change with iOS8: http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/
The current problem I'm having now is successfully invoking locationManager.requestAlwaysAuthorization or locationManager.requestWhenInUseAuthorization in the Monaca environment.

ClientDataSet's Savetostream with dfxml parameter throws access violation

Opened clientDataSet and getting:
cds.XMLData
or
st_pom := TMemoryStream.Create;
cds.SaveToStream(st_pom, dfXML );
results in AV. Has anyone encountered such behaviour?
I CAN ADD that cds has two fields: numeric and NVarchar(max) ..
It seems as the second field is the problem ...
Here are the last traces after which AV occurs
'{ Original Exception - Access violation at address 4DB10D54. Write of address 05017000 }'
(0002FD54) [4DB10D54]'#$D#$A'(000B2CB3) [004B3CB3] DBClient.TCustomClientDataSet.SaveDataPacket (Line 1500, "DBClient.pas" + 5) + $15'
(000B4385) [004B5385] DBClient.TCustomClientDataSet.WriteDataPacket (Line 2119, "DBClient.pas" + 5) + $6'
(000B457B) [004B557B] DBClient.TCustomClientDataSet.SaveToStream (Line 2186, "DBClient.pas" + 1) + $C'

Is there a good scripting Pascal-like language for Delphi?

I'm looking for a good free scripting engine for Delphi. I want to add scripting to an application so that I can write small test scripts. Specifically I need:
Pascal-like syntax
current (I looked at RemObjects Pascal Scripting but it is "obsolete" according to a posting I saw).
I don't need full language support, just the basics. I saw this: https://stackoverflow.com/questions/226135/scripting-library-for-delphi but I'm assuming things have moved on a little since then.
All I want to be able to do is add a memo component to my program, and at run-time add a fragment of source to the memo and click on a go button. I want the script to be able to access my application's variables and functions.
What's the easiest path to accomplishing this? Example program follows.
program Project31;
uses
Forms,
Unit36 in 'Unit36.pas' {Form36};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm36, Form36);
Application.Run;
end.
.
unit Unit36;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm36 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form36: TForm36;
implementation
{$R *.dfm}
procedure RoutineInMyApplication ;
begin
ShowMessage ('Hello from my Application') ;
end ;
procedure TForm36.Button1Click(Sender: TObject);
begin
//ExecuteScript (Memo1.Lines) ;
end ;
end.
.
object Form36: TForm36
Left = 0
Top = 0
Caption = 'Form36'
ClientHeight = 174
ClientWidth = 391
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 300
Top = 72
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object Memo1: TMemo
Left = 8
Top = 21
Width = 241
Height = 145
Lines.Strings = (
'begin'
'ShowMessage ('#39'Hello world'#39') ;'
'CallSomehow (RoutineInMyApplication) ;'
'end.'
' ')
TabOrder = 1
end
end
Try the dwscript library which is currently maintained by Eric Grange.
The Jedi JVCL also includes TJvInterpreter which is a very lightweight (small) interpreter, but with much more limited features than dwscript.
For very small (User entered formulas, or simple string and numeric processing tasks) JvInterpreter has worked quite well for me.
Few years ago I used to work with Pax Compiler in combination with this Forms Editor.
Release Notes maXbox 4.7.5.20 Jan 2021 mX47
Add 25 Units + 4 Tutorials
1277 unit uPSI_SystemsDiagram.pas Dendron
1278 unit uPSI_qsFoundation.pas Dendron
1279 uPSI_JclStringLists2 JCL
1280 uPSI_cInternetUtils2 FLC
1281 uPSI_cWindows.pas FLC
1282 uPSI_flcSysUtils.pas +TBytes utils
1283 unit uPSI_RotImg.pas DA
1284 uPSI_SimpleImageLoader.pas LAZ
1285 uPSI_HSLUtils.pas LAZ
1286 uPSI_GraphicsMathLibrary.pas EF
1287 unit uPSI_umodels.pas DMath
1288 uPSI_flcStatistics.pas FLC5
1289 uPSI_flcMaths.pas FLC5
1290 uPSI_flcCharSet.pas
1291 uPSI_flcBits32.pas
1292 uPSI_flcTimers.pas
1293 uPSI_cBlaiseParserLexer.pas
1294 uPSI_flcRational.pas
1295 uPSI_flcComplex.pas
1296 unit uPSI_flcMatrix (uPSI_flcVectors.pas)
1297 unit uPSI_flcStringBuilder.pas
1298 unit PJResFile_Routines;
1299 uPSI_flcASCII.pas
1300 uPSI_flcStringPatternMatcher;
1301 unit uPSI_flcUnicodeChar.pas
Totals of Function Calls: 33282
SHA1: of 4.7.5.20 D82EAD01C58738887661428F94B207DB1D8FAEB5
CRC32: 768395C5 29.5 MB (31,012,768 bytes
FastScript from FastReport (stack does not allow to give a link). Includes PascalScript, C++Script, JScript and BasicScript.
PascalScript seems to be exactly what you ask for.
Try embedding Lua. See Lua 5.1 for Delphi for instance.

how to change desktop wallpaper?

How do I change desktop wallpaper?
I tried this
procedure TForm1.Button1Click(Sender: TObject);
var
PicPath: String;
begin
PicPath := 'C:\test.bmp';
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pChar(PicPath), SPIF_SENDCHANGE)
end;
But it didn't work.
I just tried it with D2007 on XP (and also D2009 on Vista), and this code works.
But to catch If and why it is not working, you should test the result code and get the error from Windows:
if not SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, pChar(PicPath), SPIF_SENDCHANGE)then
RaiseLastOSError;
In most cases, it will be because the bmp file is not found:
System Error. Code: 2.
The system cannot find the file specified.
You can check out this python script:
http://gaze.svn.sourceforge.net/viewvc/gaze/trunk/implementation/src/gazelib/os_interface.py?view=markup
This is the python method that does all the magic. It changes a few registry keys and then calls a system method to update the wallpaper.
103 def set_wallpaper(self, file_path) :
104 self.__lock.acquire()
105 # this module is part of python 2.5 by default
106 import ctypes
107 import _winreg
108 reg = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER, self.__REGISTRY_PATH, 0, _winreg.KEY_SET_VALUE)
109 # First center the image and turn off tiling
110 _winreg.SetValueEx(reg, "TileWallpaper", 0, _winreg.REG_SZ, "0")
111 _winreg.SetValueEx(reg, "WallpaperStyle", 0, _winreg.REG_SZ, "0")
112 # Set the image
113 _winreg.SetValueEx(reg, "ConvertedWallpaper", 0, _winreg.REG_SZ, os.path.realpath(file_path))
114 _winreg.SetValueEx(reg, "Wallpaper", 0, _winreg.REG_SZ, self.convert_to_bmp(file_path))
115 _winreg.CloseKey(reg)
116 # Notify the changes to the system
117 func_ret_val = ctypes.windll.user32.SystemParametersInfoA(\
118 self.__SPI_SETDESKWALLPAPER,\
119 0,\
120 None,\
121 self.__SPIF_UPDATEINIFILE | self.__SPIF_SENDWININICHANGE)
122 assert func_ret_val == 1
123 self.__lock.release()
Check a VB code here, it can give you a clue.
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, imageLocation, SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE)
This should work
Procedure TForm1.Button1Click(Sender: TObject);
var
PicPath : string;
begin
PicPath := 'C:\test.bmp';
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, Pointer(PicPath), SPIF_SENDWININICHANGE);
end;

Resources