让WinForm打开一次的3个办法

原创 2006年06月20日 14:06:00

在开发实践中,我们有时会限制对某些窗体的操作行为,比如让用户只对某个窗体打开一次。对于这种行为,我们不能能对用户说“这个菜单项你只能点击一次,当窗口打开后就不能再点击它了”。作为有责任心的程序员们,都会想办法解决这个问题。

在处理这个问题上,我前后想出了两个办法,第一个办法实实在在地解决了问题;第二个办法将实现封装到了简单的接口中。

办法一:

 创建一个共享变量,将窗体当前的引用保存到里面,例子代码:

Public Class MyForm
             inherits System.Windows.Forms.Form
........
'声明为窗体的成员变量mRef
public shared mRef as System.Windows.Forms.Form

'在窗体的Load事件中,将窗体实例的引用保存到mRef中
mRef = Me

'在窗体的Closed事件中,将mRef置为Nothing
mRef = Nothing
...........

在打开这个窗体以前,做一些判断:
dim frm as MyForm
if IsNothing(MyForm.mRef) then
      frm = new MyForm
      frm.show()
      frm.BringToFront()
else
      frm.BringToFront()
end if
这样,就可以保证这个窗体只能被打开一次了。
在这里,起关键作用的是Shared类型的成员变量,它的生命周期同应用程序的生命周期一样,如果将其声明为private或者是protected,那它只能被该类的成员访问,如果把它声明为public,那它的作用就相当于全局变量了。在以上代码中,我们在窗体加载时窗体的实例引用保存到mRef中,在窗体关闭时被清空,那么很自然我们就可以在创建这个窗体的实例之前,通过mRef来判断窗体是否已经打开。

这种方法很简单,也很实用,就几行代码的事情,但是在现实的开发中,将这几行代码放到每个窗体中,和窗体中的那些复杂的业务逻辑处理代码放在一起,想起来心里有些不舒服,多一行代码就多了一点出错的可能性,所以,当我在我的第二个工程中遇到同样的问题时,我觉得我必须将这个功能封装起来,以后可以直接调用。

办法二:

我首先想到的是用一个函数来直接创建窗体,当这个窗体被创建后,将它的实例引用保存到一个静态列表中。
public Module Fm1
      public function Create() as Object
            static refList as ArrayList
            if isNothing(refList) then refList = New ArrayList
            ..........
      end function
End Module
但是这个想法很快就被证明是错误的,1:根本不知道要创建的窗体实例的类型;2:当创建的窗体被关闭后,如何才能将refList中保存的实例引用remove呢。

 后来我想,只让窗体创建一次,是对窗体进行全局管理的观念,那么是要建立一个全局变量来管理窗体吗?这无疑会带来麻烦,因为调用这会为了使用这个组件而引入新的全局变量。这时,我又一次想到了shared类型的变量,我只需要建立一个对这个窗体来说的全局变量,将这个变量声明为private shared即可以保证每个窗体都能够访问到它,又能够保证这个功能本身的封装。

我的第二个办法是创建一个窗体基类,将功能封装到这个窗体中,需要使用这个功能的窗体都从它继承。先考虑使用private shared 类型的成员变量来保存已经打开的窗体实例引用,然后考虑在创建窗体时,比较该窗体实例的引用是否已经存在,如果存在,那么将新创建的实例注销,返回先前已经打开的那个窗口实例。
具体代码:
Public Class FrmOpenOnce
             inherits System.Windows.Forms.Form

private shared mRefList as ArrayList = New ArrayList

'通过该方法来创建窗体
Public Shared Function Create(frm as FrmOpenOnce) as FrmOpenOnce
      If IsNothing(frm) then Throw New Exception("窗体没有被实例化")
     
      dim item as FrmOpenOnce
      For Each item in mRefList
             if item.gettype.tostring = frm.gettype.tostring then
                    frm.dispose()
                    return item
             end if
      End For

      '添加实例引用
      item = frm
      mRefList.Add(item)
      return item
End Function

Protected Overrides Sub OnClosed(ByVal e As System.EventArgs)
            Dim item As FrmOpenOnce
            Dim pos As Int32 = -1

            For Each item In mRefList
                pos += 1
                If Me.GetType.ToString = item.GetType.ToString Then
                    '发现了对相同窗体的引用
                    Exit For
                End If
            Next
            '删除该对象
            If pos > -1 Then mRefList.RemoveAt(pos)
end sub

现在,可以通过继承该窗体,来实现保证一个窗体只被打开一次的功能,例如:
Public class MyForm
      inherits FrmOpenOnce
     ....................

end sub

创建该窗体的方法:
dim frm as MyForm = MyForm.Create(New MyForm)
不管上面那句代码执行多少次,都只会打开一个窗体。

办法三:

