继承后的MDI子窗口不能正确关闭,或者不能正确继承祖先窗口的OnClose事件(100分)

  • 主题发起人 netCobra
  • 开始时间
N

netCobra

Unregistered / Unconfirmed
GUEST, unregistred user!
祖先窗口frmAncestor为MDI子窗口,在OnClose事件中写了:
frmAncestor.Free;
frmAncestor := nil;

但是继承出来的子窗口无法正确关闭,现象是第一次运行的时候正常,第二次运行的时候就会出错,我打开子窗口的语句是这样子写的:
if not Assigned(frmChild) then
frmChild := TfrmChild.Create(frmChild);

frmChild.Show;
单步跟踪发现第一次打开子窗口关闭后,frmChild不是nil,但是Show也无法正确显示,不知道哪里出问题了。

我在子窗口的OnClose事件中写:
frmChild.Free;
frmChild := nil;
就可以了。

但是我不太明白到底什么地方出了问题,难道祖先窗口的OnClose事件子窗口没有继承吗?如果没有继承,那么为什么第一次关闭以后frmChild既不为nil,又不能正确Show呢?
 

Action := caFree;
 
写了这句也是一样,没用[:(]
 
//为什么第一次关闭以后frmChild既不为nil,又不能正确Show呢?
有问题!
换一种方法吧。
 
我想知道为什么,是我继承的方法不对吗?
回头我把源代码贴出来
 
祖先窗口frmAncestor为MDI子窗口,在OnClose事件中写:
Action:=caFree;
 
源程序如下:
三个Unit:UnitMain(frmMain),UnitAncestor(frmAncestor),UnitChild(frmChild);其中frmChild是从frmAncestor继承而来的。

UnitMain源代码:
unit UnitMain;

interface

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

type
TfrmMain = class(TForm)
MainMenu1: TMainMenu;
est1: TMenuItem;
procedure est1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmMain: TfrmMain;

implementation

uses UnitChild;

{$R *.dfm}

procedure TfrmMain.est1Click(Sender: TObject);
begin
//在这里打开frmChild
//第二次打开时frmChild既不是nil也不能正常显示
if not Assigned(frmChild) then
frmChild := TfrmChild.Create(frmChild);
frmChild.Show;
end;
end.

UnitAncestor源代码:
unit UnitAncestor;

interface

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

type
TfrmAncestor = class(TForm)
procedure FormClose(Sender: TObject
var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmAncestor: TfrmAncestor;

implementation

{$R *.dfm}

procedure TfrmAncestor.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Action := caFree;
frmAncestor := nil;
end;
end.

UnitChild源代码:
unit UnitChild;
//直接从frmAncestor继承过来,没有再增加任何脚本。
interface

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

type
TfrmChild = class(TfrmAncestor)
private
{ Private declarations }
public
{ Public declarations }
end;

var
frmChild: TfrmChild;

implementation

{$R *.dfm}
end.


就是这样子的,是否我在继承时Procedure的设置错误了?

谢谢各位。
 
呵呵,我碰到过,不要用
if not Assigned(frmChild) then
来查找,用findwindow应该就可以
原因我也不知道
 
frmAncestor: TfrmAncestor;与frmChild: TfrmChild;是两个不同的变量
父窗体不能自动帮你把frmChild设为NIL的。
 
To xianjun:那么是不是说子窗口的关闭必须我自己手工去做frmChild := nil?

我觉得并不应该是这个样子的,我的想法是在祖先窗口中设了frmAncestor:= nil,在子窗口中会自动的继承为frmChild := nil;是我对继承的理解有错误吗?
 
frmAncestor := nil
--没有任何意义,对象使用了全局变量不符合要求,而且无法



procedure TfrmMain.est1Click(Sender: TObject);
begin
//在这里打开frmChild
//第二次打开时frmChild既不是nil也不能正常显示
if not Assigned(frmChild) then --无法判断,因为虽然用了Action := caFree,但是frmChild还是指向原来的位置
除非你使用frmChild := nil
frmChild := TfrmChild.Create(frmChild)
--错误,参数不能用FrmChild,可以用Self或者Application
frmChild.Show
--不需要
end

正确的使用方法应该是
procedure TfrmMain.est1Click(Sender: TObject);
var
Index : Integer;
hasChild : Boolean;
begin
hasChild := False;
for Index := 0 to Form1.MDIChildCount-1 do
if FrmMain.MDIChildren[Index] is TfrmChild then
begin
hasChild := True;
break;
end;

if not hasChild then frmChild := TfrmChild.Creat(self);
end



 
感谢yjy2002,我回去试试(今天不上班,现在在网吧)
 
顶部