Is there a good scripting Pascal-like language for Delphi? - 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.

Related

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

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.

Delphi Set Invalid Typecast

How do I fix this invalid typecast error? The code works when the set has less than 31 items. Below is the code snippet:
type
TOptionsSurveyTypes=(
ostLoadSurvey00,
ostLoadSurvey01,
ostLoadSurvey02,
ostLoadSurvey03,
ostLoadSurvey04,
ostLoadSurvey05,
ostLoadSurvey06,
ostLoadSurvey07,
ostLoadSurvey08,
ostLoadSurvey09,
ostLoadSurvey10,
ostEventLog01,
ostEventLog02,
ostEventLog03,
ostEventLog04,
ostEventLog05,
ostSagSwell,
ostTamper,
ostWaveforms,
ostDeviceList,
ostDeleteData,
ostTOUBillingTotal,
ostTOUPrevious,
ostProfileGenericLoadSurvey01,
ostProfileGenericLoadSurvey02,
ostProfileGenericLoadSurvey03,
ostProfileGenericLoadSurvey04,
ostProfileGenericLoadSurvey05,
ostProfileGenericLoadSurvey06,
ostProfileGenericLoadSurvey07,
ostProfileGenericLoadSurvey08,
ostProfileGenericLoadSurvey09,
ostProfileGenericLoadSurvey10,
ostProfileGenericEventLog01,
ostProfileGenericEventLog02,
ostProfileGenericEventLog03,
ostProfileGenericEventLog04,
ostProfileGenericEventLog05,
ostProfileGenericBillingTotal,
ostProfileGenericPrevious,
ostProfileGeneric
);
TOptionsSurveyTypesSet=set of TOptionsSurveyTypes;
function TUserProcessRollback.SurveyRollBack:boolean;
var
vRollbackDate: TDateTime;
FOptions: LongWord;
begin
...
if ostDeleteData in TOptionsSurveyTypesSet(FOptions) then <-- invalid typecast error here
vRollbackDate := 0.00
else
vRollbackDate := FRollbackDate;
...
end;
When I reduce the set to just less than 32 items and FOptions is declared as DWORD, the code compiles .
Thanks
Your enumerated type has 41 items. Each byte holds 8 bits. To have a set of this enumerated type requires at least 41 bits. The smallest number of bytes necessary to hold 41 bits is 6. So the set type is 6 bytes. To confirm this, you can execute this:
ShowMessage ( inttostr ( sizeof ( TOptionsSurveyTypesSet ) ) );
A DWORD is 4 bytes, so it cannot be typecast into a type that is 6 bytes. If you declare fOptions to be a type with 6 bytes, your code will compile.
FOptions: packed array [ 1 .. 6] of byte;
If you reduce the enumerated type to 32 or fewer items, then the set type will be 4 bytes, and so the typecast from DWORD will work.

activeX control crash on alt+tab

I've implemented an Delphi acitveX control. Everything runs fine on html. After that, I embed that activeX in an MFC application. It's good, except that when I test it, if I alt+tab to another windows(Chrome, for example...) and alt+tab back to my application, it just crashed.
I know that this is a non-clear question, but I have no clues. Any clues to solve this situation? What may go wrong or what events I should take a look at?
Thanks.
Edit 1:
This is what I got when I use spy++ on it.
<04518> 00100B7C S WM_ACTIVATE fActive:WA_INACTIVE fMinimized:False hwndPrevious:(null)
<04519> 00100B7C S WM_ACTIVATETOPLEVEL fActive:False dwThreadID:0025F40C
<04520> 00100B7C R WM_ACTIVATETOPLEVEL
Edit 2:
This is what I got from call stack when I break all at the time it hangs
mfc100d.dll!CThreadSlotData::GetThreadValue(int nSlot) Line 248 C++
mfc100d.dll!CThreadLocalObject::GetData(CNoTrackObject * (void)* pfnCreateObject) Line 420 + 0x11 bytes C++
mfc100d.dll!CThreadLocal<AFX_MODULE_THREAD_STATE>::GetData() Line 179 + 0xd bytes C++
mfc100d.dll!AfxGetModuleThreadState() Line 477 + 0x11 bytes C++
mfc100d.dll!afxMapHWND(int bCreate) Line 289 + 0x5 bytes C++
mfc100d.dll!CWnd::FromHandlePermanent(HWND__ * hWnd) Line 324 + 0x7 bytes C++
mfc100d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 405 + 0x9 bytes C++
mfc100d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam) Line 420 + 0x15 bytes C++
Edit 3:
I'm using Visual studio 2010, the call stack tell that application hangs in this function, line 2, from afxtls.cpp. Please anyone shed some lights on how to solve this.
inline void* CThreadSlotData::GetThreadValue(int nSlot)
{
EnterCriticalSection(&m_sect);
ASSERT(nSlot != 0 && nSlot < m_nMax);
ASSERT(m_pSlotData != NULL);
ASSERT(m_pSlotData[nSlot].dwFlags & SLOT_USED);
ASSERT(m_tlsIndex != (DWORD)-1);
if( nSlot <= 0 || nSlot >= m_nMax ) // check for retail builds.
{
LeaveCriticalSection(&m_sect);
return NULL;
}
CThreadData* pData = (CThreadData*)TlsGetValue(m_tlsIndex);

Can I write reverse div operator?

I have a mathematical equation and How can I find the it's reverse ?
My equation:
var
x,y:integer;
begin
//example x=1234;
x-(x div 100):=y
end;
after the code I konw "y" how can I find the "x"?(1234)
In general, you can't. Since div does integer division, there are potentially many inputs that can/will produce the same result. Starting from that result, and of those inputs is an equally likely possibility as the original input. For example:
175 div 7 = 25
176 div 7 = 25
177 div 7 = 25
178 div 7 = 25
179 div 7 = 25
180 div 7 = 25
181 div 7 = 25
Starting from 25, any of those numbers from 175 to 181 would be an equally viable answer.

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