delphi VCL DLL窗体调用错误(访问冲突)



我正试图将ChildForm从主窗体调用到DLL。

当我取出cxDBTreeList时,我在创建它时出错…

如果我再次删除cxDBTreeList,它可以正常工作,没有任何错误。

TcxEditDBRegisteredDepositoryItems.GetItemByDataBinding事件中的Result似乎为null。

如果cxDBTreeList为空,则TcxScrollBarPainter.GetMinThumbnailSize事件中的Result似乎为null。


@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;

您在这里缺少一些基础知识,请阅读Delphi Coder提供的链接。正如David所指出的,只要你知道你的内存中会有RTL/VCL的多个独立副本,如果你不使用或不能使用包,你仍然可以在DLL中使用表单。在释放DLL之前,您确实需要保存并还原DLL的应用程序句柄,否则可能会出现其他问题。简单的做法是尽可能将DLL中的表单视为一个独立的程序/进程,如果不进行大量方法甚至回调,您将永远无法从主EXE与DLL中的窗体进行交互。我不会在这里讨论,但我已经包含了两个选项来显示下面的表格。调用SetApplicationHandle,调用其中一个show form方法,然后调用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;

最新更新