单例模式——解决MDI子窗体实例化的问题

机房收费系统进行有一段时间了,但是始终有些历史遗留问题。比如,如何MDI子窗体如何显示在上层的问题和MDI子窗体实例化的问题。

对于如何显示在上层的问题,这次采用的还是SetParent函数,在模块里面添加:

<span style="font-size:18px;"><span style="font-size:18px;"> '定义一个用来设置子窗体的函数
    Declare Function SetParent Lib "user32" Alias "SetParent" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long</span></span>

接着,要解决的就是子窗体实例化的问题,然后查过一些方法之后,选择了单例模式。回过头去查自己当初学设计模式时的代码:

<span style="font-size:18px;"> <span style="font-size:18px;">public partial class FormToolbox : Form
    {
        private static FormToolbox ftb = null; //声明一个静态的类变量

        private  FormToolbox()  //将构造放改成私有的,外部代码不能直接new来实例化它
        {
            InitializeComponent();
        }

        private void FormToolbox_Load(object sender, EventArgs e)
        {

        }

        //得到类实例的方法,返回值就是本类对象,注意,此方法也是静态方法
        public static FormToolbox GetInstance()
        {

            if (ftb == null || ftb.IsDisposed)
            {
                ftb = new FormToolbox();
                ftb.MdiParent = Form1.ActiveForm;
            }
            return ftb;

        }

    }</span></span>

大的方针制定好之后,开始动手写。。

动手的时候,才会发现,学习的时候做的DEMON其实总是非常理想化的东西,实际中面临的问题往往更复杂。

复习了下设计模式之后,然后就开始写自己的VB.NET版本的了,为了解决窗体不美观的问题,这次还是加了容器空间,load的时候平铺窗体。

但是,每次子窗体弹出来,总是会闪一下,然后消失,再点击按钮,让子窗体弹出来,这下才会变正常。就像《超级破坏王》中的云妮洛普一样,

看起来就是程序中的BUG.  之后单步监视了很久,发现,调用setparent的时候,子窗体因为被前置,就会出现在主窗体的前面,但是在setparent之后,还是有了某某.Show()方法,这就造成了一个矛盾,setparent刚将窗体置前,show方法又将窗体隐藏在主窗体和控件的夹层里面了,╮(╯▽╰)╭  矛盾啊。改完这个之后,解决了闪现的问题。

还有单例的问题:

<span style="font-size:18px;"><span style="font-size:18px;">If IsNothing(checkBalance) Or checkBalance.IsDisposed Then '如果没有实例化</span></span>

但是,每次运行到这里的时候就会出错:“未将对象的引用设置到对象的实例的问题”

细想下,刚刚声明的对象,根本没有new,在这行这句话的时候,IsNothing值为true,然后它会接着调用IsDisposed,这时就会出现问题,因为checkBalance根本就是Nothing嘛~这时想起了以前学习C#的时候学到的一个逻辑短路的问题:C语言的“逻辑短路”

利用逻辑短路,可以很好的解决“未将对象的引用设置到对象的实例的问题”。

so,只需查查VB.NET的逻辑运算符,然后我找到了OrElse。。。

代码如下:

<span style="font-size:18px;">#Region "单例模式:用来判断本窗体是否已经实例化"

    Private Shared checkBalance As frmCheckBalance = Nothing  '定义一个静态的类变量

    Private Sub New()

        ' 此调用是 Windows 窗体设计器所必需的。
        InitializeComponent()

        ' 在 InitializeComponent() 调用之后添加任何初始化。
    End Sub

    Public Shared Sub GetInstance() ' As frmCheckBalance '用来出现实例

        If IsNothing(checkBalance) OrElse checkBalance.IsDisposed Then '如果没有实例化
            '注意:1,要判断窗体是否已被实例化和窗体是否被销毁过(当关闭一个窗体时,资源被释放,但是并不是nothing)
            '     2,orelse产生了逻辑短路的问题,如果这里用Or会产生错误,因为可能会引用不存在的对象。

            checkBalance = New frmCheckBalance '实例化checkbanlance
        End If

        checkBalance.MdiParent = frmMain '设置父窗体
        checkBalance.Show()     '显示窗体出来,但是此时子窗体还是被隐藏在下层的,必须要通过SetParent将它拿到上层来
        SetParent(checkBalance.Handle.ToInt64, frmMain.Handle.ToInt64)  '设置窗体置前

        'Return checkBalance '返回
    End Sub

#End Region</span>

上面对单例模式有所改动,但是不影响单例模式的灵魂。

在主窗体里,只需调用sub 过程就好。

<span style="font-size:18px;"> Private Sub checkBalanceMenu_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles checkBalanceMenu.Click

        frmCheckBalance.GetInstance()

    End Sub</span>

PS:代码里面还是一点点BUG,正在修改中,希望路过的高手们指点一二~

单例模式——解决MDI子窗体实例化的问题

