调用DLL中的MDIChild窗体后关闭时 action := caFree 的问题?(100分)

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

shunbing

Unregistered / Unconfirmed
GUEST, unregistred user!
我的代码如下:
//-------------- Library begin -----------------
library DLLForm;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

uses
Windows,
SysUtils,
Classes,
Forms,
dialogs,
Messages,
Help in 'Help.pas' {FrmHelp}; //MDIChild窗体

var
DLLAPP: TApplication;
DLLScreen: TScreen;
TheForm: TForm;
TheClass: TPersistentClass;

{$R *.res}

procedure RunDLL(DLLName, FormName, FormCaption: String; APP: TApplication; SC: TScreen) stdcall;
begin
Application := App;
Screen := SC;
RegisterClasses([TFrmHelp]);
TheClass := GetClass(PChar('T' + FormName));

if (TheClass <> nil) and TheClass.InheritsFrom(TForm) then
begin
TheForm := TForm(TheClass.Create).Create(nil);
TheForm.Show;
end;
end;

procedure DLLUnLoadProc(Reason: Integer);
begin
if Reason = DLL_PROCESS_DETACH then
begin
Application := DLLApp;
Screen := DLLScreen;
FreeAndNil(TheForm);

SendMessage(Application.Handle, WM_CLOSE, 0, 0);
FreeLibrary(Application.Handle);
end;
end;

exports
RunDLL;

begin
DLLAPP := Application;
DLLScreen := Screen;
DLLProc := @DLLUnLoadProc;
end.
//---------------------- Library end ----------------
//---------------------- UNIT begin ----------------
unit Unit1;

interface

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

const
WM_WXBFREE =WM_USER+1982;
type
TDLLMainForm = class(TForm)
MainMenu1: TMainMenu;
DLL1: TMenuItem;
DLL2: TMenuItem;
procedure DLL2Click(Sender: TObject);
private
procedure wxbFreeLib(var Message: TMessage) ; message WM_WXBFREE;
{ Private declarations }
public
{ Public declarations }
end;

Type
TRunDLL = procedure(DLLName, FormName,FormCaption: String; Application: TApplication; Screen: TScreen); stdcall;

procedure RunDLLForm(DLLName, FormName,FormCaption: String; App: TApplication; SC: TScreen); stdcall;

var
GetDLLHWND: HWND;
DLLMainForm: TDLLMainForm;

implementation

{$R *.dfm}

procedure RunDLLForm(DLLName, FormName,FormCaption: String; App: TApplication; SC: TScreen); stdcall;
var
RunDLL: TRunDLL;
begin
GetDLLHWND := LoadLibrary(PChar(DLLName));
if GetDLLHWND < 32 then
begin
MessageBox(0, PChar('未找到DLL'), PChar('加载DLL失败'), MB_OK);
Exit;
end;

@RunDLL := GetProcAddress(GetDLLHWND, PChar('RunDLL'));
if @RunDLL <> nil then
begin
Try
RunDLL(PChar(UpperCase(Trim(DLLName))), PChar(UpperCase(Trim(FormName))),PChar(FormCaption), APP, SC);
Except
Raise Exception.Create('T' + FormName + '不存在');
End;
end;
end;

procedure TDLLMainForm.DLL2Click(Sender: TObject);
begin
RunDLLForm('DLLForm', 'FrmHelp', 'FrmHelp', Application, Screen)
end;

end.
//------------------ UNIT end ----------------
现在子窗体能够打开,也能够关闭,因为子窗体的onClose事件加了action := caFree这段代码,但在主窗体退出时会报地址错误,如果不要那段代码,子窗体只能最小化,不能关闭,请问各位高手,怎样才能既关闭子窗体,又能不报错呢?
 
procedure DLLUnLoadProc(Reason: Integer);
begin
if Reason = DLL_PROCESS_DETACH then
begin
Application := DLLApp;
Screen := DLLScreen;
FreeAndNil(TheForm);

SendMessage(Application.Handle, WM_CLOSE, 0, 0);
//FreeLibrary(Application.Handle); --去掉这句试试。
end;
end;
 
TO jennykiller:去掉不会造成内存泄漏吗?
 
疑问1:
既然都 FreeAndNil(TheForm); 怎么还在action := caFree?

疑问2:
FreeLibrary(Application.Handle); FreeLibrary是对 LoadLibrary加载的dll引用计数减一 你这个Application.Handle和GetDLLHWND似乎不是一回事情吧?
 
FreeAndNil(TheForm);
我觉得你这一句话可以不要的,在你的窗体里面既然写了
Action:=CaFree;
在Destroy事件里面写 TheForm:=nil;
我觉得这样更好点
 
顶!LZ记得给分哈~~~
 
dll中我这样:
procedure LoadPlugIn(vHandle: THandle; vForm: TForm); stdcall;
begin
Application.Handle := vHandle;
FrmFill := TFrmFill.Create(vForm);
try
FrmFill.ShowModal;
finally
FrmFill.Free;
end;
end;

没有泄漏。
 
procedure DLLUnLoadProc(Reason: Integer);
begin
if Reason = DLL_PROCESS_DETACH then
begin
Application := DLLApp;
Screen := DLLScreen;
//FreeAndNil(TheForm); --去掉这句OK

SendMessage(Application.Handle, WM_CLOSE, 0, 0);
FreeLibrary(Application.Handle);
end;
end;
我的Dll中子窗口调用一切正常,只是个别时候出现了Font错误;查证了很长时间还没有办法处理,有兴趣一起学习学习。
 
谢谢以上的兄弟!
希望各位兄弟不吝赐教!
 
多人接受答案了。
 
后退
顶部