hyeong
hyeong

Reputation: 1

delphi VCL DLL Form Call Error ( Access Violation )

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

Answers (1)

TDC
TDC

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

Related Questions