用Delphi写MIS类程序(一)

 

1.程序的基本界面

1.1 使用MDI 还是 SDI

Windows的程序中,不论窗体的表现形式如何,其实都可以大致分为MDISDI两种不同的程序。在很多的教程中,都是用SDISingle Document Interface)作为例子的,因为SDI比较的简单,程序大都只用一个窗体作界面,几乎所有的功能都集中在这个窗体上。当有些程序确实要用到另外的窗体时,就在主窗体上加个按钮来激活一个模式(model)窗体,但以这种方式表现出来的程序除了编写好像简单一些外,其它方面如外观、功能、扩展等等都十分的不好,所以我建议一般写MIS的程序都使用MDI方式(当然如果应用十分的简单,那用SDI也是好的)。

MDIMultiple Document Interface)多重文件界面最典型的应用莫过于旧版的MS Office 97中的WordExcel,它们有一个主的窗体,同时可以在主窗体里面新建多个样式相同或相似的子窗体。我们在Delphi中,通过代码的生成器十分容易就可以得到这种效果的程序,但这是我们真正需要的东西吗?大家不妨可以试一试。(选择 “File->New->Other->Delphi Project->MDI Application

1.2构造第一个程序

假设现在要编写一个进销存的软件,由于这软件要求使用进仓,出仓,销售,报表等不同的界面,为了使程序中的窗体不至于太松散,所以我们采用MDI方式而不用SDI。我们将建立一个MDI主窗体,然后在它里面添加相应的菜单,同时编写相应的进仓,出仓,销售,报表等的子窗体,我们希望达到的效果是:当用户点菜单上的功能时,相应的子窗体能显示出来供用户使用。现在我们可以模拟一下这个程序。

Delphi中新建一个VCL Forms Application,将这个程序保存为MDI_Tutorial,然后将默认的Form保存为MainForm.pas,把这个FormName改为frmMain,另外设定FormStylefsMDIForm。接着新建两个Form,将这两个文件保存为ChildFormAChildFormB,将其改名为frmChildAfrmChildB,接着将这两个FormFormStylefsMDIChild,同时为了识别这两个Form,分别在Form上放上Label,分别设定LabelCaptionFormAFormB。最后,我们在主窗体(frmMain)上放上一个MainMenu的控件,然后在它上面添加上相应的菜单项(mnFormAmnFormB)。现在虽然一行代码没写,但我们还是可以运行这个程序。运行这个程序后,会发现不但主窗口显示正常,而且连两个子窗口都显示出来,更烦人的是,这两个子窗口居然是不能关掉的,这可不是我们想要的效果。但为什么有这样的效果呢?这个两子窗口是什么时候创建的呢?我们可以打开MDI_Tutorial.dpr,在这个文件中有以下的语句:

1  Application.Initialize;

  2  Application.CreateForm(TfrmMain, frmMain);

  3  Application.CreateForm(TfrmChildA, frmChildA);

  4  Application.CreateForm(TfrmChildB, frmChildB);

  5  Application.Run;

在第34行程序中,我们可以发现frmChildAfrmChildB的构建语句,原来它们是在整个程序一加载时就创建完成的。所以如果我不想它们这么早就构建的话,那么可以把这两句删除掉。这样这两个窗体就不会被创建了。

现在我们来编写MainForm菜单的响应事件:

uses

  ChildFormA, ChildFormB;

 

procedure TfrmMain.mnFormBClick(Sender: TObject);

begin

  frmChildB := TfrmChildB.Create(Application);

  frmChildB.Show;

end;

 

procedure TfrmMain.mnFormAClick(Sender: TObject);

begin

  frmChildA := TfrmChildA.Create(Application);

  frmChildA.Show;

end;

编写好后,我们再运行一次看看。我们会发现,现在菜单上的按钮能正确的响应事件了,即当我点mnFormA时会产生FormA,点击mnFormB时会产生FormB。十分的正常,但当我多次点击mnFormA时,会对应产生多个的FormA,这又不是我们想要的效果(但这确实是MDI文档应有的效果,你看看Word就知道了),为什么不是我们想要的效果呢?试想一下,如果FormA是一个“进仓功能”的窗体时,多点击几下就产生了多个进仓录入界面,先不要说程序的代码如何处理数据,就是用户看了也会晕掉,该在那个窗体中录入才好呢?而且这两个子窗体同样是不能正常关闭的。

其实这可能是大多数初学Delphi的人的迷惑?我们应该怎样去解决这个问题呢?

首先我们先解决不能关闭的问题,我们先找到子窗体对应的关闭事件(以FormA为例),添加以下代码:

procedure TfrmChildA.FormClose(Sender: TObject; var Action: TCloseAction);

begin

  Action := caFree;

end;

这个Action:=caFree是告诉窗体当用户要关闭窗体时要同时释放实例,这样就可以达到真正的关闭窗体了。而为了不让同一个窗体(严格来说是同一个菜单项目所对应的窗体)重复出现,我要增加一些代码去控制

FormA中(FormB中也是类似的)

procedure TfrmChildB.FormDestroy(Sender: TObject);

begin

  frmChildB := nil;

end;

MainForm中加入:

procedure TfrmMain.mnFormBClick(Sender: TObject);

begin

  if frmChildB = nil then

    frmChildB := TfrmChildB.Create(Application);

  frmChildB.Show;

end;

 

procedure TfrmMain.FormCreate(Sender: TObject);

begin

  frmChildA := nil;

  frmChildB := nil;

end;

 

procedure TfrmMain.mnFormAClick(Sender: TObject);

begin

  if frmChildA = nil then

    frmChildA := TfrmChildA.Create(Application);

  frmChildA.Show;

end;

红色的地方是修改原来代码的。我们用frmChildA变量去记住FormA有没有产生,当frmChildAnil的时候就产生一个实例,并将该实例赋值给它,然后再显示,如果frmChildA不是空的,那么就意味着它带了个实例,直接Show出来就可以了;当子窗体被Destroy的时候就把frmChildA设定为nil以保证下次可以正常的创建一个窗体。通过这样,我们就可以达到只产生一个子窗体实例的目的了。

在第一个程序结束之前,我们还要再设定一下这些子窗体的表现形式,我希望这些子窗体一旦创建就是最大化的,那只需修改了窗体中的WindowState值为wsMaximized,同样,如果你如果希望你的程序在Windows98下(虽然这个东西很老,但确还是有人在用的,包括我的母亲!)能比较好看一点,那么请将子窗体的字体设定为“宋体”。

我们的第一个符合MIS开发需求的MDI结构的程序模型就这样完成了,但有没改进的空间呢?是否可以消灭每个子窗体里面那些重复的代码,重复的设置呢?在主窗体中的重复代码呢?

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值