我是将test.pas(FORM)封装在abc.dll里 myDll in 'myDll.pas' {Form1};procedure newForm;stdcall;export;
var
frm1:TForm1;
begin
frm1:=TForm1.Create(nil);
frm1.Show;
end;然后用主程序 123.pas 调用"newForm"过程。。test.pas Form能正常显示出来。但按上面的按钮功能。就出现“Access violation at address 004E105F in module 'abc.dll'.Read of address 00000460”错误提示
如果将abc.dll改成这样写却能正常使用我搞不懂这样写有什么区别。。
myDll in 'myDll.pas' {Form1};procedure newForm;stdcall;export;
begin
Form1:=TForm1.Create(nil);
Form1.Show;
end;
我想实现的功能:是主程序 123.pas 有8个按钮。。每点击一个按钮就调用 newForm 动态生成一个 test.pas Form ...
所以想用第一种方法定义窗口来加以区分:
var
frm1,frm2,frm3,frm4,frm5,frm6,frm7,frm8:TForm1;如果按第二种方法的虽然也能正常动态创建8个 test.pas Form 但没办法区分开来。我想显示/隐藏哪个窗口都无法判断
麻烦大家给个方法可以不按我上面所说的。。能实现相同功能就行了
var
frm1:TForm1;
begin
frm1:=TForm1.Create(nil);
frm1.Show;
end;然后用主程序 123.pas 调用"newForm"过程。。test.pas Form能正常显示出来。但按上面的按钮功能。就出现“Access violation at address 004E105F in module 'abc.dll'.Read of address 00000460”错误提示
如果将abc.dll改成这样写却能正常使用我搞不懂这样写有什么区别。。
myDll in 'myDll.pas' {Form1};procedure newForm;stdcall;export;
begin
Form1:=TForm1.Create(nil);
Form1.Show;
end;
我想实现的功能:是主程序 123.pas 有8个按钮。。每点击一个按钮就调用 newForm 动态生成一个 test.pas Form ...
所以想用第一种方法定义窗口来加以区分:
var
frm1,frm2,frm3,frm4,frm5,frm6,frm7,frm8:TForm1;如果按第二种方法的虽然也能正常动态创建8个 test.pas Form 但没办法区分开来。我想显示/隐藏哪个窗口都无法判断
麻烦大家给个方法可以不按我上面所说的。。能实现相同功能就行了
begin
with TTestForm.Create(nil) do
begin
Show;
Result := Handle;
end;
end;var hnd1: THandle;
hnd1 := NewForm;
ShowWindow(hnd1,SW_HIDE); //隐藏
showWindow(hnd1,SW_SHOW); //显示
dll:
myDll in 'myDll.pas' {Form1};function newForm:THandle;stdcall;export;
begin
with TForm1.Create(nil) do
begin
Show;
Result:=Handle;
end;
end;主程序调用:
procedure TForm1.Button1Click(Sender: TObject);
var
hnd1:Cardinal;
begin
hnd1:=newForm;
end;
窗口也是可以正常创建成功。。但点里面的按钮还是出现。
“Access violation at address 004E105F in module 'abc.dll'.Read of address 00000460”错误提示
你的问题中 form1 变量定义在哪里?
你 dll 中的 8 个按钮中,是否直接使用了 form1 变量?
myDll in 'myDll.pas' {Form1}; 这条指令后。。就有个form1自动指向mydll.pas...。。也可以看成mydll.Form1
8个按钮是主程序调用dll 的 newForm...
myDll in 'myDll.pas' {Form1}; 这条指令后。。就有个form1自动指向mydll.pas...。。也可以看成mydll.Form1
8个按钮是主程序调用dll 的 newForm...
var
Form1: TForm1;而别的线程如mydllunit2.pas 要使用 Form的控件时,都要这样写 Form1.edtYjID.Text从而造成上面的错误。。这个该如何改?
Form1:=self;
type TMyPro = function: THandle;
var p: TMyPro;
begin
isShow := False;
hnd := LoadLibrary('testDll.Dll');
if hnd > 0 then
begin
@p := GetProcAddress(hnd,'Form1Show');
if Assigned(@p) then hndWnd := p;
isShow := True;
end;
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if hnd > 0 then FreeLibrary(hnd);
end;procedure TForm1.Button2Click(Sender: TObject);
begin
if hndWnd > 0 then
begin
if isShow then
ShowWindow(hndWnd,SW_HIDE)
else
ShowWindow(hndWnd,SW_SHOWNORMAL);
end;
isShow := not isShow;
end;其中:
private
isShow: Boolean;
hndWnd,hnd: THandle;
{ Private declarations }
=====================================================================
function Form1Show: THandle;implementation{$R *.dfm}function Form1Show: THandle;
begin
with TForm1.Create(Application) do
begin
Result := WindowHandle;
show;
end;
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caFree;
end;其中:exports Form1Show;
所以,不建议你将窗口类控件封装到dll中,应该另开一个bpl,将这些窗口类控件封装到bpl中,然后exe和dll都带包编译,dll中只封装对这些窗口类控件的操作,exe仅仅负责调度。
其实,不单单是窗口类控件,由于dll和exe使用的是两套类机制(虽然都是一样的,但的确是两套),所以如果将dll中的类通过函数引出来供exe用,都会存在问题,因为在exe中,无法正确定位这些类的类信息。
所以,建议你将类封装在包中,dll中仅仅封装功能(也就是把不同的类组装在一起完成某一任务),exe仅仅负责对不同任务的调度。你上面的问题,不是不能解决,而是解决起来太麻烦,而且维护成本也太高。所以,你还是换个思路吧。
原因就是他们使用了两套类机制,这两个按钮的RTTI信息的地址是不一样的