主程序使用完dll中窗体后如何释放,请各位高手帮忙分析一下(200分)

  • 主题发起人 主题发起人 ssjyr
  • 开始时间 开始时间
S

ssjyr

Unregistered / Unconfirmed
GUEST, unregistred user!
project2.dll:

function LoadDLL(): TForm;
begin
dm := Tdm.Create(Application);
Form2 := TForm2.Create(Application);
Result := Form2;

end;

project1.exe:

procedure TForm1.Button1Click(Sender: TObject);
var
ProcAddr: FarProc;
DllShow: TDllShow;
frmDll: TForm;
begin
// if DllHandle = 0 then
DllHandle := LoadLibrary('Project2.dll');
ProcAddr := GetProcAddress(DllHandle, PChar('LoadDLL'));
if assigned(ProcAddr) then
begin
DllShow := ProcAddr;
frmDll := DllShow();
frmDll.show;
end;
end;

这样使用完后,如果要重新修改project2.dll编译的话,会提示,还在使用中,怎样可以用完后就释放呢?
 
你在程序退出时, 这样释放了吗?
Freelibrary('Project2.dll');
 
就是阿,自己Load进来的Dll需要自己释放,Delphi不会管你的
 
Freelibrary('Project2.dll');
 
具体说明一下吧,谢谢了
 
哪里创建,哪里释放,如果是DLL里面创建的,那在DLL里增加个函数自己释放,到时候调用就可以了。
 
把代码写一写,好不好?我是眼高手低呀
 
送你一段程序:
{插件功能}
unit Func_DLL;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;

type
{定义接口函数类型}
TplugShow = function(AHandle:THandle
ACaption:string):Boolean
Stdcall;
TplugName = function:Pchar
StdCall;

plugFail = class(Exception);
{定义TTestPlugIn类,存放caption,Address,call等信息}
TplugInfo = class
Name :string
{存取加载后,GetCaption返回的标题}
Addr :THandle
{存取加载DLL的句柄}
Call :Pointer
{存取ShowDLLForm函数句柄}
end;
var
plugShow :TplugShow;{声明接口函数类型}
plugList :TList
{存放每一个DLL加载后的相关信息}
{------------------------------------------------------------------------------}
{载入插件}procedure PlugIns_Load;
{执行插件}procedure PlugIns_Exec(const intplug :integer);
{释放插件}procedure PlugIns_Free;
{------------------------------------------------------------------------------}
implementation

