您好,欢迎访问三七文档
1李德奇主编第二十五讲MDI窗体设计大连理工大学出版社2教学目标理解MDI窗体的概念掌握MDI主窗体的设计方法掌握判别MDI子窗体实例存在性的方法掌握MDI父窗体和子窗体菜单合并的处理方法掌握MDI子窗体在父窗体中排列方式的控制方法完成MDI窗体实例的程序编写3教学内容一、MDI窗体的特性二、MDI窗体的设计过程三、MDI窗体的菜单处理四、MDI窗体的显示控制4MDI窗体设计C#允许在单个容器窗体中创建包含多个子窗体的多文档界面(MDI)。多文档界面的典型例子是MicrosoftOffice中的Word和Excel,在那里允许用户同时打开多个文档,每个文档占用一个窗体,用户可以在不同的窗体间切换,处理不同的文档。5一、MDI窗体的特性在项目中使用MDI窗体时,通常将一个MDI容器窗体作为父窗体,父窗体可以将多个子窗体包容在它的工作区之中。MDI父窗体与其子窗体之间表现出如下的特性:MDI的容器窗体(父窗体)必须且只能有一个,它只能当容器使用,其客户区用于显示子窗体,客户区不能接受键盘和鼠标事件。不要在容器窗体的客户区加入控件,否则那些控件会显示在子窗体中。容器窗体的框架区可以有菜单、工具栏和状态栏等控件。子窗体可以有多个,各个子窗体不必相同。子窗体被显示在容器窗体的客户区之中,子窗体不可能被移出容器窗体的客户区之外。子窗体被最小化后,其图标在容器窗体的底部,而不是在任务栏中。容器窗体被最小化后,子窗体随同容器窗体一起被最小化在任务栏中。容器窗体被还原后,子窗体随同容器窗体一起还原,并保持最小化之前的状况。子窗体可以单独关闭,但若关闭容器窗体,子窗体随同容器窗体一起被关闭。子窗体可以有菜单,但子窗体显示后,其菜单被显示在容器窗体上。6二、MDI窗体的设计过程(1/2)1、MDI容器窗体只要将窗体的IsMdiContainer属性设置为true,它就是容器窗体。为此在窗体的Load事件中加入以下语句就是。this.IsMdiContainer=true;容器窗体在显示后,其客户区是凹下的,等待子窗体显示在下凹区。不要在容器窗体的客户区设计任何控件。7二、MDI窗体的设计过程(2/2)2、MDI子窗体MDI子窗体就是一般的窗体,其上可以设计任何控件,此前设计过的任何窗体都可以作为MDI子窗体。只要将某个窗体实例的MdiParent属性设置到一个MDI父窗体,它就是那个父窗体的子窗体,语法为:窗体实例名.MdiParent=父窗体对象;例如,下一段代码编写在一个MDI父窗体的某个事件处理程序中,创建一个子窗体实例formChild1并将其显示在MDI父窗体的客户区中:FormChildformChild1=newFormChild();formChild1.MdiParent=this;formChild1.Show();其中窗体类FormChild是一个一般的普通窗体。8三、MDI窗体的菜单处理(1/2)可以分别为MDI父窗体和子窗体设计菜单。父窗体显示时,会显示自己的菜单。当子窗体显示在MDI父窗体中时,会将当前活动的子窗体的菜单显示在父窗体上,子窗体的菜单项与父窗体的菜单项合并共同组成MDI父窗体的菜单。在默认的情况下,子窗体的菜单被排列的父窗体的菜单后面。通过设置各个菜单项的MergeOrder属性和MergeType属性,可以控制父窗体菜单与子窗体菜单合并组成的新菜单的顺序和菜单的组合方式。MergeOrder属性菜单项的MergeOrder属性决定菜单项被组合到新菜单中的排列位置,这个属性值是一个整型数。所有菜单项的MergeOrder值不必连续,只需要能区分出大小就行。9三、MDI窗体的菜单处理(2/2)MergeType属性菜单项的MergeType属性决定菜单项被组合到新菜单中的组合形式,这个属性值是MenuMerge类型的枚举量,这些枚举量的含义如下表。菜单项的MenuMerge枚举枚举值含义Add菜单项被添加到新菜单之中。Replace菜单项替换合并菜单中相同位置的现有菜单项。MergeItems该菜单项的所有子菜单项与合并菜单中相同位置的现有菜单项的子菜单项进行合并。Remove菜单项被从合并菜单中移除。若要在父窗体上仅显示当前活动的子窗体的菜单,需要将父窗体的Menu属性指定到这个子窗体的主菜单。例如在父窗体中有这样的语句:this.Menu=formChild1.Menu;this是父窗体,formChild1是当前活动的子窗体。这样当子窗体formChild1活动时,父窗体上显示的是子窗体formChild1的菜单,而父窗体自己的菜单却不显示。10四、MDI窗体的显示控制(1/4)1、在MDI父窗体中显示子窗体通常将MDI父窗体作为项目的主窗体,用户登陆后这个窗体就被启动。在MDI父窗体中显示子窗体的方法很简单,创建任何一个窗体的实例,指定本窗体为它的父窗体,就可以将这个实例显示在MDI父窗体中。例如在MDI父窗体中的第一个菜单项单击代码中将本窗体设置为子窗体实例formChild1的父窗体。privatevoidmenuItem1_Click(objectsender,System.EventArgse){FormChild1formChild1=newFormChild1();formChild1.MdiParent=this;formChild1.Show();}11四、MDI窗体的显示控制(2/4)上述menuItem1_Click事件处理程序代码能够创建子窗体的实例并显示在MDI父窗体中。倘若用户不断地单击该菜单项,将不断有同类新的子窗体实例被创建并显示,形成重复的子窗体实例在父窗体内堆积,浪费系统资源,造成数据冲突。为了在MDI父窗体中检测某子窗体实例是否已经存在,定义一个ExistsMdiChildrenInstance()方法来实现。在该方法中,利用MdiChildren.Name来核对从参数传入的子窗体类型,若存在该子窗体的实例,激活它并返回true;若不存在,返回false。程序代码如下。pivateboolExistsMdiChildrenInstance(stringMdiChildrenClassName){//遍历每一个MDI子窗体实例foreach(FormchildFrminthis.MdiChildren){//若子窗体的类型与实参相同,则存在该类的实例if(childFrm.Name==MdiChildrenClassName){//若该窗体实例被最小化了if(childFrm.WindowState==FormWindowState.Minimized){//最大化这个实例childFrm.WindowState=FormWindowState.Maximized;}//激活该窗体实例childFrm.Activate();returntrue;}}returnfalse;}12四、MDI窗体的显示控制(3/4)有了这个方法,每当在MDI父窗体创建一个子窗体实例之前,先调用这个方法来检测该类子窗体实例的存在性。倘若已存在这个实例,激活它使之占据前台,并返回一个true;若不存在这个实例,返回一个false。调用者根据这个返回值来确定是否需要创建这个子窗体的实例。回过头来修改menuItem1_Click事件处理程序代码如下,子窗体重复堆积的问题就可迎刃而解。privatevoidmenuItem1_Click(objectsender,System.EventArgse){//若不存在FormModiInfo窗体的实例if(!ExistsMdiChildrenInstance(FormChild1)){FormChild1formChild1=newFormChild1();formChild1.MdiParent=this;formChild1.Show();}}13四、MDI窗体的显示控制(4/4)2、子窗体在MDI父窗体中的排列在默认的情况下,MDI多个子窗体显示后被层叠排列在父窗体的工作区中,子窗体的菜单按照各菜单项的MergeOrder属性和MergeType属性设置被合并到父窗体的菜单中。当子窗体被最大化后,其标题栏也被合并到父窗体中,标题文本Text被接在父窗体的标题文本之后,并被放在一对[]之中,窗体控制框被放置在父窗体的菜单栏中。父窗体的LayoutMdi方法可以改变子窗体在MDI父窗体中的排列方式,该方法的参数是一个MdiLayout类型的枚举值,通过这些枚举值来指定子窗体以何种形式排列在父窗体的工作区之中。MdiLayout类型的枚举值如下表。MdiLayout类型的枚举值枚举值含义ArrangeIcons所有的子窗体均排列在MDI父窗体工作区之中。Cascade所有的子窗体均层叠在MDI父窗体工作区之中。TileHorizontal所有的子窗体均水平平铺在MDI父窗体工作区之中。TileVertical所有的子窗体均垂直平铺在MDI父窗体工作区之中。例如在MDI父窗体中有语句this.LayoutMdi(MdiLayout.TileHorizontal);,该窗体中的所有子窗体将被水平平铺在它的工作区中。
本文标题:C#-MDI窗体
链接地址:https://www.777doc.com/doc-4709775 .html