请教精通dll的高手,DLL封装MDI子窗体,如何在窗体关闭时自动卸载dll,以减少内存占用?(30分)

  • 主题发起人 主题发起人 richardi
  • 开始时间 开始时间
R

richardi

Unregistered / Unconfirmed
GUEST, unregistred user!
下面是我的代码,exe动态加载dll “baseinfo”,在dll的DLL_PROCESS_DETACH中写了卸载dll语句,实现dll封装的窗体关闭后就卸载dll,好节约内存,现在程序运行不报错,也没内存泄漏,就是当封装的MDI子窗体关闭后,dll不能自动卸载,还占据着内存,请教高手有什么办法能实现动态卸载dll,好节约内存。<br><br><br>library baseinfo;//dll的代码<br>uses<br>&nbsp; SysUtils,<br>&nbsp; Classes,<br>&nbsp; ADODB,<br>&nbsp; Windows,<br>&nbsp; Forms,<br>&nbsp; d_baseinfo in 'd_baseinfo.pas' {dfmBaseInfo};<br>var<br>&nbsp; DllApp:TApplication; &nbsp; &nbsp;//定义变量<br>{$R *.res}<br>procedure CallBaseinfo(const app:TApplication;const adocnn:Tadoconnection);stdcall;<br>begin<br>&nbsp; Application:=app;<br>&nbsp; if dfmBaseInfo=nil then<br>&nbsp; begin<br>&nbsp; &nbsp; dfmBaseInfo:=TdfmBaseInfo.Create(app);//创建mdi子窗体<br>&nbsp; &nbsp; dfmBaseInfo.ADOConnection1:=adocnn; &nbsp;//把参数adocnn对象赋给ADOConnection1获得数据库连接<br>&nbsp; end;<br>&nbsp; dfmBaseInfo.Show;<br>end;<br>procedure MyDLLProc(Reason:Integer);<br>begin<br>&nbsp; if Reason=DLL_PROCESS_DETACH then<br>&nbsp; begin<br>&nbsp; &nbsp; if Assigned(DllApp) then<br>&nbsp; &nbsp; &nbsp; Application:=DllApp;<br>&nbsp; &nbsp; FreeLibrary(Application.Handle); &nbsp;//进程退出时卸载dll<br>&nbsp; end;<br>end;<br>exports<br>&nbsp; CallBaseinfo;<br>begin<br>&nbsp; DllApp:=Application; &nbsp; &nbsp;//把dll的Application先存起来<br>&nbsp; DllProc:=@MyDLLProc; &nbsp; &nbsp;//<br>end. <br>//exe的调用代码<br>type<br>&nbsp; PlugIn=function(const app:TApplication;const adocnn:Tadoconnection):integer;stdcall;<br>……<br><br>procedure Tf_main.N3Click(Sender: TObject);<br>var<br>&nbsp; ahandle:THandle;<br>&nbsp; plug:PlugIn;<br>begin<br>&nbsp; ahandle:=LoadLibrary('baseinfo.dll') ; &nbsp;//动态加载DLL<br>&nbsp; if ahandle=0 then<br>&nbsp; &nbsp; exit;<br>&nbsp; @plug:=GetProcAddress(ahandle,'CallBaseinfo');<br>&nbsp; if @plug &lt;&gt;nil then<br>&nbsp; plug(Application,ADOConnection1);<br>end;
 
简单点的,可以这样<br>在dll内的窗体关闭时用postmessage向主程序发送一个消息。<br>主程序在收到此消息后进行卸载操作。
 
怎么发送消息呢?我不会写,能给些代码吗?
 
在窗体放一个THandle变量<br>var<br>form1:tform;<br>h:THandle;<br><br>把dll的句柄传到dll<br>procedure CallBaseinfo(const app:TApplication;const adocnn:Tadoconnection; dllhandle:THandle);stdcall;<br><br>h:=dllhandle;<br><br><br>关闭窗口,可以<br>FreeLibrary(H);
 
可是这是mdi窗体啊,怎么自动FreeLibrary(H)呢?如果像在下面子窗体中写会报内存错误<br>procedure TdfmBaseInfo.FormClose(Sender: TObject;<br>&nbsp; var Action: TCloseAction);<br>begin<br>&nbsp; dfmBaseInfo:=nil;<br>&nbsp; action:=cafree;<br>&nbsp; FreeLibrary(dllhandle);<br>end;
 
kinneng:我按你说的把卸载代码写在onDestroy中也不行,还是报内存错误<br>procedure TdfmBaseInfo.FormDestroy(Sender: TObject);<br>begin<br>&nbsp; FreeLibrary(dllhandle);<br>end;
 
主窗体<br>const<br>&nbsp; WM_FREEDLL = WM_USER + 100;<br>&nbsp; &nbsp; procedure WM_MessageFreeDll(var AMessage : TMessage); message WM_FREEDLL; &nbsp; &nbsp;<br><br>procedure TFMain.WM_MessageFreeDll(var AMessage: TMessage);<br>begin<br>&nbsp; if AMessage.LParam&lt;&gt;0 then<br>&nbsp; &nbsp; FreeLibrary(AMessage.LParam);<br>end;<br>--------------DLL------------------------------<br>&nbsp; &nbsp; procedure FormDestroy(Sender: TObject);<br>procedure TFBaseChild.FormDestroy(Sender: TObject);<br>begin<br>&nbsp; inherited;<br>&nbsp; &nbsp; //发送消息给主程序,释放调用DLL<br>&nbsp; PostMessage(iParams.MainHandle ,WM_FREEDLL,0,iParams.DllHandle);<br>end;
 
pangzhenguang的写法很好,我在dll中发出消息时出错,显示undeclared identifier wm_freedll,是不是要把exe定义的常量当参数传给dll啊?否则就报错。<br>我的写法是<br>在dll中定义个变量,用来接收exe的handle,MainHnd:THandle;exe传递参数时把handle传给dll的MainHnd变量,发送消息时根据这个MainHnd发送。<br>procedure TdfmBaseInfo.FormDestroy(Sender: TObject);<br>begin<br>&nbsp; inherited;<br>&nbsp; PostMessage(MainHnd,WM_FREEDLL,0,Handle);<br>end;
 
在dll内再定义一下这个常量就可以了。
 
我实际没试过,确实有问题,所以我编了一个没问题的放在这里 http://kinneng.ys168.com/ 在 20081210 里面,OK
 
TMainForm = class(TForm)<br>public<br>property MDIChildCount;<br>end;<br>// 子窗体关闭时 (WM_MDIDESTROY 消息 或 重载 procedure &nbsp; Notification(AComponent: &nbsp; TComponent; &nbsp; Operation: &nbsp; TOperation); &nbsp; override; 过程) <br>if MDIChildCount &lt;= 0 then<br>&nbsp; // ...御载
 
谢谢各位,问题解决了,pangzhenguang和kinneng写法都可以,pangzhenguang发送消息的写法更简单一些。
 
多人接受答案了。
 
后退
顶部