一个调用Dll子窗体如何释放的问题! ( 积分: 100 )

  • 主题发起人 主题发起人 新来的菜鸟
  • 开始时间 开始时间

新来的菜鸟

Unregistered / Unconfirmed
GUEST, unregistred user!
下面是我调用dll子窗体的函数,每次主窗体调用完dll后关闭主窗体就会出错!我想应该是没有释放子窗体的缘故,应该如何释放子窗体呢?请高手告知谢谢!

调用字窗体
function TForm1.Dllfrmshow(frm:integer;dllname:string):boolean;
type
Windowmax= function :boolean;stdcall;
openform =function (pbase:basemsg):string;
var
DLLHandle: THandle;
DLLSub: InvokeDLLForm;
Tf:Windowmax;
Tf2:openform;
Tp,Tp2:TFarProc;
begin

if DllHandle_rk[frm] = 0 then
begin


DllHandle_rk[frm] :=LoadLibrary(PChar(extractfilepath(application.ExeName)+'dll/'+dllname));
if DllHandle_rk[frm] = 0 then
begin
showmessage('调入失败!');
exit;
end;
Windowsid:=frm;
//////////////////////载入函数


//////////////////////载入函数

//DllHandle_rk[frm]:= DLLHandle;
try
if DllHandle_rk[frm] <> 0 then
begin
@DLLSub := GetProcAddress(DllHandle_rk[frm], 'CreateDLLForm');
if Assigned(DLLSub) then
DLLForm := DLLSub(Application, Screen);



////////////////////传递pbase类给dll
Tp2:=GetProcAddress(DllHandle_rk[frm],PChar('openform')); /////open dll函数
Pbase.userid :='yzl';
Pbase.phandle:=Handle;
Pbase.Windowsid:=frm;
if Tp2<>nil
then
begin
Tf2:=openform(Tp2);
BitBtn_Competence[frm]:=Tf2(pbase);
end;
////////////////////传递pbase类给dll

BitBtn_Control(BitBtn_Competence[frm]); ///////初始按钮权限
end;
except
FreeLibrary(DllHandle_rk[frm]);
end;



end
else
begin
BitBtn_Control(BitBtn_Competence[frm]);
Windowsid:=frm;
Tp:=GetProcAddress(DllHandle_rk[frm],PChar('Windowmax')); ////窗口最大化函数
if Tp<>nil
then
begin
Tf:=Windowmax(Tp);
Tf();
end;
end;
end;


主窗体关闭是进行释放,但还是出错我定义了一个 DllHandle_rk:array[0..150] of Thandle;//DLL文件存放入口 用于存放DLL的Handle的,不知释放的对否,请高手解答谢谢
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
i:integer;
begin
for i:=1 to 10 do
if DllHandle_rk <> 0 then
FreeLibrary(DllHandle_rk);
self.Close;
end;
 
for i:=High(DllHandle_rk) Downto Low(DllHandle_rk) do
if DllHandle_rk <> 0 then
FreeLibrary(DllHandle_rk);
 
to 银雨辰
还是不行呀,程序关闭的时候还是出错!我这个是多dll调用的,是不是没有释放完呀,麻烦帮我看看还有什么地方没有释放的,谢谢!
 
子窗口 最好是 DLL 内创建 就在DLL内释放
由DLL 来管理

你这样来回调用/释放很容易出问题的
 
呵,在dll窗体里我也释放了这上关闭窗体时候的代码
procedure TfrmDLLForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
freeandnil(frmDLLForm);
end;

在主窗体关闭的时候的代码
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
i:integer;
begin
for i:=1 to 10 do
if DllHandle_rk <> 0 then
FreeLibrary(DllHandle_rk);
self.Close;
end;

以上是子窗体和主窗体关闭时的代码,请帮我看看有啥问题吗?最好能不能用主窗体来控制释放子窗体呢?因为用户有时候不一定是关了子窗体再关主窗体的,他们有可能直接关主窗体。请帮我看看如何用主窗体释放全部的子窗体,麻烦了,谢谢!
 
两处释放当然会出问题!
一处释放就可以了
 
但我把子窗体的释放去掉了在主窗体释放他还是出错!
 
就在子窗体关闭的时候释放它自己就行达
action:=cafree;
XXX:=nil;
 
