2017-02-22 6 views
-1

핸들 만 사용하여 Delphi에서 DLL로 폼과 프레임을 만들려고합니다. 호스트 응용 프로그램에 양식이 정상적으로 나타나지만 프레임이 전혀 나타나지 않습니다.DLL의 Delphi Form이 작동하지만 델파이 프레임이 아닙니다.

무엇이 잘못 될 수 있습니까?

나는 프레임과 창을 모두 생성 코드의 조각을 제공 아래 :

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

TDLLFrame1에 대한 정의는 어디에 있습니까? – Dsm

+0

업데이트 됨. 코드가 지금도 있습니다. – Paul

+0

DLLForm.pas는 어떻습니까? CreateDLLForm 및 CreateDLLFrame을 호출하는 코드 샘플은 어떻습니까? –

답변

1

델파이 TFrame는 (따라서하고, TControl의) 경우 TWinControl에서 내려, 그들은은을 소유자 및 부모 (이들은 종종 동일합니다)가 있습니다. 소유자는 프레임의 표시 위치 (즉, 어떤 윈도우 핸들이 사용되는지)를 제어하는 ​​동안 프레임의 수명을 제어합니다. 예를 들어, 2 개의 폼 단위와 프레임 단위를 가진 VCL 응용 프로그램에서 프레임의 소유자가 Application 객체이거나 첫 번째 Form 인 프레임을 인스턴스화 할 수 있습니다. 반면에 부모는 두 번째 형식입니다. 프레임은 소유자가 첫 번째 프레임 임에도 불구하고 두 번째 양식에 표시됩니다.

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

이 작은 예는 DLL을 사용하지 않지만, 프레임이 할당되는 부모없이 표시되지 않습니다 방법을 보여줍니다

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. 

나는 당신의 문제가 있음을 확신 프레임에는 부모 컨트롤이 없기 때문에 창 핸들 만 전달하는 경우 프레임 컨트롤을 설정할 수 있다고 생각하지 않습니다.

+0

'CreateParented'는'Parent'를 설정하거나'Winapi.Windows.SetParent'를 호출하는 것과 같습니다. 그러나'TFrame'에는 내부에 CreateWindowEx 호출이 없다는 것을 알았습니다. – Paul

+0

나는 그것도 생각하고 있었다. 필자는 예제에서 Frame의 ParentWindow를 Form의 Handle이나 WindowHandle로 설정해 보았습니다. TWinControl "Parent"속성은 핸들보다 더 많은 것으로 보입니다. –

+0

@Dave 런타임 패키지를 사용하지 않는 한이 작업을 수행 할 수 없습니다. –