我正在尝试使用仅使用句柄在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.
答案 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控件,如果你只传递窗口句柄,我认为不可能设置一个。