我们在做机房重构的时候一直存在这样的一个误区,就是单例模式,当我们希望有一个主窗体,其他的窗体可以在主窗体中显示,也就是MDI窗体做主窗体,其他调用的窗体做子窗体。我拿充值窗体为例。
第一种方法
代码如下
’单击菜单事件
Private Sub MenuCharge_Click(sender As Object, e As EventArgs) Handles MenuCharge.Click
Dim NewMDIRecharge As New frmRecharge '实例化一个新的充值的窗体 NewMDIRecharge为自定符号可以更改的
NewMDIRecharge.MdiParent = Me '定义父窗体为frmMain(主窗体)
NewMDIRecharge.Show() '显示刚定义的窗体
End Sub
上面的代码就完成了,父子窗体的设定。效果如下:
每次单击都会出现一个充值窗体是不是很不友好,这个时候就是单例模式出场的时候了。
第二种方法
下面的单例模式,写咋子窗体的代码中,写到类里就好了。同样就是充值窗体对应的代码class中。
''' <summary>
''' 单例模式下面三个方法
''' </summary>
Private Shared UIfrom As Form '定义的自变量UIfrom (也可以是具体的窗体)
Public Sub New() '这东西我真的是没有明白知道的可以分享一下
' 此调用是设计器所必需的。
InitializeComponent() '在 InitializeComponent() 调用之后添加任何初始化。
End Sub
Public Shared Function getInstance(ByVal transmitform As Form) '这是一个判断窗体是否实例化一次的方法 transmitform传递子窗体名字(自己理解的)
If UIfrom Is Nothing OrElse UIfrom.IsDisposed Then '实例化条件
UIfrom = transmitform
UIfrom.MdiParent = FrmAdminMian '定义父窗体为frmMain(主窗体)
End If
Return UIfrom
End Function
主窗体的菜单单击事件中写下面的代码
’单击菜单事件
Private Sub MenuCharge_Click(sender As Object, e As EventArgs) Handles MenuCharge.Click
frmRecharge.getInstance(frmRecharge).Show() '调用充值窗体中的单例模式,这时就不会单击一次出现一个窗体了。
End Sub
上面的代码有一个小的Bug。如下图:
问题就是,子窗体出现在了父窗体内,但是还出现在了父窗体控件的下面,尴尬了。
第三种方法
解决方案如下。
'写在主窗体的代码中就好了。
Declare Function SetParent Lib "user32" Alias "SetParent" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Long
’单击菜单事件
Private Sub MenuCharge_Click(sender As Object, e As EventArgs) Handles MenuCharge.Click
Me.IsMdiContainer = True '设置主窗体为父窗体。IsMdiContainer是窗体的一个属性,MDI窗体。和VB有点区别。 这个属性也可以在窗体中设置,就不用多次写了。
SetParent(frmRecharge.Handle, Me.Handle) '定义父窗体为frmMain(主窗体)
frmRecharge.Show()
End Sub
'Me 是主窗体也就是FrmMain窗体,frmRecharge是子窗体,也就是充值窗体
总结
在其他的一些博客中会用到单例模式但是就会出现上面,子窗体出现在父窗体控件的下面的情况,很多的博客中用了这样一句代码, 下面简写不写全面了就。
Declare Function SetParent Lib "user32" Alias "SetParent" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Long
SetParent(frmRecharge.Handle, Me.Handle)
实际上填上这句代码就相当有了第三种方法,单例模式完全就没有起到应该有的作用。