Delphi 如何将DLL中的表单嵌入Inno安装向导页面?
我在Delphi DLL中构建了一些VCL表单,这些表单在Inno安装过程中显示。但是,如果我能将这些表单嵌入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
我该怎么做呢?对您来说,最简单的方法是创建一个导出函数,该函数将完成库中的所有工作。该函数所需的最小值是表单应嵌入的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设置专家:-)