首页 > 代码库 > 2015.12.14 MDI(多文档窗口结构)设置基本解决,折腾一天,部分解决存在已久的问题。但效果仍不如临时航线的MDI窗体结构。

2015.12.14 MDI(多文档窗口结构)设置基本解决,折腾一天,部分解决存在已久的问题。但效果仍不如临时航线的MDI窗体结构。

创建从一个窗口弹出多个子窗口的结构叫MDI窗体结构

如果不按MDI结构管理,最简单的做法是:

在窗体A上添加菜单或按钮,在菜单或按钮事件中添加弹出B窗体代码:

B b = new B();

b.show()

这样A与B没有任何关系,有多少个弹出窗口任务栏上就有多少个图标,父窗口最小化时其余窗口没有任何变化。这样比较凌乱。

但好处是弹出窗口的位置和大小与父窗口没有约束关系,弹出窗口可以在父窗口之外显示。

 

稍改进的方法(可能是比下方改进MDI还好的方法)

B b = new B();

b.show(this) //加上this后标明b窗口属于A窗体this,这样A最小化时所有子窗口也会最小化,最小化后任务栏上只有一个图标。且所有子窗口始终在父窗口的前端,不会被其遮挡。但任务栏上还是会有所有子窗口的图标。

 

要用传统的MDI子窗口处理如下

1、父窗口的isMdiContainer属性设为true(可通过界面设)

2、菜单或按钮事件的子窗口弹出代码写为:

B b = new B();

b. MdiParent = this; //this代表父窗口

b.WindowState = FormWindowState.Maximized;//

b.show()

注意:重要缺陷:可能是VS的bug,所有子窗体都只能在父窗体控件下方显示,如果父窗体上有一个picturebox的图片背景,则所有弹出窗口都会被图片盖住,就像没弹出一样。(折腾我近1个小时才发现)。

3种解决方法:

1、将背景图片设成主窗口的背景,而不用picturebox但这样会产生闪烁,不好看

2、弹出任意子窗口后将picturebox隐藏。

3、用API函数代替b. MdiParent = this。写成API.SetParent(b.Handle,pictureBox1.Handle); 注意:是将子窗体的父窗体设为picturebox而不是A!这对传统MDI窗体来说已经比较完美了,但是如果用了下面的优化MDI效果就不好,只能用方法2

这样就完成了传统MDI窗体的设置,

这样做缺点与优点一样明显。

优点是:所有窗体在任务栏上只有一个图标,所有子窗体最小化后都罗列在父窗体底部(显示最大化、最小化等三个按钮)、所有子窗体都随父窗口一起最消失出现。

缺点只有1个,但很致命:子窗体不能挪出父窗体。对大显示器或多显示器非常不方便。

改进方法:主要解决子窗体无法挪出父窗口的。

思路:子窗体默认最大化,充满父窗口客户区,但点击恢复正常尺寸显示时,退出MDI子窗口模式,使其脱离父窗口尺寸限制,成为独立窗口。

方法:上述MDI设置后,在弹出每个窗体中增加Wndproc回调函数,处理还原显示事件以及最大、最小化事件

在子窗口函数中定义:

        const int WM_SYSCOMMAND = 0X112;//274

        const int SC_MAXIMIZE = 0XF030;//61488

        const int SC_MINIMIZE = 0XF020;//61472

        const int SC_RESTORE = 0XF120; //61728

        const int SC_CLOSE = 0XF060;//61536       

        protected override void WndProc(ref Message m)

        {

            if (m.Msg == WM_SYSCOMMAND)

            {

                if (m.WParam.ToInt32() == SC_RESTORE) //处理窗体还原事件,将子窗口父窗体设为原父窗口的父窗口,即桌面

                {

                    this.MdiParent = MF.mf.MdiParent;

                    this.WindowState = FormWindowState.Normal;

                    System.Drawing.Rectangle rect = SystemInformation.WorkingArea;//获取屏幕工作尺寸

                    this.Height = rect.Height * 3 / 4;

                    this.Width = rect.Width * 3 / 4;

                    this.CenterToParent();

                }

                if (m.WParam.ToInt32() == SC_MAXIMIZE) //处理窗体最大化最小化事件,还原成MDI模式,同时还要写上最大化、最小化

                {

                    this.MdiParent = MF.mf;

                    this.WindowState = FormWindowState.Maximized;

                }

                if (m.WParam.ToInt32() == SC_MINIMIZE)

                {

                    this.MdiParent = MF.mf;

                    this.WindowState = FormWindowState.Minimized;

                }

            }

            base.WndProc(ref m);

        }

2015.12.14 MDI(多文档窗口结构)设置基本解决,折腾一天,部分解决存在已久的问题。但效果仍不如临时航线的MDI窗体结构。