我需要为应用程序添加一些插件功能,以及动态加载和打开插件的能力。
在我的应用程序中(主要形式),我有以下代码:
procedure TfrmMain.PluginClick(Sender: TObject);
Var
DllFileName : String;
DllHandle : THandle;
VitoRunPlugin : procedure (AppHandle, FormHandle : HWND);
begin
DllFileName := (Sender AS TComponent).Name + '.dll';
DllHandle := LoadLibrary(PWideChar (DllFileName));
if DllHandle <> 0 then
Begin
@VitoRunPlugin := GetProcAddress (DllHandle, 'VitoRunPlugin');
VitoRunPlugin (Application.Handle, Self.Handle);
End Else Begin
ShowMessage ('Plugin load error');
End;
FreeLibrary (DllHandle);
end;
我的插件库(仅用于测试):
library plugintest;
uses
System.SysUtils, WinApi.Windows,
Vcl.Forms,
System.Classes,
Vcl.StdCtrls;
{$R *.res}
Procedure VitoRunPlugin (AppHandle, FormHandle : HWND);
Var F : TForm; B: TButton;
Begin
F := TForm.CreateParented(FormHandle);
F.FormStyle := fsNormal;
B := TButton.Create(F);
B.Left := 5; B.Top := 5; B.Height := 50; B.Width := 50;
B.Caption := 'Touch me!';
B.Parent := F;
F.ShowModal;
F.Free;
End;
exports VitoRunPlugin;
begin
end.
表单打开OK,但没有任何效果:我既不能按下按钮,也不能关闭表单。我只能通过Alt + F4关闭它。
怎么了?
答案 0 :(得分:4)
CreateParented
使表单成为子窗口。并且您无法以模态方式显示子窗口。那么,谁知道你的表单出现后会发生什么?我确定无法预测将VCL表单窗口句柄传递给另一个VCL表单的CreateParented
构造函数时会发生什么。
将表单创建更改为:
F := TForm.Create(nil);
为了让表单拥有合适的所有者(我的意思是owner in the Win32 sense),您可能需要覆盖CreateParams
,如下所示:
procedure TMyForm.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.WndParent := FormHandle;
end;
显然,您需要声明派生的TMyForm
类添加一些管道,以允许其重写的CreateParams
方法获取对所有者表单句柄的访问权。
如果您希望按钮执行某些操作,则需要对其进行编码。可以是OnClick
事件处理程序,也可以设置按钮的ModalResult
属性。