DLL中的Delphi表单工作,但Delphi框架 - 不是

时间:2017-02-22 13:06:36

标签: delphi dll frame

我正在尝试使用仅使用句柄在Delphi制作的DLL中创建一个Form和一个Frame。该表单通常会显示在主机应用程序中,但框架根本不会出现。

可能出现什么问题?

下面我提供了一段创建框架和窗口的代码:

library DLL1;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  System.SysUtils,
  System.Classes,
  DllMain in 'DllMain.pas',
  Winapi.Windows,
  Vcl.Forms,
  Vcl.Controls {DLLFrame1: TFrame},
  DllForm in 'DllForm.pas' {Form1};

{$R *.res}

type
  TSingleton = class
  private
    fra: TDLLFrame1;
    frm: TForm1;
    class var __instance: TSingleton;
    class function __getInstance(): TSingleton; static;
  public
    class property Instance: TSingleton read __getInstance;
    procedure CreateDLLFrame(AppHandle, ParentWindow: HWND);
    procedure CreateDLLForm(AppHandle, ParentWindow: HWND);
    procedure DestroyDLLFrame();
    procedure DestroyDLLForm();
  end;

procedure CreateDLLFrame(AppHandle, ParentWindow: HWND); stdcall;
begin
  TSingleton.Instance.CreateDLLFrame(AppHandle, ParentWindow);
end;

procedure CreateDLLForm(AppHandle, ParentWindow: HWND); stdcall;
begin
  TSingleton.Instance.CreateDLLForm(AppHandle, ParentWindow);
end;

procedure DestroyDLLFrame(); stdcall;
begin
  TSingleton.Instance.DestroyDLLFrame();
end;

procedure DestroyDLLForm(); stdcall;
begin
  TSingleton.Instance.DestroyDLLForm();
end;

exports
  CreateDLLFrame,
  CreateDLLForm,
  DestroyDLLFrame,
  DestroyDLLForm;

procedure TSingleton.CreateDLLFrame(AppHandle, ParentWindow: HWND);
begin
  Application.Handle := AppHandle;
  fra := TDLLFrame1.CreateParented(ParentWindow);
  fra.Show();
end;

procedure TSingleton.DestroyDLLForm();
begin
  frm.Free();
end;

procedure TSingleton.DestroyDLLFrame();
begin
  fra.Free();
end;

procedure TSingleton.CreateDLLForm(AppHandle, ParentWindow: HWND);
begin
  Application.Handle := AppHandle;
  frm := TForm1.CreateParented(ParentWindow);
  frm.Show();
end;

class function TSingleton.__getInstance(): TSingleton;
begin
  if __instance = nil then
    __instance := TSingleton.Create();
  Result := __instance;
end;

end.

DLLFrame:

unit DllMain;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TDLLFrame1 = class(TFrame)
    mmoText: TMemo;
    pnlSend: TPanel;
    edtSend: TEdit;
    btnSend: TButton;
  private
  public
    constructor Create(AOwner: TComponent); override;
  end;

implementation

{$R *.dfm}

{ TDLLFrame1 }

constructor TDLLFrame1.Create(AOwner: TComponent);
begin
  inherited;
  if AOwner = nil then
    MessageBox(0, 'Frame owner is NIL', 'Debug', 0)
  else
    MessageBox(0, PWideChar(AOwner.Name), 'Debug', 0);
end;

end.

1 个答案:

答案 0 :(得分:2)

Delphi TFrame来自TWinControl(因此,TControl),他们有一个所有者,他们有一个父(通常这些是相同的)。所有者控制Frame的生命周期,而Parent控制它显示的位置(即使用哪个Window句柄)。例如,在具有2个表单单元和框架单元的VCL应用程序中,您可以实例化一个框架,使其所有者为Application对象或第一个Form,同时将其父级设为第二个Form;框架将显示在第二个窗体上,即使它的所有者是第一个框架。

What is the difference between Owner and Parent of a control?

这个小例子不使用DLL,但它显示了如果没有分配Parent就不会显示帧:

unit CreateFrameAtRunTimeForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm2 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

uses CreateFrameAtRunTimeFrame;

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);

var
   F : TFrame3;

begin
   F := TFrame3.Create(self);
   F.Name := 'Frame'+Random(1000000).ToString;
   F.Panel1.Caption := 'Frame '+F.Name;
   F.Left := 200;
   F.Top  := 100;
end;

procedure TForm2.Button2Click(Sender: TObject);

var
   F : TFrame3;

begin
   F := TFrame3.Create(self);
   F.Name := 'Frame'+Random(1000000).ToString;
   F.Panel1.Caption := 'Frame '+F.Name;
   F.Left := 200;
   F.Top  := 100;
   F.Parent := self;
end;

end.

我确定你的问题是Frame没有Parent控件,如果你只传递窗口句柄,我认为不可能设置一个。