时间: 2024-10-05 05:06:12

单例模式——解决MDI子窗体实例化的问题的相关文章

VB.NET章鱼哥出品—如何解决MDI子窗体被父窗体中的控件覆盖的问题

最近有个网友问我这个问题,我就上网搜了下,结果很失望,有几个在CSDN上发的求助帖,看到最后都没有找到明确的答案.这里笔者在网上找到了API函数SetParent(),并对网上的错误进行了修改,并给出了简单实例代码.读者可自行测试: Public Class Form1 '作者:章鱼哥,QQ:3107073263 群:309816713 '如有疑问或好的建议请联系我,大家一起进步 '声明SetParent函数,这是一个API函数 Declare Function SetParent Lib "u

C#解决MDI子窗体切换闪屏的方法

解决方法: 在主窗体任意位置添加以下代码: protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= 0x02000000; return cp; } }

解决WinForm(C#)中MDI子窗体最大化的问题

“用MDI方式打开一个子窗口体后,总是不能最大化显示,明明子窗口体的WindowState设置为Maximized?”,相信有很多人会遇到这的样问题,请按下面的方法设置即可使MDI子窗体最大化: 1.把父窗体的IsMdiContainer设置为True:2.把子窗体的WindowState设置为Normal:3.在父窗体中用下面的方法打开子窗体:private void menuItemsMdiForm_Click(object sender, EventArgs e){     MyChild

解决WinForm(C#)中MDI子窗体最大化跑偏的问题

“用MDI方式打开一个子窗口体后,总是不能最大化显示,明明子窗口体的WindowState设置为Maximized?”,相信有很多人会遇到这的样问题,请按下面的方法设置即可使MDI子窗体最大化: 1.把父窗体的IsMdiContainer设置为True:2.把子窗体的WindowState设置为Normal:3.在父窗体中用下面的方法打开子窗体:private void menuItemsMdiForm_Click(object sender, EventArgs e){     MyChild

WinForm排列MDI子窗体

如果一个MDI窗体中有多个子窗体同时打开,假如不对其排列顺序进行调整,那么界面会非常的混乱,而且不容易浏览.那么如何解决这个问题呢?我们可以通过使用带有MdiLayout枚举的LayoutMdi方法来排列多文档界面父窗体中的子窗体.语法:public void LayoutMdi (MdiLayout value)value:是MdiLayout枚举值之一,用来定义MDI子窗体的布局.MdiLayout枚举用于指定MDI父窗体中子窗体的布局.语法:public enum MdiLayoutMdi

在DLL动态链接库中封装VCL的MDI子窗体

在DLL动态链接库中封装VCL的MDI子窗体不多说了,看代码就应该明白了,曾经我遇到的问题,现在放出来大家共享! 这里是工程文件的部分: 在DLL中封装MDI子窗体需要重写DLL入口函数,具体代码如下: var DllApp: TApplication;//定义保存原DLL的TApplication对象 DllScr: TScreen;//定义保存原DLL的TScreen对象 procedure UnProcDll(Reason: Integer); register;//重新定义DLL入口函数

Delphi中实现MDI子窗体(转)

Delphi中实现MDI子窗体 用MDI实现浏览子窗口,具有窗口管理功能,同屏观看多个网页的内容  ① 多文档窗体(MDI) MDI窗体是一种具有主子结构的窗体体系,微软的Word便是其中的一个典型例子.MDI体系中至少需要两种窗体,只能将其中之一设置为主窗体,其余窗体全部则全部为子窗体,主窗体负责子窗体的管理.切换等工作.自然,子窗体上承载的内容可各不相同.Tidy浏览器最终实现了三种不同的窗体:主窗体.浏览子窗体.源代码子窗体.  ② 设置窗体类型  我们通过窗体的FormStyle属性设置

WinForm MDi子窗体最大化导致子窗体标题栏和主窗体菜单栏合并问题的解决方法

在主窗体菜单栏的ItemAdded事件中编写如下代码: *msMain是我的主窗体菜单栏的Name属性值 //子窗体最大化不显示图标 private void msMain_ItemAdded(object sender, ToolStripItemEventArgs e) { if (e.Item.Text.Length == 0) { e.Item.Visible = false; } else { e.Item.Visible = true; } } 说明: 打开的子窗体最大化的时候,菜单

C# 设置MDI子窗体只能弹出一个的方法

Windows程序设计中的MDI(Multiple Document Interface)官方解释就是所谓的多文档界面,与此对应就有单文档界面 (SDI), 它是微软公司从Windows 2.0下的Microsoft Excel电子表格程序开始引入的,Excel电子表格用户有时需要同时操作多份表格,MDI正好为这种操作多表格提供了很大的方便,于是就产生了MDI程序. 新建一个WindowForm程序.得到一个窗体作为我们父窗体Parent.拖入一个menustrip空间.在新建一个窗体FrmCh