在下面这段调用dll代码里我把调用函数那部分屏蔽掉,只调用dll窗体时我就算是没关子窗体直接关主窗体都不会出错,我想应该还函数调用的时候有问题!
function TForm1.Dllfrmshow(frm:integer;dllname:string):boolean;
type
Windowmax= function :boolean;stdcall;
openform =function (pbase:basemsg):string;
var
DLLHandle: THandle;
DLLSub: InvokeDLLForm;
Tf:Windowmax;
Tf2:openform;
Tp,Tp2:TFarProc;
begin

DllHandle_rk[frm] :=LoadLibrary(PChar(extractfilepath(application.ExeName)+'dll/'+dllname));
if DllHandle_rk[frm] = 0 then
begin
showmessage('调入失败!');
exit;
end;
try
if DllHandle_rk[frm] <> 0 then
begin
@DLLSub := GetProcAddress(DllHandle_rk[frm], 'CreateDLLForm');
if Assigned(DLLSub) then
DLLForm := DLLSub(Application, Screen);


/////////////////我把这段屏蔽掉关闭主窗体时候就没出错,这段应该咋改呢?
////////////////////传递pbase类给dll
Tp2:=GetProcAddress(DllHandle_rk[frm],PChar('openform')); /////open dll函数
Pbase.userid :='yzl';
Pbase.phandle:=Handle;
Pbase.Windowsid:=frm;
if Tp2 <> nil
then
begin
Tf2:=openform(Tp2);
BitBtn_Competence[frm]:=Tf2(pbase);
end;
////////////////////传递pbase类给dll
/////////////////我把这段屏蔽掉关闭主窗体时候就没出错,这段应该咋改呢?


end;
except
FreeLibrary(DllHandle_rk[frm]);
end;
end;
 
你的 pbase类 是怎么定义的
赋值前是否已经创建?

单步调试 看你屏蔽的那部分代码哪里异常!!
 
to 银雨辰
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, Buttons, ComCtrls, ToolWin, ExtCtrls, StdCtrls;
const
WM_ModifyAA= WM_USER + 20;
WM_ModifyAB= WM_USER + 21;
type
basemsg=packed Record
phandle:Thandle;
userid:string;
Windowsid:integer;
BitBtn_Control:string;
end;

我在调用dll函数的时候没有出错,函数也调用正常,就是在关闭主窗体的时候出错的,是不是函数地址没有释放之类的!
 
真奇怪 调用一个窗体为什么要把这个窗体整体暴露给调用者?
你只需要暴露一个调用的函数就可以了
如果要暴露整个类 就不应该用dll应该用bpl更合适
 
to ball_cao
呵,我的目的是在想调用dll的时候把pbase类传给dll,也就是说要传一组变量给dll,如你有什么更好的方法能不能告诉我,只要能达到传变量的问题就可以!谢谢
 
我也有同样的问题,期待中.....
 
呵这是主窗体的全部原码,运行正常,而且函数也调用正常,就是在关闭主窗体的时候回报错,如果把函数调用的那段代码屏蔽掉就一切正常了!

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, Buttons, ComCtrls, ToolWin, ExtCtrls, StdCtrls;
type
basemsg=packed Record
phandle:Thandle;
userid:string;
Windowsid:integer;
BitBtn_Control:string;
end;

type
InvokeDLLForm = function(App: TApplication; Scr: TScreen): TForm;
TForm1 = class(TForm)
ToolBar1: TToolBar;
BitBtn1: TSpeedButton;
BitBtn2: TSpeedButton;
BitBtn3: TSpeedButton;
BitBtn4: TSpeedButton;
ToolButton3: TToolButton;
BitBtn5: TSpeedButton;
BitBtn6: TSpeedButton;
BitBtn7: TSpeedButton;
BitBtn8: TSpeedButton;
BitBtn9: TSpeedButton;
bitbtn11: TSpeedButton;
bitbtn12: TSpeedButton;
BitBtn10: TSpeedButton;
MainMenu1: TMainMenu;
N111: TMenuItem;
SBar: TStatusBar;
Timer1: TTimer;
N1: TMenuItem;
Image1: TImage;
N2: TMenuItem;
N3: TMenuItem;
function Dllfrmshow(frm:integer;dllname:string):boolean;
procedure N2Click(Sender: TObject);
private
{ Private declarations }
public
DllHandle_rk:array[0..150] of Thandle;//DLL文件存放入口
BitBtn_Competence:array[0..150] of string;
{ Public declarations }
end;
var
Form1: TForm1;
DLLForm: TForm;
Windowsid:integer;
Pbase:basemsg;
implementation
{$R *.dfm}

