You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pascal Script中创建带按钮的表单并为按钮绑定PascalScript编写的事件

没问题,我来帮你搞定这个事儿!要给PascalScript创建的按钮绑定脚本里的事件,核心是在宿主程序(Lazarus的Form)里做好桥接层,让脚本引擎能把自定义的事件处理过程关联到LCL控件的标准事件上。下面是完整的实现步骤和代码示例:

第一步:扩展宿主程序的PascalScript注册逻辑

首先,我们需要在Lazarus的Form单元里,给PascalScript引擎注册更多函数:创建按钮的函数、绑定点击事件的桥接函数,还有脚本要用到的ShowMessage(如果需要的话)。

修改你的Form1单元代码如下:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
  // 引入PascalScript相关单元
  pscustom, psruntime, psglobals;

type

  { TForm1 }

  TForm1 = class(TForm)
    PSScript1: TPSScript;
    procedure PSScript1Compile(Sender: TPSScript);
  private

  public

  end;

var
  Form1: TForm1;

// 声明要注册给脚本的函数
procedure CreateForm;
function CreateButton(ParentForm: TForm; Caption: string; Left, Top: Integer): TButton;
procedure BindButtonClick(Button: TButton; OnClickProc: TProcedure);
procedure ShowMessage(const Msg: string);

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.PSScript1Compile(Sender: TPSScript);
begin
  // 注册创建表单的函数
  Sender.AddFunction(@CreateForm, 'procedure CreateForm;');
  // 注册创建按钮的函数
  Sender.AddFunction(@CreateButton, 'function CreateButton(ParentForm: TForm; Caption: string; Left, Top: Integer): TButton;');
  // 注册绑定按钮点击事件的函数
  Sender.AddFunction(@BindButtonClick, 'procedure BindButtonClick(Button: TButton; OnClickProc: TProcedure);');
  // 注册ShowMessage,让脚本可以弹出提示
  Sender.AddFunction(@ShowMessage, 'procedure ShowMessage(const Msg: string);');
end;

// 实现创建表单的函数(和你原来的代码一致,稍作优化)
procedure CreateForm;
var
  F1: TForm;
begin
  F1 := TForm.Create(Application);
  F1.Caption := '脚本创建的表单';
  F1.Width := 300;
  F1.Height := 200;
  F1.ShowModal;
  F1.Free;
end;

// 实现创建按钮的函数,返回创建好的按钮对象
function CreateButton(ParentForm: TForm; Caption: string; Left, Top: Integer): TButton;
var
  btn: TButton;
begin
  btn := TButton.Create(ParentForm);
  btn.Parent := ParentForm;
  btn.Caption := Caption;
  btn.Left := Left;
  btn.Top := Top;
  btn.Width := 80; // 给按钮设个默认宽度
  Result := btn;
end;

// 桥接函数:把脚本中的无参数过程转换成LCL标准的OnClick事件
procedure BindButtonClick(Button: TButton; OnClickProc: TProcedure);
type
  // 包装类:用于适配脚本过程和LCL事件的参数差异
  TPSClickWrapper = class
    FScriptProc: TProcedure;
    procedure DoClick(Sender: TObject);
  end;
var
  Wrapper: TPSClickWrapper;
begin
  Wrapper := TPSClickWrapper.Create;
  Wrapper.FScriptProc := OnClickProc;
  // 把包装类的方法绑定到按钮的OnClick事件
  Button.OnClick := Wrapper.DoClick;
  // 将包装类实例存到按钮的Tag属性,避免被提前释放
  Button.Tag := Integer(Wrapper);
end;

// 包装类的事件处理方法:调用脚本中的过程
procedure TPSClickWrapper.DoClick(Sender: TObject);
begin
  FScriptProc;
end;

// 实现ShowMessage(直接调用LCL的ShowMessage)
procedure ShowMessage(const Msg: string);
begin
  Dialogs.ShowMessage(Msg);
end;

end.
第二步:在PascalScript中编写事件逻辑并绑定按钮

现在你可以在PascalScript的脚本代码里,创建表单、按钮,并且绑定自己写的点击事件了。示例脚本如下:

var
  MyForm: TForm;
  ClickMeBtn: TButton;

// 脚本自定义的按钮点击事件处理过程
procedure OnBtnClick;
begin
  ShowMessage('太棒了!这是PascalScript里的按钮点击逻辑 😎');
end;

begin
  // 创建表单
  MyForm := TForm.Create(Application);
  MyForm.Caption := '脚本驱动的表单';
  MyForm.Width := 350;
  MyForm.Height := 250;
  MyForm.Position := poScreenCenter; // 让表单居中显示

  // 创建按钮并设置位置
  ClickMeBtn := CreateButton(MyForm, '点击我试试', 120, 80);

  // 把脚本里的过程绑定到按钮的点击事件
  BindButtonClick(ClickMeBtn, @OnBtnClick);

  // 显示表单
  MyForm.ShowModal;
  
  // 释放资源:记得释放包装类实例
  if ClickMeBtn.Tag <> 0 then
    TObject(ClickMeBtn.Tag).Free;
  MyForm.Free;
end.
关键原理说明
  • 参数适配:LCL的按钮OnClick事件要求过程带Sender: TObject参数,但脚本里的事件过程可能不需要这个参数,所以我们用TPSClickWrapper包装类做了转换,把标准事件转换成脚本能识别的无参数过程。
  • 内存管理:把包装类实例存在按钮的Tag属性里,这样在表单释放前可以手动释放包装类,避免内存泄漏。
  • 函数注册:所有脚本要用到的宿主函数(创建控件、绑定事件、弹窗)都必须在PSScript1Compile事件里注册,这样脚本引擎才能识别并调用它们。

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:14:08