EventAdapter not working

I tried to create a new EventAdapter for TDrawCell of TStringGrid.
But I am not able to compile it. What have I done wrong?

type
  TMyDrawCellEventDispatcher = class(TatEventDispatcher)
  private
    procedure __TDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
  end;

...

  DefineEventAdapter(TypeInfo(TDrawCellEvent), TMyDrawCellEventDispatcher,
    @TMyDrawCellEventDispatcher.__TDrawCell);

...

{ TMyDrawCellEventDispatcher }

procedure TMyDrawCellEventDispatcher.__TDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
begin
  if Assigned(Scripter) and (RoutineName > '') then begin
    Scripter.ExecuteSubroutine(RoutineName, [Sender, ACol, ARow, Rect, State]);
  end;
end;

The line
Scripter.ExecuteSubroutine(RoutineName, [Sender, ACol, ARow, Rect, State]);
seems to have a problem with Rect and State.

How can I fix this problem?

Records (like TRect) require a special treatment. Nevertheless, there are a few examples in Support Center about how to use it, specifically in events. Here are some references:

I have changed it like this:

type
  TRectWrapper = class(TatRecordWrapper)
  private
    FLeft: Integer;
    FTop: Integer;
    FRight: Integer;
    FBottom: Integer;
  published
    property Left: Longint read FLeft write FLeft;
    property Top: Longint read FTop write FTop;
    property Right: Longint read FRight write FRight;
    property Bottom: Longint read FBottom write FBottom;
  end;
{ TMyDrawCellEventDispatcher }

procedure TMyDrawCellEventDispatcher.__TDrawCell(Sender: TObject; ACol,
  ARow: Integer; Rect: TRect; State: TGridDrawState);
var
  MyRect: TRectWrapper;
  MyStateTypeSet: TGridDrawState;
  MyStateType: Variant;
begin
  MyRect := TRectWrapper.Create();
  MyRect.Left := Rect.Left;
  MyRect.Top := Rect.Top;
  MyRect.Right := Rect.Right;
  MyRect.Bottom := Rect.Bottom;

  MyStateTypeSet := State;
  MyStateType := IntFromSet(MyStateTypeSet, SizeOf(TGridDrawState));

  if Assigned(Scripter) and (RoutineName > '') then begin
    Scripter.ExecuteSubroutine(RoutineName, [Sender, ACol, ARow, MyRect, MyStateType]);
  end;
  MyRect.Free;
end;

Now it compiles, but I still have the problem that Rect only contains NULL values.
When debugging in Delphi IDE I see that MyRect.Left receives a correct value and MyRect is also passed using
Scripter.ExecuteSubroutine(RoutineName, [Sender, ACol, ARow, MyRect, MyStateType]);.
But inside the script Rect.Left is NULL all the time.
Where is my mistake?

I can't seen anything wrong in your code. Are you able to pack it in a sample project reproducing the issue, so we can try to help you our more objectively?

It is difficult to give you a sample project. In which format would you need it? We store our Scripting code in an own format inside a database and are able to export it in a self developed XML-Format. This would not help you.

It works now with a tricky workaround:
Scripter.ExecuteSubroutine(RoutineName, [Sender, ACol, ARow, MyRect, MyStateType, MyRect.Left, MyRect.Top]);

I simply pass the missing values as additional parameters. This works even if the header of the function does not have these parameters.
procedure TMyDrawCellEventDispatcher.__TDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);

Inside the scripting engine code it looks like this:

procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState; iLeft, iTop: integer);
begin
  if Rect = null then ShowMessage('Rect is null'); // does not show => Rect has a value
  if Rect.Left = null then ShowMessage('Rect.Left is null'); // This message box will be shown
  ShowMessage(Format('iLeft=%d/iTop=%d', [iLeft, iTop])); // The correct values are displayed
  ShowMessage(Format('Rect.Left=%d/Rect.Top=%d', [Rect.Left, Rect.Top])); // Script crashs because of null values in Rect.Left and Rect.Top

Currently I am able to process the needed values with that workaround, so I am content.
But I think there is a bug anywhere inside the scripting engine...

Sidenote:

procedure StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState; iLeft, iTop: integer);
var
  test1: TRect;  
  test2: TRectWrapper;
begin
  test1.Left := 1; // Works
  test2.Left := 2; // Scripting-Error
end

In both cases if I type test1. or test2. I do not get any popup menu which would show me the members of TRect.

But my Delphi code already contains the lines

  AScripter.DefineRecordByRTTI(TypeInfo(TRect));
  AScripter.DefineRecordByRTTI(TypeInfo(TRectWrapper));

A Delphi project that shows the problem happening. If you are struggling with this setup, I would even recommend that you try the event adapter in a separate project instead in your main application for learning and testing purposes.

Can you give me a "empty" Delphi program with the minimum requirements for Scripting?
I use Delphi 10.1 Berlin with Scriper v7.27 (Version from March 2022)

Here you go:

ScripterTest.zip (9.0 KB)

How can I implement a windows form inside that tiny demo program?
I have no clue how to do that.
In my version of scripter I can open the "TMS Scripter IDE" and create/execute a Windows Form.
In your example I can only execute simple code without a form.

That's what I need

That's what I got from you

That's what it looks like when I execute my script. With this workaround it is already able to color the grid.

You can then modify the existing ScripterProIDE project and then send it to us.