function TForm1.Dllfrmshow(frm:integer;dllname:string):boolean;
type
Windowmax=function :boolean;stdcall;
openform=function (pbase1:basemsg):string;
var
DLLHandle:THandle;
DLLSub:InvokeDLLForm;
Tf:Windowmax;
Tf2:openform;
Tp,Tp2:TFarProc;

begin

DllHandle_rk[frm]:=LoadLibrary(PChar(extractfilepath(application.ExeName)+'dll/'+dllname));
DLLHandle:=DllHandle_rk[frm];
if DllHandle_rk[frm]=0 then
begin
showmessage('调入失败!');
exit;
end;
try
if DllHandle_rk[frm] <> 0 then
begin
@DLLSub := GetProcAddress(DllHandle_rk[frm],'CreateDLLForm');
if Assigned(DLLSub) then
DLLForm := DLLSub(Application,Screen);


/////////////////我把这段屏蔽掉关闭主窗体时候就没出错,这段应该咋改呢?
////////////////////传递pbase类给dll

try
Tp2:=GetProcAddress(DLLHandle,PChar('openform')); /////open dll函数
Pbase.userid :='yzl';
Pbase.phandle:=Handle;
Pbase.Windowsid:=frm;
if Tp2 <> nil
then
begin
Tf2:=openform(Tp2);
//BitBtn_Competence[frm]:=Tf2(pbase);
end;
finally
FreeLibrary(DLLHandle);
end;
////////////////////传递pbase类给dll
/////////////////我把这段屏蔽掉关闭主窗体时候就没出错,这段应该咋改呢?

end;
except
FreeLibrary(DllHandle_rk[frm]);
end;
end;

procedure TForm1.N2Click(Sender: TObject);
begin
Dllfrmshow(1,'prjDLL2.dll');
end;

end.


以下是dll原码
unit DLLFormUnit;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Menus, StdCtrls, ExtCtrls, DB, ADODB, Grids, DBGrids;

type
basemsg=packed Record
phandle:Thandle;
userid:string;
Windowsid:integer;
BitBtn_Control:string;
end;
const
WM_ModifyAA= WM_USER + 20;
WM_ModifyAB= WM_USER + 21;
type
TfrmDLLForm = class(TForm)
Label1: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);

private
/// procedure WMSysCommand(var Msg:TMessage);message WM_SYSCOMMAND; //////最大化最小化事件
{ Private declarations }
public
{ Public declarations }
end;
function openform(pbase:basemsg):string;
function save:boolean;stdcall;
function Windowmax:boolean;stdcall;
function Cancellation:boolean;stdcall;
function Preview:boolean;stdcall;
function Print:boolean;stdcall;
function Add:boolean;stdcall;
function Delete:boolean;stdcall;
function modif:boolean;stdcall;
function View:boolean;stdcall;
function Refresh:boolean;stdcall;
function Audit:boolean;stdcall;
function Derived:boolean;stdcall;
var
frmDLLForm: TfrmDLLForm;
puserid:string;
fhandle:Thandle;
Windowsid:integer;
BitBtn_Control:string;
implementation

uses Unit1;

{$R *.dfm}


///在主窗体调用dll的时候dll在这个函数了接收主窗体传过来的变量
function openform(pbase:basemsg):string;
begin
fhandle:=pbase.phandle;
puserid:=pbase.userid;
Windowsid:=pbase.Windowsid;
BitBtn_Control:='110110111011'; ////////////////////////按钮权限
result :=BitBtn_Control;
end;


end.


请各位帮看看为什么调用dll函数的时候关闭时候会报错,谢谢各位了!
 
最好把主窗体的handle传给dll中的子窗体,要不然出错
 
我调试出来了就是在传pbase这个类的时候关闭主窗体就会出错,如果只是定义成
openform =function (i:inetger):string传普通的字符或数字就不会出错,那如果要传一个类过去的话要怎么传呢!!


try
Tp2:=GetProcAddress(DLLHandle,PChar('openform')); /////open dll函数
Pbase.userid :='yzl';
Pbase.phandle:=Handle;
Pbase.Windowsid:=frm;
if Tp2 <> nil
then
begin
Tf2:=openform(Tp2);
//BitBtn_Competence[frm]:=Tf2(pbase);
end;
finally
FreeLibrary(DLLHandle);
end;
 
呵自己搞定了,散分!!
 
多人接受答案了。
 
怎么搞定的
 
后退
顶部