Delphi 如何将DLL中的表单嵌入Inno安装向导页面?

Delphi 如何将DLL中的表单嵌入Inno安装向导页面?,delphi,dll,embed,inno-setup,Delphi,Dll,Embed,Inno Setup,我在Delphi DLL中构建了一些VCL表单,这些表单在Inno安装过程中显示。但是,如果我能将这些表单嵌入Inno安装向导,它将更加简洁 我该怎么做呢?对您来说,最简单的方法是创建一个导出函数,该函数将完成库中的所有工作。该函数所需的最小值是表单应嵌入的Inno设置控件句柄的参数。对于嵌入,您需要知道的下一件事情是边界,但是您可以通过库端的WindowsAPI函数调用获得边界 以下是Delphi部分,显示了DLL项目中的单元和表单: unit Unit1; interface uses

我在Delphi DLL中构建了一些VCL表单,这些表单在Inno安装过程中显示。但是,如果我能将这些表单嵌入Inno安装向导,它将更加简洁


我该怎么做呢?

对您来说,最简单的方法是创建一个导出函数,该函数将完成库中的所有工作。该函数所需的最小值是表单应嵌入的Inno设置控件句柄的参数。对于嵌入,您需要知道的下一件事情是边界,但是您可以通过库端的WindowsAPI函数调用获得边界

以下是Delphi部分,显示了DLL项目中的单元和表单:

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]
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安装程序也支持,因此上述方法不是将对象嵌入向导表单的唯一方法。然而,这是最简单的一个


哦,还有一个音符,也许你应该知道。如果您需要从库中执行某个Inno安装脚本代码,可以在Inno安装端生成回调函数,然后在DLL端传递并执行它。

p.S.我有意忽略
GetWindowRect
函数调用的结果(但您不应该),因为如果调用失败,你会在哪里替换表单呢。从DLL中引发异常是无用的,因为您无法将其对象发送到Inno安装程序。不过,如果向导出函数添加边界参数,或者使用现有的
SetLastError
机制和第29位(在IS中调用
DllGetLastError
),至少可以向IS侧报告父边界的查找失败,则可以修复此缺陷。这就是我留给你决定的。我强烈希望使用第一个选项,因为向函数中添加bounds参数会给您带来更好的灵活性。@Sertac,例如。从通常的实现角度来看,这相当棘手,因为Inno设置中定义的每个过程实际上都是一个隐藏对象的方法。当我试图进行回调时,我花了一些时间才意识到这一点。然后我记得脚本中的所有事件方法(即使是您自己定义的)都是无对象过程,因此必须有一个隐藏的对象将它们包装到方法中。这很有趣,谢谢。如果我需要的话,我一定会问一个适当的问题谢谢,非常高兴知道Stack Overflow有一位Inno设置专家:-)