如何在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
相关产品推荐
相关产品推荐

