在VB6.0版本的机房收费系统中就用到了MDI技术(多文档界面),其中有的窗体用了MDI,而有的则没有用到,回头想想这些个关于增删改查的功能都该是MDI这个容器中的子窗体,于是这次我将他们都放到了MDI窗体中。
MDI窗体设置步骤:
(1)在frmMain中打开属性窗格,”IsMdiContainer”属性设置为”True”。
(2)把工具箱中MenuStrip控件拖到frmMain中,创建菜单如图
由于最近敲的是“修改密码“的窗体,就拿这个为例。
单击按钮“修改密码”,填写代码如图:'单击“修改密码”执行的操作 Private Sub menuModifyPassword_Click(sender As Object, e As EventArgs) Handles menuModifyPassword.Click Dim NewMDIModifyPassword As New frmModifyPassword '实例化一个新的修改密码的窗体 NewMDIModifyPassword.MdiParent = Me '定义父窗体为frmMain NewMDIModifyPassword.Show() '显示刚定义的窗体 End Sub
此时,运行程序时候已经能够生成子窗体(MDI类型)。
But,请看图:
这幅图片,当多次单击按钮的时候,怎么每次都会弹出一个框框额……,记得在设计模式的时候“单例模式”能够解决这种按钮多次单击避免重复出现窗体的弊端,So,加模式吧。
之前已经加过了“外观”和“抽象工厂”模式,对于设计模式加到机房重构系统中已经不是新鲜事情了,通过看书,这个时候需要加一个“单例模式”,唯一觉得困难的是C#代码到.NET的转换很不好做到,因为之前在敲设计模式的时候都是用C#,这次加“单例模式”大部分时间花在了代码的转换上。
于是Firstly,在“修改密码”窗体中,重新写如下代码:
Private Shared mdfPWD As frmModifyPassword = Nothing '声明一个共享的类变量mdfPWD '该frmModifyPassword类的构造函数 Private Sub New() ' 此调用是设计器所必需的。 InitializeComponent() ' 在 InitializeComponent() 调用之后添加任何初始化。 End Sub '写一个公有的方法来检验这个类是否初始化以及被释放过 Public Shared Function GetInstance() As frmModifyPassword 'If (mdfPWD Is Nothing) Or (mdfPWD.IsDisposed) Then If mdfPWD Is Nothing OrElse mdfPWD.IsDisposed Then mdfPWD = New frmModifyPassword mdfPWD.MdiParent = frmMain.ActiveForm End If Return mdfPWD '把新的窗体返回出来 End Function
Private Sub menuModifyPassword_Click(sender As Object, e As EventArgs) Handles menuModifyPassword.Click ' Dim NewMDIModifyPassword As New frmModifyPassword '实例化一个新的修改密码的窗体 ' NewMDIModifyPassword.MdiParent = Me '定义父窗体为frmMain ' NewMDIModifyPassword.Show() '显示刚定义的窗体 frmModifyPassword.GetInstance.Show() End Sub
这个模式只要是照办书上的C#代码就OK了,但是需要注意的两点,
一.构造函数的写法:
PrivateSubNew()
'此调用是设计器所必需的。
InitializeComponent()
'在 InitializeComponent()调用之后添加任何初始化。
EndSub
二、判断子窗体是否实例化,或者被释放
<span style="font-family:KaiTi_GB2312;font-size:18px;">If mdfPWD IsNothingOrElsemdfPWD.IsDisposed Then</span>
下面是我写的代码:
If(mdfPWD Is Nothing) Or (mdfPWD.IsDisposed) Then怎么这样子就不对呢?分析一下自己的代码里有个逻辑错误,mdfPWD.IsDisposed是说这个类变量被处理了,而该处应该是未被处理掉。
对于“单例模式“自己的理解,如果用面向对象思想来说我记得在策略模式学习过程中有讲到把自己内部执行的操作封装起来,自己要怎么做、做了没有由自己来判断,外部代码负责调用,当把构造函数定义为private时,通过本类中的public方法调用,就很好的做到了这点,而正是用这个原理,在子窗体的调用上做到了很好的体现。
既然写到了MDI窗体,这样,那玩个新花样:
(1)窗体排序方式:
No1、
No2、
No3、
仅仅是多加了一个功能,就可以让容器中的子窗体按要求排序:
当同时打开了多个窗体的时候,可以选择排列顺序,很贴心的小功能。
(2)手动决定当前活动窗体
之前的VS例如2003里有MdiList属性,但是现在没有了,通过这个属性可以选择要成为获得焦点的窗体,通过上网查资料,只能通过代码写控件的方式来做了,这个功能实现后,当所有的子窗体在Minimized的情况下,就可以手动输入或者快捷键的方式来选择当前要成为活动窗体的窗体了,这个以后等到合作时候再研究吧,先挂起来。
PS:Visual Stadio的功能也是不断在进化的,就像上面所说的这个功能,RT:
所以,学会去写自己所要用到的控件往往比直接拖动去用可能更有意义。
Thatis all.