MDI主窗口打开DLL子窗口后再关闭报内存错误

luquansen 2011-09-01 10:18:09
如果不打开DLL子窗口,直接关闭MDI主窗口不会报错
当打开DLL子窗口后直接关闭主窗口——报错
当打开DLL子窗口,先关闭该子窗口,再关闭主窗口——依然报错,错误一致

代码如下:
...全文
222 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
luquansen 2011-09-05
  • 打赏
  • 举报
回复
解决了,改成动态调用就不报错了,不过还是不知道为什么静态就出错?

另外,DLL开头那段英文注释很重要啊,如果涉及String,单元ShareMem不但在DLL中需要加,引用的pas里面也要加
luquansen 2011-09-05
  • 打赏
  • 举报
回复
请问怎么销毁?

还有四楼,我这个CHILDWIN是MDI子窗体,不是DLL里面的那个,我不调用DLL子窗体是不报错的,所以我觉得应该是3楼说的那样,
但是我不知道怎么销毁,Destroy吗?在哪销毁呢?子窗体onFormClose事件吗?


[Quote=引用 3 楼 shijies 的回复:]

自己创建的对象,不使用时应该销毁,若没有销毁,就关闭窗体,则会产生内存泄露。
[/Quote]
shijies 2011-09-05
  • 打赏
  • 举报
回复
free方法可以销毁对象。
baideyi 2011-09-04
  • 打赏
  • 举报
回复
var
Child: TMDIChild;
子窗口的定义应该在外部的,你在函数内定义,函数调用后,它的生命周期已经结束。所以会产生内存泄露。
shijies 2011-09-04
  • 打赏
  • 举报
回复
自己创建的对象,不使用时应该销毁,若没有销毁,就关闭窗体,则会产生内存泄露。
紫威剩人阚雷 2011-09-04
  • 打赏
  • 举报
回复
我也遇到过这个问题,期待...
luquansen 2011-09-01
  • 打赏
  • 举报
回复
MdiApp
 program Mdiapp;

uses
Forms,
MAIN in 'MAIN.PAS' {MainForm},
CHILDWIN in 'CHILDWIN.PAS' {MDIChild},
about in 'about.pas' {AboutBox};

{$R *.RES}

begin
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TAboutBox, AboutBox);
Application.Run;
end.


MainForm
unit MAIN;

interface

uses Windows, SysUtils, Classes, Graphics, Forms, Controls, Menus,
StdCtrls, Dialogs, Buttons, Messages, ExtCtrls, ComCtrls, StdActns,
ActnList, ToolWin, ImgList;

type
TMainForm = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
FileNewItem: TMenuItem;
FileOpenItem: TMenuItem;
FileCloseItem: TMenuItem;
Window1: TMenuItem;
Help1: TMenuItem;
N1: TMenuItem;
FileExitItem: TMenuItem;
WindowCascadeItem: TMenuItem;
WindowTileItem: TMenuItem;
WindowArrangeItem: TMenuItem;
HelpAboutItem: TMenuItem;
OpenDialog: TOpenDialog;
FileSaveItem: TMenuItem;
FileSaveAsItem: TMenuItem;
Edit1: TMenuItem;
CutItem: TMenuItem;
CopyItem: TMenuItem;
PasteItem: TMenuItem;
WindowMinimizeItem: TMenuItem;
StatusBar: TStatusBar;
ActionList1: TActionList;
EditCut1: TEditCut;
EditCopy1: TEditCopy;
EditPaste1: TEditPaste;
FileNew1: TAction;
FileSave1: TAction;
FileExit1: TAction;
FileOpen1: TAction;
FileSaveAs1: TAction;
WindowCascade1: TWindowCascade;
WindowTileHorizontal1: TWindowTileHorizontal;
WindowArrangeAll1: TWindowArrange;
WindowMinimizeAll1: TWindowMinimizeAll;
HelpAbout1: TAction;
FileClose1: TWindowClose;
WindowTileVertical1: TWindowTileVertical;
WindowTileItem2: TMenuItem;
ToolBar2: TToolBar;
ToolButton1: TToolButton;
ToolButton2: TToolButton;
ToolButton3: TToolButton;
ToolButton4: TToolButton;
ToolButton5: TToolButton;
ToolButton6: TToolButton;
ToolButton9: TToolButton;
ToolButton7: TToolButton;
ToolButton8: TToolButton;
ToolButton10: TToolButton;
ToolButton11: TToolButton;
ImageList1: TImageList;
ToolButton12: TToolButton;
procedure FileNew1Execute(Sender: TObject);
procedure FileOpen1Execute(Sender: TObject);
procedure HelpAbout1Execute(Sender: TObject);
procedure FileExit1Execute(Sender: TObject);
procedure ToolButton12Click(Sender: TObject);
private
{ Private declarations }
procedure CreateMDIChild(const Name: string);
public
{ Public declarations }
end;