上面那段代码有个地方让我越想越不爽,就是在判断之前,必须先创建这个窗体的实例,有没有直接通过窗体类型来判断的方法呢?我想起我在进行.net remoting编程的时候,使用过Activator来创建远程对象的实例,我想我应该也可以用这个类来创建本地对象的实例吧。看了一下.Net SDK 中有关Activator的帮助信息,才发现.Net框架真是做得很强大。下面我把我的最终版本贡献出来:
Public Class FrmOpenOnce
        Inherits System.Windows.Forms.Form

 Private Shared mRefList As ArrayList = New ArrayList

'通过类型的名称来创建,如果名称不正确,那么抛出异常
        'fileName:文件名称,frmType:对象类型,被创建的对象必须是该类的继承类的对象
        Public Shared Function Create(ByVal fileName As String, ByVal frmTypeName As String) As FrmOpenOnce
            Dim item As FrmOpenOnce

            For Each item In mRefList
                If item.GetType.ToString = frmTypeName Then
                    '发现了相同的窗体
                    Return item
                End If
            Next

            item = DirectCast(Activator.CreateInstanceFrom(fileName, frmTypeName).Unwrap, FrmOpenOnce)
            mRefList.Add(item)

            Return item

        End Function


        Protected Overrides Sub OnClosed(ByVal e As System.EventArgs)
            Dim item As FrmOpenOnce
            Dim pos As Int32 = -1

            For Each item In mRefList
                pos += 1
                If Me.GetType.ToString = item.GetType.ToString Then
                    '发现了对相同窗体的引用
                    Exit For
                End If
            Next
            '删除该对象
            If pos > -1 Then mRefList.RemoveAt(pos)
        End Sub
    End Class

 以上的方法通过类型名称来判断该窗体的实例是否已经创建,所以比前一方法要好。
其它朋友还有什么好的方法,还请赐教!

 

WCF简单实例--用Winform启动和引用

以订票为例简单应用wcf程序,需要的朋友可以参考下
  • kuui_chiu
  • kuui_chiu
  • 2014年06月04日 11:26
  • 2503

winform程序开机自启动设置方法总结

1.原理:需要开机自启动的程序,需要将其启动程序的路径写到注册表中指定的文件夹下 2. 写入注册表的方式有两种 a.在生成安装程序时配置 b.在程序运行时,动态配置。 方法一:在生成安...
  • liyc123youxiang
  • liyc123youxiang
  • 2015年05月20日 15:47
  • 4490

C# Winform同一子窗体只允许打开一次

最近在写一个小程序,遇到子窗口打开多次的情况,通过查找找到了解决办法,但是有写不尽人意,比如对子窗体最小化时的处理。 因此进行了优化得到如下代码,目前测试可能遇到的情况都完美解决,包括子窗体最小化: ...
  • kangkang621
  • kangkang621
  • 2015年11月05日 16:13
  • 893

C#.NET WINFORM应用程序中控制应用程序只启动一次

using System; using System.Threading; using System.Collections.Generic; using System.Windows.F...
  • u011696342
  • u011696342
  • 2014年09月03日 09:52
  • 320

winform开机自启动及 设置后不起作用的问题

开机自动启动,不起作用的情况记录
  • fyshk
  • fyshk
  • 2017年01月26日 14:18
  • 599

C#_WinForm接收命令行参数

首先,我要仔细的声明下,本文讲的是接受命令行参数,让程序启动。而不是启动那个黑黑的框。。。我要实现的效果和它么有关系 网上那些千篇一律,只管Ctrl+C,Ctrl+V,采集来的文章,本人已经深受...
  • lysc_forever
  • lysc_forever
  • 2014年08月03日 10:17
  • 3133

C#_启动多个窗体winform

启动多个窗体有很多方法,可以在Application.Run()中先实例化一个,然后在实例化出来的那个窗体的Onload,或者构造函数中实例化另一个窗体,这样在用户看来就是出现了两个窗体了。MSDN上...
  • pengjian444
  • pengjian444
  • 2016年02月15日 21:53
  • 895

WinForm载入窗体完成后自动执行事件

在Form1_Load之后自动执行事件 可以使用事件Form1_Activated或Form1_Shown 区别在于Form1_Activated先执行。Form1_Activated可能触发多次...
  • u012692537
  • u012692537
  • 2017年02月21日 23:39
  • 4365

C#客户端(WinForm)开机自动启动实现

1.原理:需要开机自启动的程序,需要将其启动程序的路径写到注册表中指定的文件夹下 2. 写入注册表的方式有两种 a.在生成安装程序时配置 b.在程序运行时,动态配置。 方法一:在生成安装程序时配置 ...
  • wangzl1163
  • wangzl1163
  • 2017年07月12日 20:15
  • 2014

Android引导界面---实现应用程序只启动一次引导界面

这篇文章算是对整个引导界面开发专题的一个终结了吧,个人觉得大部分的引导界面基本上都是千篇一律的,只要熟练掌握了一个,基本上也就没什么好说的了,要是在今后的开发中遇到了更好玩,更有趣的引导界面,博主也会...
  • zhangjikuan
  • zhangjikuan
  • 2014年09月18日 22:35
  • 750
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:让WinForm打开一次的3个办法
举报原因:
原因补充:

(最多只允许输入30个字)