我在DLL里Create一个Form,
Function ShowForm(URL:PChar):integer;stdcall;
var
MyForm:TForm1;
begin
Unit1.URL:=String(URL); //我在这里定义的Form1
MyForm:=TForm1.Create(nil);
MyForm.Show;
//MyForm.Free; //如果Dll里写这句话,那么调用的时候不出错,但是我就是想不free,因为我要用这个Form呀!但是不写的话,调用的程序在关闭的时候出内存错误!为什么呢?
ShowBSForm:=1;
end;
exports
ShowForm;
大家帮忙解释一下,我在PB里和Delphi里调用都有这个问题
Function ShowForm(URL:PChar):integer;stdcall;
var
MyForm:TForm1;
begin
Unit1.URL:=String(URL); //我在这里定义的Form1
MyForm:=TForm1.Create(nil);
MyForm.Show;
//MyForm.Free; //如果Dll里写这句话,那么调用的时候不出错,但是我就是想不free,因为我要用这个Form呀!但是不写的话,调用的程序在关闭的时候出内存错误!为什么呢?
ShowBSForm:=1;
end;
exports
ShowForm;
大家帮忙解释一下,我在PB里和Delphi里调用都有这个问题
解决方案 »
- FastReport3问题,急。。。。。。。。。 在线等!
- 请教如何来唯一标识一台机器
- 一个Excel导入问题,如何解决?
- 遇到了一个奇怪的问题,请高手帮忙
- 如何使SPEEDBUTTON上的图标在 Enable:=False 变为凹陷的效果
- 高分求购:如何做成象资源浏览器那样的信息管理方式?
- 打印问题
- 我是初学者,希望高手们来帮忙,DBGRID我想排序,怎么设置升序和降序呢?
- 如何把edit中的数字在用户输入完后自动加上小数位 如输入10 输入完后自动变成¥10.00
- 有人可以解决这个问题吗?
- 如何把DBGird里的记录导出到ACCESS中去...急!!!!!!!!!
- 用Delphi的都是高手,哪位高手使用过TAPI过来帮助一下!
MyForm.ShowModal;
MyForm.Free;
var
MyForm:TForm1;
begin
Application.Handle := AHandle;
Unit1.URL:=String(URL); //我在这里定义的Form1
MyForm:=TForm1.Create(nil);
MyForm.Show;
//MyForm.Free; //如果Dll里写这句话,那么调用的时候不出错,但是我就是想不free,因为我要用这个Form呀!但是不写的话,调用的程序在关闭的时候出内存错误!为什么呢?
ShowBSForm:=1;
end;
exports
ShowForm;
还有,就是最后我要做成Dll,用Application.Handle := AHandle行吗?
MyForm.Release;你放心的用
因为 调用你的dll时 主程序被挂起的
调用方式如下:
ShowForm(Application.handle,'HLZW')
MyForm.ShowModal;
CMyForm.Free;
我现在想做的是:不想让主程序被挂起,怎么办呢?
还有,你告诉我的办法我有点想不明白,release难道不释放对象吗?如果不释放的话它都做了些什么呢?如果释放的话那窗体为什么不消失呢?
我写成Show,然后release为什么窗体就消失了呢?请告知。
OldExitProc:Pointer;
Form1: TForm1;Function ShowForm(URL:PChar):integer;stdcall;
var
MyForm:TForm1;
begin
Unit1.URL:=String(URL); //我在这里定义的Form1
MyForm:=TForm1.Create(nil);
MyForm.Show;
//MyForm.Free; //如果Dll里写这句话,那么调用的时候不出错,但是我就是想不free,因为我要用这个Form呀!但是不写的话,调用的程序在关闭的时候出内存错误!为什么呢?
ShowForm:=1;
end;
procedure MyExitProc;
var
gfa:ATOM;
begin
gfa:=GlobalFindAtom('MyFormCreate');
if (gfa<>0) then
begin
Form1.Free;
GlobalDeleteAtom(gfa);
end;
ExitProc:=OldExitProc;
end;
exports
ShowForm;
begin
GlobalAddAtom('MyFormCreate');
OldExitProc:=ExitProc;
ExitProc:=@MyExitProc;
end.
//在Form1的onClose这样写。
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
gfa:ATOM;
begin
Action:=caFree;
gfa:=GlobalFindAtom('MyFormCreate');
if (gfa<>0) then
begin
GlobalDeleteAtom(gfa);
end;
end;
按你的意思是把procedure MyExitProc给导出为ShowForm吗?我不太明白。
ExitProc有定义吗?
exports
ShowForm;
到底是针对哪个函数呢?
exports
ShowForm;
//导出结束
begin//动态连接库初始开始
GlobalAddAtom('MyFormCreate');
OldExitProc:=ExitProc;
ExitProc:=@MyExitProc;
end.//动态连接库初始结束//这样该明白了吧?兄台好好看看Library文件结构就明白了。
OldExitProc:Pointer;
Form1: TForm1;
//--------------------------------------------------------
Function ShowForm(URL:PChar):integer;stdcall;
var
MyForm:TForm1;
begin
Unit1.URL:=String(URL); //我在这里定义的Form1
MyForm:=TForm1.Create(nil);
MyForm.Show;
//MyForm.Free; //如果Dll里写这句话,那么调用的时候不出错,但是我就是想不free,因为我要用这个Form呀!但是不写的话,调用的程序在关闭的时候出内存错误!为什么呢?
ShowForm:=1;
end;
//--------------------------------------------------------
procedure MyExitProc;
var
gfa:ATOM;
begin
gfa:=GlobalFindAtom('MyFormCreate');
if (gfa<>0) then
begin
Form1.Free;
GlobalDeleteAtom(gfa);
end;
ExitProc:=OldExitProc;
end;
//--------------------------------------------------------
exports
ShowForm;
//--------------------------------------------------------
begin
GlobalAddAtom('MyFormCreate');
OldExitProc:=ExitProc;
ExitProc:=@MyExitProc;
end.
//--------------------------------------------------------
//这样够清晰了吧。
我应该把MyForm定义成局部的还是全局的呢?
//在dll单元中这样写。var
OldExitProc:Pointer;
MyForm:TForm1;
//--------------------------------------------------------
Function ShowForm(URL:PChar):integer;stdcall;
begin
Unit1.URL:=String(URL); //我在这里定义的Form1
MyForm:=TForm1.Create(nil);
MyForm.Show;
ShowForm:=1;
end;
//--------------------------------------------------------
procedure MyExitProc;
var
gfa:ATOM;
begin
gfa:=GlobalFindAtom('MyFormCreate');
if (gfa<>0) then
begin
MyForm.Free;
GlobalDeleteAtom(gfa);
end;
ExitProc:=OldExitProc;
end;
//--------------------------------------------------------
exports
ShowForm;
//--------------------------------------------------------
begin
GlobalAddAtom('MyFormCreate');
OldExitProc:=ExitProc;
ExitProc:=@MyExitProc;
end.
//--------------------------------------------------------
//在Form1的onClose这样写。
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
gfa:ATOM;
begin
Action:=caFree;
gfa:=GlobalFindAtom('MyFormCreate');
if (gfa<>0) then
begin
GlobalDeleteAtom(gfa);
end;
end;
还有个问题,
begin
GlobalAddAtom('MyFormCreate');
OldExitProc:=ExitProc; //这句话每次调用函数的时候都先执行吧?
ExitProc:=@MyExitProc;
end.
开始的时候ExitProc是什么呢?
ExitProc:=@MyExitProc,我看了一下,MyExitProc里把ExitProc:=OldExitProc;好象是个圈呀?不明白了,请指教!
MyExitProc里的ExitProc:=OldExitProc;去掉了。
把OldExitProc的声明也去掉了。您看行吗?
应该就不会有问题了
-------------------------------------------------------------------
我把代码改了改,也没有问题。我把OldExitProc:=ExitProc; 去掉了。
MyExitProc里的ExitProc:=OldExitProc;去掉了。
把OldExitProc的声明也去掉了。您看行吗?
-------------------------------------------------------------------
拜托你不要那样做,我加这些代码的原因是因为当动态连接库卸载时如果MyForm没有
关闭并卸载就会在DLL卸载时卸载MyForm,如果你把这些去掉我做的一切工作都是白费,
你想,进程都被杀死了(DLL卸载了),而在它的空间内开辟的窗口资源(MyForm)还有可能
没有关闭并释放,这是多么不安全的做法,不出错实在是侥幸。求您不要那样做!!!
//在dll单元中这样写。var
OldExitProc:Pointer;
MyForm:TForm1;
//--------------------------------------------------------
Function ShowForm(URL:PChar):integer;stdcall;
begin
GlobalAddAtom('MyFormCreate');
Unit1.URL:=String(URL); //我在这里定义的Form1
MyForm:=TForm1.Create(nil);
MyForm.Show;
ShowForm:=1;
end;
//--------------------------------------------------------
procedure MyExitProc;
var
gfa:ATOM;
begin
gfa:=GlobalFindAtom('MyFormCreate');
if (gfa<>0) then
begin
MyForm.Free;
GlobalDeleteAtom(gfa);
end;
ExitProc:=OldExitProc;
end;
//--------------------------------------------------------
exports
ShowForm;
//--------------------------------------------------------
begin
OldExitProc:=ExitProc;
ExitProc:=@MyExitProc;
end.
//--------------------------------------------------------
//在Form1的onClose这样写。
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
gfa:ATOM;
begin
Action:=caFree;
gfa:=GlobalFindAtom('MyFormCreate');
if (gfa<>0) then
begin
GlobalDeleteAtom(gfa);
end;
end;我已经试过,原封不动的运行我的上面这段代码是不可能出错的,不必传Application.Handle.
MyForm:=TForm1.Create(Application);
MyForm.Show;TForm1的Owner改为Application
然后再TForm1的OnClose中写
Action := caFree;
就可,因为在dll卸载时,会自动卸掉Application对象
还有传一个Handle给Application对象,要不在任务栏会出现两个程序的东西
PB我不知道传啥
GlobalAddAtom('MyFormCreate');还用在加载DLL的begin,end之间写吗?
象我说的,
开始的时候ExitProc是什么呢?
ExitProc:=@MyExitProc,我看了一下,MyExitProc里把ExitProc:=OldExitProc;好象是个圈呀?不明白了,请指教!
现在子窗口关闭以后关闭主窗口是没有问题了,但是我想要的是开子窗口以后象开一个应用程序一样,不受制于任何程序了,用户关闭了就行了,现在把子窗口打开以后,关闭主程序会出错,是不是我问的问题用DLL根本就实现不了?
还有,最后是要给PB用的,到底能实现不?唉!
Action:=caFree;
就行了。原理应该是一样的吧。
to 楼主 老兄我那样做是双保险,正如我说的
--------------------------------------------------------------------------
进程都被杀死了(DLL卸载了),而在它的空间内开辟的窗口资源(MyForm)还有可能
没有关闭并释放,这是多么不安全的做法,不出错实在是侥幸。
--------------------------------------------------------------------------
窗体释放时会告诉发出广播(GlobalDeleteAtom(gfa)语句的功能)。
在动态连接库卸载时会检测窗体是否释放,如果窗体释放了(接到广播),就直接退出,调用系统默认的卸载过程。如果窗体没有释放,就释放后退出。
我想问您最后一个问题,到底能不能实现象我说的,开窗口以后,主程序正常的退出,而开开的窗口正常的工作?
uses Forms就会有一个Application全局对象这你知道吧,
而uses了Forms,Forms就肯定uses了Controls吧
而在
Controls的initialization
initialization
NewStyleControls := Lo(GetVersion) >= 4;
InitControls;
...InitControls里创建了Application对象
在Forms的finalization段
if Application <> nil then DoneApplication;
...procedure DoneApplication;
begin
with Application do
begin
if Handle <> 0 then ShowOwnedPopups(Handle, False);
ShowHint := False;
Destroying;
DestroyComponents;
end;
end;
也就是说不管dll是否被谁调用,dll本身如果创建了窗体,那Dll本身都
有一个Application对象
如果dll是被delphi程序调用,并且是Build With runtime package,并且主程序也是
Build With runtime package,那么dll就和主程序共享一个Application
反之则是两个独立的Application对象,这也是为什么一般要给dll
传个主程序的Applicaiton.Handle的原因
而如果pb调用我就不知道如何传了你问题想得有些复杂了
因为你的dll的窗体是存在于你的pb程序这个进程的地址空间的
当pb程序关掉,窗体所在的地址空间都没了,怎么能不出错呢
你如果实现那样的效果,何不如做成单独的delphi程序
然后你的pb程序同delphi程序使用一些比如内存映像的东西
进行通讯
往DLL里传了一个handle,然后在DLL里Application.handle=传进去的handle,
create的时候要么是(nil),要么是(application)都行,问题就全解决了。