procedure PlugIns_Load;
function fileQuery(const currDir,currExt:string):string;
var
recFile :TSearchRec;
strTemp :string;
FlgTemp :Integer;
begin{返回指定目录下指定扩展名的文件列表}
result := '';
strTemp := currDir+currExt;
FlgTemp := FindFirst(strTemp, faAnyFile, RecFile);
while (FlgTemp=0) do
begin
if(RecFile.Attr and faDirectory =0) then
result := result +recFile.Name+#13#10;
FlgTemp := FindNext(recFile);
end;
FindClose(recFile);
end;
{000000000000000000000000000000000000000000000000000000000000000000000000000000}
var
intLoop :Integer;
strList :TStrings;
PluRecd :TplugInfo;
pluName :TplugName;
begin{加载插件}
strList := TStringList.Create;
try
plugList := TList.Create;
//查找指定目录下的.dll文件,并存于strList对象中
strList.Text := fileQuery(ExtractFilepath(Application.Exename), '*.dll');
//加载查找到的DLL
for intLoop:=0 to strList.Count-1 do
begin
if(strList[intLoop] = '') then continue;
PluRecd := TplugInfo.Create;
PluRecd.Addr := LoadLibrary(PChar(strList[intLoop]));
if PluRecd.Addr = 0 then
begin
showMessage(format('插件:%s'#$D'装载失败!',[strList[intLoop]]));
continue;
end;
try
@pluName := GetProcAddress(PluRecd.Addr, 'plugName');
PluRecd.Name := pluName;
PluRecd.Call := GetProcAddress(PluRecd.Addr, 'plugShow');
plugList.Add(PluRecd);
except
// raise plugFail.Create('初始化失败');
end;
end;
finally
FreeAndNil(strList);
end;
end;

procedure PlugIns_Exec(const intplug:integer);
begin{运行插件}
try
@plugShow := TplugInfo(plugList[intplug]).Call;{函数调用地址}
if plugShow(application.Handle, TplugInfo(plugList[intplug]).Name) then exit;
except
showMessage('插件执行错误!');
end;
end;

procedure PlugIns_Free;
var
intLoop: Integer;
begin{释放插件}
for intLoop:=plugList.Count-1 downto 0 do
try FreeLibrary(TplugInfo(plugList[intLoop]).Addr)
except end;
plugList.Free;{释放plugIns对象}
end;
end.
 
再送一段调用的例子
procedure TForm_Main.N_plugListClick(Sender: TObject);
var
intLoop :integer;
NewMenu :TMenuItem;
begin
if(Sender = nil) then
begin{释放插件-----------------------------------------------------------------}
N_plugList.Free;
Plugins_Free;
exit;
end else
if(Sender = N_plugList) then
begin{建立插件-----------------------------------------------------------------}
PlugIns_Load;
N_plugList.Visible :=(PlugList.Count>0);
N_plugList.Checked :=false;
for intLoop := 0 to PlugList.Count -1 do
begin
//创建菜单,并将菜单标题,Onclick事件赋值
NewMenu := TMenuItem.Create(Self);
NewMenu.Caption := TplugInfo(PlugList[intLoop]).Name;
NewMenu.OnClick := N_plugListClick;
NewMenu.Tag := intLoop;
if(NewMenu.Caption = '数据服务') then
begin
N_plugList.Checked := true;
N_plugList.Tag := intLoop;
end;
N_plugList.Add(NewMenu);
end;
exit;
end else
begin{点击插件-----------------------------------------------------------------}
TMenuItem(Sender).Checked := not TMenuItem(Sender).Checked;
plugIns_Exec(TMenuItem(Sender).Tag);
exit;
end;
end;
 
我只是要求在使用完dll中窗体后,即dll中窗体关闭后,自动关闭引用句柄.否则必须等到整个应用程序关闭,才能释放.很麻烦
 
最好只是在DLL中导出窗体类,在主程序中创建、释放,比较方便。参考文章
http://www.liu-yi.net/HTML/resource/download/articles/DelphiDLL.pdf
 
象二楼那样建立一个动态调用就可以实现拉,网上有很多调用的例子,找一下就可以了
 
我觉得大家好都是喜欢讲,并没有解决我的问题,很是郁闷.大家把程序写出来可以吗?我真的还是搞不懂哎,"动态调用dll中窗体"难道就这么难吗?
 
人家都说得很清楚了,你还不明白,所以也就没有说话了。
 
if assigned(ProcAddr) then
begin
DllShow := ProcAddr;
frmDll := DllShow();
frmDll.showModal
// 用模态窗体
frmDll.free;
frmDll := nil
// 我没有试,应该没有问题的
end;
 
忘了加一句 freeLibrary( DllHandle)

if assigned(ProcAddr) then
begin
DllShow := ProcAddr;
frmDll := DllShow();
try
frmDll.showModal
// 用模态窗体
finally
frmDll.free;
frmDll := nil
// 我没有试,应该没有问题的
end;
end;

但这样释放窗体不是好的方法,好的方法见 delphi5 开发人员指南吧

Dll 要谁创建谁释放
 
用模态窗体我知道是OK的,关键的问题是我需要的是非模态窗体.如果用模态的话,我早就用了,这样怎么改呢?

try
DllHandle := LoadLibrary('Project2.dll');
ProcAddr := GetProcAddress(DllHandle, PChar('LoadDLL'));
if assigned(ProcAddr) then
begin
DllShow := ProcAddr;
frmDll := DllShow();
frmDll.showmodal;
end;
finally
freelibrary(DllHandle);
end;

用showmodal因为要等窗体返回后再释放当然没问题.如果要用show就不行了,大家再帮忙吧,谢了.
 

Similar threads

I
回复
0
查看
650
import
I
D
回复
0
查看
844
DelphiTeacher的专栏
D
D
回复
0
查看
795
DelphiTeacher的专栏
D
后退
顶部