Registering a method/notify object

I'm trying to include the Scalabium TSMDBGrid into the IDE/Palette.

So far it has worked fairly well by using:


...
  IDEScripter1.DefineClassByRTTI(TSMDBGrid,    '', [mvpublic, mvpublished], true, TRedefineOption.roInclude);

...
  RegisterComponent('Data Controls',  TSMDBGrid,   'Grids,DBGrids');
...



However, it has various TNotifyEvents that aren't being registered.

I can't figure out how to get this declaration working:


 TOnFilterApply = procedure (Sender: TObject; Field: TField; const FilterString: string; var Accept: boolean) of object; 



When I try adding an OnFilterApply event to the grid, I get:


 formMain: Event adapter not defined for 'OnFilterApply' property (TOnFilterApply) when evaluating instruction CallClassProc ($297,$1,$809B58,$46DF720,'Create').
Stack content is: [UnicodeString:D:\Data\EDI\In\850\Log\paccar850_ST-R437030_2017-07-17-210343-716.xml,Integer:157320624].



The property is published in the TSMDBGrid class:

      property OnFilterApply: TOnFilterApply read FOnFilterApply write FOnFilterApply;


Cheers,
EdB

Hello, that's a TOnFilterApply event, not TNotifyEvent. Thus you must register the event type in scripter. You must use DefineEventAdapter. Below is an example of registering the TCloseQueryEvent, and here are links for other forum topics where users asked similar question:


http://www.tmssoftware.com/site/forum/forum_posts.asp?TID=5997&PID=22775&title=trzstringgrid-ondrawcell-event-adapter-notdefined#22775


https://www.tmssoftware.com/site/forum/forum_posts.asp?TID=5625&title=event-adapter-not-defined-for-ondrawcolumncell



  TatFormsDispatcher = class(TatEventDispatcher)
  private
    procedure __TCloseQueryEvent( Sender: TObject; var CanClose: Boolean);




procedure TatFormsDispatcher.__TCloseQueryEvent( Sender: TObject; var CanClose: Boolean);
var
  CanCloseTemp: variant;
begin
  if DoOnExecuteEvent then
  begin
    CanCloseTemp := CanClose;
    if Assigned(Scripter) and (RoutineName > '') then
      Scripter.ExecuteSubroutine(RoutineName, [Sender,CanCloseTemp]);
    CanClose := CanCloseTemp;
  end;
end;


  DefineEventAdapter(TypeInfo(TCloseQueryEvent), TatFormsDispatcher, @TatFormsDispatcher.__TCloseQueryEvent);

Thanks Wagner - once again the perfect amount of info to get me going...

Until I get stuck again.

I've set up:


  // support for SMDBGrid onApplyFilter
type
  TMyFilterApplyDispatcher = class(TatEventDispatcher)
    private
      procedure __TOnFilterApplyEvent(Sender: TObject; Field: TField; const FilterString: string; var Accept: boolean);
  end;

...

{ TMyFilterApplyDispatcher }

procedure TMyFilterApplyDispatcher.__TOnFilterApplyEvent(Sender: TObject;
  Field: TField; const FilterString: string; var Accept: boolean);
var
  FieldTemp      : Variant;
  AcceptTemp     : Variant;
  FilterStTemp   : Variant;
begin
  if DoOnExecuteEvent then begin
    AcceptTemp     := Accept;
    if Assigned(Scripter) and (RoutineName>'') then begin
      FieldTemp       := Field.AsVariant;
      FilterStTemp    := FilterString;
      Scripter.ExecuteSubroutine(RoutineName,[Sender, FieldTemp, FilterStTemp, AcceptTemp]);
    end;
    Accept:=AcceptTemp;
 end;
end;

...
 IDEScripter1.DefineClassByRTTI(TField,          '', [mvpublic, mvpublished], true, TRedefineOption.roInclude);
  IDEScripter1.DefineClassByRTTI(TSMDBGrid,            '', [mvpublic, mvpublished], true, TRedefineOption.roInclude);
 
 
DefineEventAdapter(TypeInfo(SMDBGrid.TOnFilterApply),TMyFilterApplyDispatcher,
 @TMyFilterApplyDispatcher.__TOnFilterApplyEvent);



And in the script itself I'm calling:


procedure gridMainFilterApply(Sender: TObject; Field: TField; FilterString: string; var Accept: Boolean);
begin
  // "contents" search
  Accept := (Pos(AnsiUpperCase(FilterString), AnsiUpperCase(Field.AsString))>0);
end;



It doesn't like "Field.AsString":


'RUNTIME
 ERROR File library uLogForm: Access violation at address 0084EFF1 in 
module 'pImportEDI.exe'. Read of address 00000000 when evaluating 
instruction CallProc ($FFFFFFFF,$0,$84EFC8,$8C1D9F0,'AsString').

Stack content is: [Boolean:False,UnicodeString:t,String:TD-A979861,Integer:164755520].
Source position: 130,75
Position: 130, 75'.




This
in no doubt an issue of passing the TField as a variant and trying to
use it as a TField in the script - but in my sleep-deprived state I'm
not making any progress.

Suggestions?

TIA.

Cheers,
EdB

Hi Ed,


you don't need to "convert" all parameters to Variant: only those that need to be passed as reference (in this case, Accept parameter). All the others can be passed directly, like you are doing with Sender parameter:

[thump] [thump] [thump]

Don't mind me whilst I bang my head on the desk at the blindingly obvious.

(sigh)

Thanks Wagner - once again, timely support - and with 100% less snickering than I'd be expressing!

Cheers,
EdB

Don't be so hard with yourself :-)

Dealing with events in scripter is unfortunately not that trivial, at least not as much as I would like. But I'm glad it's working now.