我已经在 Delphi 的 DLL 中构建了一些 VCL 表单,这些表单将在 Inno Setup 安装过程中显示。然而,如果我能够将这些表单嵌入到 Inno Setup 向导中,那将更加简洁。
我该怎么做呢?
我已经在 Delphi 的 DLL 中构建了一些 VCL 表单,这些表单将在 Inno Setup 安装过程中显示。然而,如果我能够将这些表单嵌入到 Inno Setup 向导中,那将更加简洁。
我该怎么做呢?
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids;
type
TEmbeddedForm = class(TForm)
StringGrid1: TStringGrid;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
end;
procedure CreateEmbeddedForm(ParentWnd: HWND); stdcall;
implementation
{$R *.dfm}
{ TEmbeddedForm }
procedure TEmbeddedForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
{ CreateEmbeddedForm }
procedure CreateEmbeddedForm(ParentWnd: HWND); stdcall;
var
R: TRect;
Form: TEmbeddedForm;
begin
Form := TEmbeddedForm.Create(nil);
Form.ParentWindow := ParentWnd;
Form.BorderStyle := bsNone;
GetWindowRect(ParentWnd, R);
Form.BoundsRect := R;
Form.Show;
end;
exports
CreateEmbeddedForm;
end.
这里是Inno Setup脚本:
[Setup]
AppName=My Program
AppVersion=1.5
DefaultDirName={pf}\My Program
[Files]
Source: "MyDLL.dll"; Flags: dontcopy
[Code]
procedure CreateEmbeddedForm(ParentWnd: HWND);
external 'CreateEmbeddedForm@files:MyDLL.dll stdcall';
procedure InitializeWizard;
var
CustomPage: TWizardPage;
begin
CustomPage := CreateCustomPage(wpWelcome, 'Caption', 'Description');
CreateEmbeddedForm(CustomPage.Surface.Handle);
end;
请注意,Inno Setup还支持COM Automation
,所以上述方法并不是将对象嵌入向导表单的唯一选项。但是,它是最简单的方法。
还有一个提示可能对您有用。如果您需要从库中执行某个Inno Setup脚本代码,可以在Inno Setup端创建回调函数,并在DLL端传递和执行它。
GetWindowRect
函数调用的结果(但你不应该这样做),因为如果那个调用失败了,你会在哪里放置表单呢?从你的DLL抛出异常是无用的,因为你不会得到它的对象以供Inno Setup使用。虽然如果您为导出函数添加一个边界参数,或者例如使用现有的SetLastError
机制,并使用29位(通过在IS中调用DllGetLastError
)至少报告IS端找到父级边界失败,您可以修复此弱点。这是我留给你决定的事情。 - TLama这样
。从通常的实现角度来看,这是相当棘手的,因为Inno Setup中定义的每个过程实际上都是一个隐藏对象的方法。当我尝试进行回调时,我花了一些时间才意识到这一点。然后我记起来脚本中的所有事件方法(即使是你自己定义的)都是无对象过程,因此必须有一个隐藏的对象将它们全部包装成方法。 - TLama