+ -
当前位置:首页 → 问答吧 → delphi MDI 子窗体关闭后再打开报错,请大家看看什么原因

delphi MDI 子窗体关闭后再打开报错,请大家看看什么原因

时间:2011-09-23

来源:互联网

Delphi(Pascal) code
//父
unit sybz_main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,Mz_dl, ToolWin, ActnMan, ActnCtrls, ActnMenus, Menus, ImgList,
  ComCtrls, ExtCtrls,Unit_cx,Unit_dj, DB, DBTables, Grids, DBGrids,
  StdCtrls,Unit_dm1;

type
  Tmain = class(TForm)
    MainMenu1: TMainMenu;
    N1: TMenuItem;
    N2: TMenuItem;
    N3: TMenuItem;
    N4: TMenuItem;
    ImageList1: TImageList;
    stat1: TStatusBar;
    tmr1: TTimer;
    Panel1: TPanel;
    DBGrid1: TDBGrid;
    Button1: TButton;
    procedure FormShow(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure tmr1Timer(Sender: TObject);
    procedure N1Click(Sender: TObject);
    procedure N2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    { Private declarations }
  public
     sybz_dj: Tsybz_dj;
     sybz_cx: Tsybz_cx;
    { Public declarations }
  end;

var
  main: Tmain;

implementation

{$R *.dfm}

procedure Tmain.FormShow(Sender: TObject);
begin
    Dl_form.Showmodal;
end;

procedure Tmain.FormActivate(Sender: TObject);
begin
  stat1.Panels[0].Text:='操作人姓名:' +dl_form.Edit1.Text;
  if Dl_Form.Edit1.Text='管理员'
  then
  begin
     main.Enabled:=False;
     MessageBox(0,'请勿使用公用管理员帐号登录本系统!','提示!',MB_ICONSTOP);
     Close;
  end;
end;

procedure Tmain.tmr1Timer(Sender: TObject);
begin
  Stat1.Panels[1].Text:=   FormatDateTime( 'yyyy "年 "mm "月 "dd "日 "   hh:mm:ss ',   Now());
end;

procedure Tmain.N1Click(Sender: TObject);

begin

  //保持窗口唯一

  if sybz_dj = nil then
  begin
    sybz_dj := Tsybz_dj.Create(Self);
  end
  else
  begin
    sybz_dj.Show;
  end;
  sybz_dj.WindowState := wsMaximized; 
 end;






procedure Tmain.N2Click(Sender: TObject);


begin
  if sybz_cx =nil then
  begin
    sybz_cx := Tsybz_cx.Create(nil);
  end
  else
  begin
    sybz_cx.Show;
  end;
  sybz_cx.WindowState := wsMaximized;

end;


procedure Tmain.Button1Click(Sender: TObject);
begin
    dm1.qry_jrtj.Active:=True;
end;

procedure Tmain.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Caption := IntToStr(X) + chr(32) + IntToStr(Y);
  if (X < Panel1.Left+200) or
     (X > Panel1.Left + Panel1.Width) or
     (Y < Panel1.Top) or
     (Y > Panel1.Top + Panel1.Height) then
    Panel1.Hide
  else
    Panel1.Show;
    
end;

end.

//子
unit Unit_dj;

interface

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

type
  Tsybz_dj = class(TForm)
    Label1: TLabel;
    procedure FormActivate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  sybz_dj: Tsybz_dj;

implementation

{$R *.dfm}

uses sybz_main;
procedure Tsybz_dj.FormActivate(Sender: TObject);
begin
  main.stat1.Panels[2].Text:='登记状态';
end;

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

procedure Tsybz_dj.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  Caption := IntToStr(X) + chr(32) + IntToStr(Y);
    if (X < main.Panel1.Left+200) or
       (X > main.Panel1.Left + main.Panel1.Width) or
       (Y < main.Panel1.Top) or
       (Y > main.Panel1.Top + main.Panel1.Height) then
      main.Panel1.Hide
    else
      main.Panel1.Show;
end;

end.

作者: guxinren521   发布时间: 2011-09-23

sybz_dj := nil;
  这个放到窗体的destroy事件下吧。
  好像这样没有什么区别啊

作者: moshao6   发布时间: 2011-09-23

你在主窗体设置了 sybz_dj:Tsybz_dj;定义了一个窗体

在子窗体中还有一个sybz_dj.

在主窗体中创建子窗体时其实用的是主窗体的 sybz_dj 变量
子窗体在close 时 sybz_dj:=nil;其实是 子窗体的变量。

在第二次打开时,主窗体中的 sybz_dj <> nil ;这里调用 sybz_dj.show 肯定会错了.

作者: ZyxIp   发布时间: 2011-09-23

我觉得你的程序有几个问题:
1.窗体命名不好, Tsybz_dj 让别人看根本就不知道是个窗体.最好命令是 Tfrm_sybzdj 所有的窗体都加上 tfrm前缀。
2.窗体单元命令不好。Unit_dj表现不出这是一个窗体单元最好加上 TWindj 使用 TWin前缀。
3.在窗体调用时不要在调用窗体中定义被调用窗体的变量。你在主窗体中:
public
  sybz_dj: Tsybz_dj;
  sybz_cx: Tsybz_cx; 这样不好。

4.窗体的创建的代码最好在窗体自己的单元文件中实现,而你的是在主窗体中调用的。可以参考以下的实现方式。

Delphi(Pascal) code
//主窗体

procedure TWinMain.btn_OpenDJ(Sender:Tobject);
begin
  CreateWinsybzdj(参数);
end;

//子窗体
Winsybzdj

  Tfrm_sybzdj=class(tform)

  public
    class function CreateWinsybzdj(参数):Boolean;

  end;

implementation

var 
  frm_sybzdj:Tfrm_sybzdj;
//如果窗体只是 Show出来,则这样写
class function Tfrm_sybzdj.CreateWinsybzdj(参数):Boolean;
begin
  Result:=False;
  if Not Assigned(frm_sybzdj) then
     frm_sybzdj:=Tfrm_sybzdj.Create(Application);

  frm_sybzdj.Show;
  Result:=True;
  //然后在窗体的 Close 事件中 action:=cafree; frm_sybzdj:=nil;
end;

//如果窗体是ShowModal 出来,则这样写
class function Tfrm_sybzdj.CreateWinsybzdj(参数):Boolean;
var 
  frm_sybzdj:Tfrm_sybzdj; //将上面的变量放在这里。
begin
  Result:=False;
  frm_sybzdj:=Tfrm_sybzdj.Create(Application);

  frm_sybzdj.ShowModal;
  Result:=frm_sybzdj.ModalResult=mrOK;
  frm_sybzdj.Free;
end;


作者: ZyxIp   发布时间: 2011-09-23