var
MainForm: TMainForm;
SHandle:THandle;

function ShowForm(var App: TApplication; ParentForm: TForm): Boolean;stdcall; external 'DLLT.dll';//为了简单,使用静态调用方法

implementation

{$R *.dfm}

uses CHILDWIN, about;

procedure TMainForm.CreateMDIChild(const Name: string);
var
Child: TMDIChild;
begin
{ create a new MDI child window }
Child := TMDIChild.Create(Application);
Child.Caption := Name;
if FileExists(Name) then Child.Memo1.Lines.LoadFromFile(Name);
end;

procedure TMainForm.FileNew1Execute(Sender: TObject);
begin
CreateMDIChild('NONAME' + IntToStr(MDIChildCount + 1));
end;

procedure TMainForm.FileOpen1Execute(Sender: TObject);
begin
if OpenDialog.Execute then
CreateMDIChild(OpenDialog.FileName);
end;

procedure TMainForm.HelpAbout1Execute(Sender: TObject);
begin
AboutBox.ShowModal;
end;

procedure TMainForm.ToolButton12Click(Sender: TObject);
begin
ShowForm(Application, Self);//调用DLL函数调出窗体。传入当前主程序的Application对象和Form1本身
end;

procedure TMainForm.FileExit1Execute(Sender: TObject);
begin
Close;
end;

end.


这个实例是我在网上找的,出错后搜了一下发现不少人遇到过这个问题,但是没找到我能看懂且能够解决问题的答案

请大家帮帮忙,迁就一下我这个初学者,知道解决方法的请尽量写的详细点,最好是能写出具体的代码,多谢了!!
luquansen 2011-09-01
  • 打赏
  • 举报
回复
DLLT
library DLLT;

{ 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
ShareMem,
SysUtils,
Classes,
Forms,
Dialogs,
Windows,
Messages,
F_T in 'F_T.pas' {MDIC_T};

{$R *.res}
var
DLLApp: TApplication;

function ShowForm(var App: TApplication;ParentForm: TForm): Boolean;export; stdcall;
begin
{获取调用窗体的Application,显而易见的功能是 能使你的窗体融合到调用程序中。通过它还能进行很多操作}
Application:= App;//将DLL的Application转为App
MDIC_T:= TMDIC_T.Create(ParentForm);//创建子窗体,子窗体随着ParentForm存在、释放。
MDIC_T.FormStyle:= fsMDIChild;//设置窗体模式
MDIC_T.Show;
end;

{重写Dll入口函数,否则程序会出错}
procedure DLLUnloadProc(Reason: Integer); register;
begin
{DLL取消调用时,发送DLL_PROCESS_DETACH消息,此时将DLL的Application返回为本身}
if Reason = DLL_PROCESS_DETACH then
Application:=DLLApp;
end;

exports
ShowForm;

begin
{在DLL入口预先储存DLL的Application}
DLLApp:=Application;
{DllProc:DLL入口函数指针。Delphi定义为 DllProc: TDLLProc;}
{在此指向我们自己定义的函数}
DLLProc := @DLLUnloadProc;
end.

1,184

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