【问题标题】:Delphi Web Script (DWScript) link a script method to an external control eventDelphi Web Script (DWScript) 将脚本方法链接到外部控制事件
【发布时间】:2012-09-23 04:03:32
【问题描述】:

我想知道 DWScript 是否支持使用脚本方法作为 Delphi 表单上的控件的事件处理程序。例如,我想将 TButton OnClick 事件链接到脚本中存在的方法。

我可以通过调用返回 TMethod 对象的 GetProcMethod 来使用 RemObjects Delphi 脚本引擎执行此操作。然后我使用 SetMethodProp 将脚本方法分配给按钮的 OnClick 事件。

procedure LinkMethod(SourceMethodName: String; Instance: TObject; ScriptMethodName: String);
var
  ScriptMethod: TMethod;
begin
  ScriptMethod := ScriptEngine.GetProcMethod(ScripMethodName);

  SetMethodProp(Instance, SourceMethodName, ScriptMethod);
end;

我想在 DWScript 而不是 Rem 对象脚本引擎中执行此操作,因为它可以执行我需要的其他一些东西。

【问题讨论】:

    标签: delphi events dwscript


    【解决方案1】:

    我决定改用 RemObjects。它是最容易使用的,可以满足我的需要。

    【讨论】:

      【解决方案2】:

      AFAIK DWScript 不直接支持您想要实现的目标,但它可以以不同的方式实现。 我将尝试发布一些如何实现它的源代码,但您可能需要对其进行调整以适应您的需求。

      首先,声明一个小包装类,它应该为每个脚本方法分开:

      type
        TDwsMethod = class
        private
          FDoExecute: TNotifyEvent;
          FScriptText: string;
          FDws: TDelphiWebScript;
          FLastResult: string;
          FMethod: TMethod;
        protected
          procedure Execute(Sender: TObject);
        public
          constructor Create(const AScriptText: string); virtual;
          destructor Destroy; override;
      
          property Method: TMethod read FMethod;
          property LastResult: string read FLastResult;
        published
          property DoExecute: TNotifyEvent read FDoExecute write FDoExecute;
        end;
      
      constructor TDwsMethod.Create(const AScriptText: string);
      begin
        inherited Create();
        FDoExecute := Execute;
        FScriptText := AScriptText;
        FDws := TDelphiWebScript.Create(nil);
        FMethod := GetMethodProp(Self, 'DoExecute');
      end;
      
      destructor TDwsMethod.Destroy;
      begin
        FDws.Free;
        inherited Destroy;
      end;
      
      procedure TDwsMethod.Execute(Sender: TObject);
      begin
        ShowMessage('My Method executed. Value: ' + FDws.Compile(FScriptText).Execute().Result.ToString);
      end;
      

      现在我们必须在代码中的某处创建这个类的实例(例如在表单的创​​建事件中):

      procedure TMainForm.FormCreate(Sender: TObject);
      begin
        FDWSMethod := TDwsMethod.Create('PrintLn(100);'); //in constructor we pass script text which needs to be executed
        //now we can set form's mainclick event to our DWS method
        SetMethodProp(Self, 'MainClick', FDWSMethod.Method);
      end;
      
      procedure TMainForm.FormDestroy(Sender: TObject);
      begin
        FDWSMethod.Free;
      end;
      

      现在当我们调用 MainClick 时,我们的脚本被编译并执行:

      【讨论】:

      • 谢谢。不幸的是,直到运行时我才知道所需参数的事件名称。 RemObjects 处理拦截事件调用并将参数转发到脚本事件处理程序。这样你就不需要知道任何关于在编译时被调用的方法。我希望 DWS 能做这样的事情。
      • 目前还没有完成,因为 DWScript 旨在完全可沙盒化并且旨在安全,如果参数之间存在不匹配,RemObject 使用的方法将导致内存损坏或崩溃。 RTTI 在这方面取得了一些进展,但它仍然容易受到内存泄漏或 AV 的影响,因为没有办法自动化 Delphi 事件的内存管理。如果有人可以忍受这些限制并发布支持代码,我会整合它......并带有适当的“警告”通知;-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-24
      • 2014-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多