Reputation: 1
I'm trying to call a ChildForm from a main form to a DLL.
When I take out cxDBTreeList, I get an error when creating it...
If I delete the cxDBTreeList again, it works without any errors.
It seems that the Result is null in the TcxEditDBRegisteredRepositoryItems.GetItemByDataBinding event.
With an empty cxDBTreeList, the Result seems to be null in the TcxScrollBarPainter.GetMinThumbnailSize event.
@DLLForm
library Project1;
uses
System.SysUtils,
System.Classes,
Forms,
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
function CreateDLLForm(App: TApplication): TForm;
begin
Application := App;
Form1 := TForm1.Create(Application.MainForm);
Result := Form1;
end;
exports
CreateDLLForm;
unit Unit1;
...
type
TForm1 = class(TForm)
cxDBTreeList1: TcxDBTreeList;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
end.
@MainForm
unit Unit1;
...
var
Form1: TForm1;
DLLHandle: THandle;
DLLForm : TForm;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
type
TDLLProc = function(App: TApplication): TForm;
var
AProcedure : TDLLProc;
MessageStr : String;
begin
DLLHandle := LoadLibrary(PChar( 'Project1.dll' ));
if (DLLHandle > 32) then
begin
@AProcedure := GetProcAddress( DLLHandle, PChar( 'CreateDLLForm' ) );
if (@AProcedure <> nil ) then
begin
DLLForm := AProcedure(Application);
with DLLForm do
begin
Width := 500;
Height := 500;
end;
Application.ProcessMessages;
end
else
begin
MessageStr := 'Not find dll file1';
ShowMessage( MessageStr );
end;
end
else
begin
MessageStr := 'Not find dll file2';
ShowMessage( MessageStr );
end;
end;
Upvotes: 0
Views: 290
Reputation: 11
Your missing some basics here, read the link provided by Delphi Coder. As long as you understand you will have multiple, independent copies of the RTL/VCL in memory as David pointed out you could still use a form in a DLL if you do not or can not use packages. You do need to save and restore the DLL's Application handle before releasing the DLL or you could have other problems. The simple thing to do is treat the form in the DLL as a standalone program/process as much as possible, you will never be able to interact with the form in the DLL from the main EXE without making lots of methods or even callbacks. I will not go into that here, but I have included two options to display the form below. You call the SetApplicationHandle, call one of the show form methods then call ResetApplicationHandle.
var
fOldAppHandle: THandle;
procedure SetApplicationHandle(Value: THandle); stdcall;
begin
fOldAppHandle := Application.Handle;
Application.Handle := Value;
end;
function ShowForm1: Integer; stdcall;
begin
Form1 := TForm1.Create(nil);
try
Result := Form1.ShowModal;
finally
Form1.Free;
end;
end;
function ShowForm1WithSize(H, W: Integer): Integer; stdcall;
begin
Form1 := TForm1.Create(nil);
try
Form1.Width := W;
Form1.Height := H;
Result := Form1.ShowModal;
finally
Form1.Free;
end;
end;
procedure ResetApplicationHandle; stdcall;
begin
Application.Handle := fOldAppHandle;
end;
exports
SetApplicationHandle,
ResetApplicationHandle,
ShowForm1,
ShowForm1WithSize;
Upvotes: 1