BLACKFIRE69
Новичок
1) Today, I unlock the feature 'Runtime Scripts' for FMXInno for general use.
So, what are 'Runtime Scripts'? They are scripts that run at runtime without needing to be compiled at compile-time. This means that once you compile your Setup, you don't need to recompile it to apply changes made in 'Runtime Scripts'.
Enough explanations, let's dive into a simple example:
Here, I use the file extension '.fxs' for Runtime Scripts, but you can use whatever you want: '.pas', '.iss', '.txt', etc.
1. This example will create a Rectangle (ARect1: FRectangle) at runtime, while the Setup is running.
2. While the Setup is running, make some changes to the Runtime Script and smash the 'Run' button to see the changes.
* FMXInno has supported runtime scripts for quite a while with 'Lua'. Some may not be familiar with 'Lua', so i didn't promote it. On the other hand, 'FRuntimeScript' is Pascal, so everyone who uses InnoSetup can use this without any doubt.
[*] Built-In Features / Functions / Constants / Variables:
[*] Register Custom Types:
[*] Load External Libraries (DLLs):
You can call external DLLs inside runtime scripts in three different ways,
-- Supported flags: 'stdcall' , 'cdecl' , and 'delayload' .
[*] Call a function/procedure declared in Runtime Scripts through InnoSetup:
There are two ways to call a function/procedure declared in Runtime Scripts via InnoSetup.
[*] Register InnoSetup's function/procedure and use them in Runtime Script:
You can register functions/procedures for Runtime Scripts that have been declared in the InnoSetup (.iss).
1. At the moment, it doesn't accept any parameters.
2. You have to use the Callback function.
[*] PreProcessor and Include Files:
Runtime scripts support preprocessors and include files.
[*] Syntax Highlighting in the Text Editor:
Open the '.fxs' file in your favorite text editor or IDE and select the file syntax as 'Pascal'. Now you're good to go.
![00.gif 00.gif](https://krinkels.org/data/attachments/8/8008-e07c5fdd2cc5cb07922fbc33bfe306b4.jpg)
![01.gif 01.gif](https://krinkels.org/data/attachments/8/8009-5d181db83697336891f33a8782c33167.jpg)
![02.gif 02.gif](https://krinkels.org/data/attachments/8/8010-fc99609288f175e1bc50cdc1e7ac3e6b.jpg)
![03.gif 03.gif](https://krinkels.org/data/attachments/8/8011-5ff48c03c415a01dc4a804f051d0d8aa.jpg)
![x.png x.png](https://krinkels.org/data/attachments/8/8012-30c1597e3e183f4ac5c2afc68d5cb691.jpg)
![y.png y.png](https://krinkels.org/data/attachments/8/8013-05526a347fbe39bed342c5e7d564512c.jpg)
![z.png z.png](https://krinkels.org/data/attachments/8/8014-e8a5a2353a317483ee217f0baf30ae37.jpg)
So, what are 'Runtime Scripts'? They are scripts that run at runtime without needing to be compiled at compile-time. This means that once you compile your Setup, you don't need to recompile it to apply changes made in 'Runtime Scripts'.
Enough explanations, let's dive into a simple example:
Here, I use the file extension '.fxs' for Runtime Scripts, but you can use whatever you want: '.pas', '.iss', '.txt', etc.
Форматирование (BB-код):
Test_1.fxs
-------------------------------------------
program Test1CreateRect; // This line is optional, so you can get rid of it.
var ARect: FRectangle;
procedure CleanUpRect;
begin
ARect := nil;
end;
begin
ARect := InitRectangleHandle;
ARect.FCreate(FMXFormHandle);
ARect.SetBounds(200, 90, 250, 250);
ARect.FillColor(ALRed);
AExternalObj := ARect.Handle;
end.
Форматирование (BB-код):
Example.iss
-------------------------------------------
var
ARuntimeScript: FRuntimeScript;
FirstRun: Boolean;
AExternalObj: TFMXObject;
procedure ABtnOnClick(Sender: TObject);
begin
if not FirstRun then
begin
// Get the handle of the external object that was created with the external script.
AExternalObj := ARuntimeScript.GetRegisteredLongIntVar('AExternalObj');
// Call for cleanup.
ARuntimeScript.CallProcFromScriptNoVar('CleanUpRect');
// Remove the external object from FMXForm as well.
FMXForm.RemoveObject(AExternalObj);
end;
ARuntimeScript.CompileAndRun;
FirstRun := False;
end;
Форматирование (BB-код):
procedure InitializeWizard();
begin
{FMX Form}
FMXForm.FCreateFluent(WizardForm.Handle, False, False, 0.96, 0);
{ABtn}
ABtn.FCreate(FMXForm.Handle);
ABtn.Text('&Run');
ABtn.OnClick(@ABtnOnClick);
{ARuntimeScript}
ARuntimeScript.FCreate(ExpandConstant('{src}\_Scripts\Test_1.fxs'));
ARuntimeScript.RegisterLongIntConst('FMXFormHandle', FMXForm.Handle);
ARuntimeScript.RegisterLongIntVar('AExternalObj', 0);
end;
2. While the Setup is running, make some changes to the Runtime Script and smash the 'Run' button to see the changes.
Форматирование (BB-код):
ARect.FillColor(ALGreen); // ARect.FillColor(ALRed);
3. Try creating a similar object (ARect2) by following the 'ARect1' code. Once you save the file, click the 'Run' button.
Форматирование (BB-код):
var ARect, ARect2: FRectangle;
begin
ARect := InitRectangleHandle;
ARect.FCreate(FMXFormHandle);
ARect.SetBounds(80, 90, 200, 200);
ARect.FillColor(ALRed);
ARect2 := InitRectangleHandle;
ARect2.FCreate(FMXFormHandle);
ARect2.SetBounds(360, 90, 200, 200);
ARect2.FillColor(ALBlue);
...
end .
* FMXInno has supported runtime scripts for quite a while with 'Lua'. Some may not be familiar with 'Lua', so i didn't promote it. On the other hand, 'FRuntimeScript' is Pascal, so everyone who uses InnoSetup can use this without any doubt.
[*] Built-In Features / Functions / Constants / Variables:
1. 'Runtime Scripts' has built-in support for FMXInno classes, so you can use them inside 'Runtime Scripts'.
-- Currently, it only supports the 'FMX_Standard', 'FMX_Shapes', 'FMX_Additional', 'FMX_Layouts', and 'FMX_Effects' classes. because i'm too lazy to add all the classes at the moment. but in the future.
2. 'Runtime Scripts' are not literally InnoSetup, so functions like "ExpandConstant" and "ExtractTemporaryFile" used in InnoSetup can't be used in runtime scripts.
-- However, I've added some extra useful functions by default from 'System.SysUtils', 'System.Math', 'Winapi.Windows', etc., and you'll find them in the 'BuiltIn Features.txt' file.
3. Added default variable 'Application: TApplication', so you can now use 'Application.ProcessMessages;' inside the runtime scripts.
[*] Register Custom Types:
Форматирование (BB-код):
Example.iss
-------------------------------------------
ARuntimeScript.RegisterType('TDummyRec', 'record' +#13#10+
' PosX: Integer;' +#13#10+
' PosY: Integer;' +#13#10+
'end;');
ARuntimeScript.RegisterType('TsNum', 'Single');
Test_1.fxs
-------------------------------------------
var
Shipping Fees: TsNum;
ADummyRec: TDummyRec;
[*] Load External Libraries (DLLs):
You can call external DLLs inside runtime scripts in three different ways,
-- Supported flags: 'stdcall' , 'cdecl' , and 'delayload' .
1. System Libs:
Форматирование (BB-код):
Test_1.fxs
-------------------------------------------
function KillTimer(handle: HWND; TimerId: LongWord): boolean;
external 'KillTimer@user32.dll stdcall';
2. Libs from custom path:
Форматирование (BB-код):
Test_1.fxs
-------------------------------------------
procedure MyDllFunc(hWnd: Integer);
external 'MyDllFunc@"C:\Test\Libs\MyDll.dll" stdcall';
3. I've added three special constants to runtime scripts, but you need to define them manually first.
a. 'Src':
Форматирование (BB-код):
Example.iss
-------------------------------------------
ARuntimeScript.RegisterSpecialSrcConst(ExpandConstant('{src}'));
Test_1.fxs
-------------------------------------------
procedure MyDllFunc(hWnd: Integer);
external 'MyDllFunc@"{src}\MyDll.dll" stdcall';
b. 'App':
Форматирование (BB-код):
Example.iss
-------------------------------------------
ARuntimeScript.RegisterSpecialAppConst(ExpandConstant('{src}\_ExtrnlDll'));
Test_1.fxs
-------------------------------------------
procedure MyDllFunc(hWnd: Integer);
external 'MyDllFunc@"{app}\MyDll.dll" stdcall';
c. 'Tmp':
Форматирование (BB-код):
Example.iss
-------------------------------------------
ARuntimeScript.RegisterSpecialAppConst(ExpandConstant('{src}\_ExtrnlDll'));
Test_1.fxs
-------------------------------------------
procedure MyDllFunc(hWnd: Integer);
external 'MyDllFunc@"{tmp}\MyDll.dll" stdcall';
d. You can also use 'files:' to define the path.
Форматирование (BB-код):
Test_1.fxs
-------------------------------------------
procedure MyDllFunc(hWnd: Integer);
external 'MyDllFunc@"files:MyDll.dll" stdcall';
- In runtime scripts, 'files:' is equal to 'Tmp'.
- It doesn't extract the Lib to the 'Tmp' directory as InnoSetup does.
e. Added built-in support for 'CreateCallback' function.
Форматирование (BB-код):
Test_1.fxs
-------------------------------------------
SetTimer(0, 0, 250, CreateCallback(@TimerProc1));
[*] Call a function/procedure declared in Runtime Scripts through InnoSetup:
There are two ways to call a function/procedure declared in Runtime Scripts via InnoSetup.
1. Without Parameters:
Форматирование (BB-код):
Test_1.fxs
-------------------------------------------
procedure SayHi;
begin
ShowMessage('Hi, I am from the Runtime Script!');
end;
Example.iss
-------------------------------------------
ARuntimeScript.CallProcFromScriptNoVar('SayHi');
2. With Parameters:
-- Here you have to use FNewArray for Parameters.
Форматирование (BB-код):
Test_1.fxs
-------------------------------------------
procedure CalAddition(const x, y: Integer);
begin
MyMathResult := x + y;
end;
Example.iss
-------------------------------------------
var
AParams: FNewArray;
{AParams}
AParams.FCreate;
AParams.AddInteger(32);
AParams.AddInteger(37);
ARuntimeScript.CallProcFromScript('CalAddition', AParams);
[*] Register InnoSetup's function/procedure and use them in Runtime Script:
You can register functions/procedures for Runtime Scripts that have been declared in the InnoSetup (.iss).
1. At the moment, it doesn't accept any parameters.
2. You have to use the Callback function.
Форматирование (BB-код):
Example.iss
-------------------------------------------
type
TDummyFunc2 = function: Integer;
function XWrapNoVarFuncNew(Callback: TDummyFunc2): Longword;
external 'XWrapNoVar@files:FMXInno.dll stdcall delayload';
function GetValueFromInnoSetup: Integer;
begin
Result := 69;
end;
procedure InnoMsgProc;
var
LNum: Longint;
begin
MsgBox('Hi', mbInformation, MB_OK);
end;
ARuntimeScript.RegisterProcNoVar(XWrapNoVarProc(@InnoMsgProc), 'procedure InnoMsgProc;');
ARuntimeScript.RegisterProcNoVar(XWrapNoVarFuncNew(@GetValueFromInnoSetup), 'function GetValueFromInnoSetup: Integer;');
Форматирование (BB-код):
Test_1.fxs
-------------------------------------------
program Test7RegisterProc;
var
LuckyNum: Integer;
procedure DoIt;
begin
InnoMsgProc();
end;
begin
LuckyNum := GetValueFromInnoSetup();
DoIt;
end.
[*] PreProcessor and Include Files:
Runtime scripts support preprocessors and include files.
Форматирование (BB-код):
Test_1.fxs
-------------------------------------------
program Test10aIncludeFiles; // This line is optional, so you can get rid of it.
{$DEFINE WHO_ARE_YOU}
{$I ".\_Scripts\Test_10b.fxs"}
var
S: String;
begin
{$IFDEF WHO_ARE_YOU}
S := 'Mr. BLACKFIRE';
{$ELSE}
S := 'Mr/Ms/Mrs. Nobody';
{$ENDIF}
SayHi(S);
end.
[*] Syntax Highlighting in the Text Editor:
Open the '.fxs' file in your favorite text editor or IDE and select the file syntax as 'Pascal'. Now you're good to go.
![00.gif 00.gif](https://krinkels.org/data/attachments/8/8008-e07c5fdd2cc5cb07922fbc33bfe306b4.jpg)
![01.gif 01.gif](https://krinkels.org/data/attachments/8/8009-5d181db83697336891f33a8782c33167.jpg)
![02.gif 02.gif](https://krinkels.org/data/attachments/8/8010-fc99609288f175e1bc50cdc1e7ac3e6b.jpg)
![03.gif 03.gif](https://krinkels.org/data/attachments/8/8011-5ff48c03c415a01dc4a804f051d0d8aa.jpg)
![x.png x.png](https://krinkels.org/data/attachments/8/8012-30c1597e3e183f4ac5c2afc68d5cb691.jpg)
![y.png y.png](https://krinkels.org/data/attachments/8/8013-05526a347fbe39bed342c5e7d564512c.jpg)
![z.png z.png](https://krinkels.org/data/attachments/8/8014-e8a5a2353a317483ee217f0baf30ae37.jpg)
Вложения
-
5.1 MB Просмотры: 9