2017-02-22 10 views
-1

Я пытаюсь создать форму и рамку в Delphi-made DLL, используя только ручки. Форма обычно появляется в приложении-хозяине, но кадр вообще не отображается.Delphi Form в DLL работает, но Delphi 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

Где твое определение TDLLFrame1? – Dsm

+0

Обновлено. Код тоже есть. – Paul

+0

Как насчет DLLForm.pas? Как насчет образца кода, который вызывает CreateDLLForm и CreateDLLFrame? –

ответ

1

Delphi TFrame спускаются с TWinControl (и, таким образом, TControl), у них есть Владелец, и у них есть родитель (часто они одинаковые). Владелец управляет временем жизни Frame, в то время как Parent контролирует, где он отображается (т. Е. Какой дескриптор окна должен использоваться). Например, в приложении VCL с двумя модулями формы и блоком кадра вы можете создать экземпляр Frame, если его владельцем является объект Application или первая форма, а его родительская - вторая форма; Рамка будет отображаться во второй форме, хотя ее владелец был первым фреймом.

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

Я тоже думал об этом. В моем примере я попробовал просто установить ParentWindow в Frame Handle или WindowHandle без успеха. Похоже, что свойство «Родитель» TWinControl больше, чем просто «Ручки». –

+0

@Dave Вы не можете сделать это, если не используете пакеты времени выполнения. –