Visual C#是微軟公司推出的下一代主流程序開發語言,他也是一種功能十分強大的程
序設計語言,正在受到越來越多的編程人員的喜歡。在Visual C#中,提供了為實現MDI程序設計的很多功能。本文就是通過一個具體的例子來詳細的介紹在Visual C#中的MDI編程。
一程序設計及運行的環境:
(1)視窗2000服務器版
(2).Net FrameWork SDK Beta 2版
二程序設計的思路、主要步驟和實現方法:
MDI編程主要就是要在主窗體中能夠新建一個MDI窗體,並且能夠對主窗體中的所有MDI窗體實現層疊、水平平鋪和垂直平鋪。雖然這些操作比較基本,但卻是程序設計中的要點和重點。本文就按照上述功能的順序來一一介紹。
(1)首先要設定主窗體是一個MDI窗體的容器,因為只有如此才能夠在此主窗體上面添加MDI窗體,從而實現對MDI編程,具體實現語句如下:
public Form1() { InitializeComponent(); this.IsMdiContainer = true; }
我是直接把this.IsMdiContainer = true ;寫在窗體的構造函數中,你也可以寫的form_load函數中。
(2)在主窗體上面新建一個MDI窗體。在程序中,新建一個MDI窗體的命令是通過一個菜單的事件來實現的。在處理新建一個MDI窗體事件中,關鍵是要設定此MDI窗體的父窗體。其實MDI窗體和別的窗體沒有什么不同,不同點就在MDI窗體有上一級窗體,即父窗體,而其他窗體是沒有的,具體實現語句如下:
private void New_Click ( object sender , EventArgs e )//這是一個菜單的事件 { Form frmTemp = new Form ( ) ; //新建一個窗體 frmTemp.MdiParent = this ; //定義此窗體的父窗體,從而此窗體成為一個MDI窗體 frmTemp.Text = "窗體0" + FormCount.ToString ( ) ; //設定MDI窗體的標題 FormCount++ ; frmTemp.Show ( ) ; //把此MDI窗體顯示出來 }
(3)實現對MDI窗體的層疊:
對於在主窗體中實現對MDI窗體的層疊操作,在主程序中,是通過一個方法來實現的,這個方法就是LayoutMdi,他所帶的參數是MdiLayout.Cascade,具體實現語句如下:
private void Cascade_Click ( object sender , EventArgs e ) //實現對主窗體中的MDI窗體的層疊操作 { this.LayoutMdi ( MdiLayout.Cascade ) ; }
實現操作后具體如下圖:

圖01:在主窗體中實現對MDI窗體的層疊操作,點擊小圖放大
(4)實現對MDI窗體的水平平鋪:
要在主窗體實現MDI窗體水平平鋪,也是通過LayoutMdi方法,此時所帶的參數是MdiLayout.TileHorizontal,具體實現語句如下:
this.LayoutMdi ( MdiLayout.TileHorizontal ) ;

圖02:在主窗體中實現對MDI窗體的水平平鋪操作,點擊小圖放大
(5)實現對MDI窗體的垂直平鋪:
要在主窗體實現MDI窗體垂直平鋪,也是通過LayoutMdi方法,此時所帶的參數是MdiLayout.TileVertical,具體實現語句如下:
this.LayoutMdi ( MdiLayout.TileVertical ) ;//實現對主窗體中的MDI窗體的垂直平鋪操作

(6)在有些MDI程序,當新建一個MDI窗體以后,往往會在某些菜單項的下面生產一個以此MDI窗體的名稱為名稱的子菜單項。在其他語言中要實現這種功能,可能就要在某些主菜單項下動態的加入子菜單了。但是在Visual C#中實現此種功能,就顯得比較簡單的,只有在要加入的主菜單項下加入下面一句程序就可以了:
WindowMenu.MdiList = true ;本程序中,是在"窗口"主菜單項下面加入MDI窗體的子菜單項的。加入此語句后,程序運行界面具體如下圖:

三.程序源代碼(mdi.cs)及編譯方法:
通過對程序設計中的難點介紹以后,就可以比較容易得到實現對上述MDI窗體處理的源程序代碼(mdi.cs),具體如下:
mdi.cs源程序代碼:
using System ; using System.Windows.Forms ; using System.ComponentModel ; using System.Drawing ; //導入在程序中用到的名稱空間 class MDIDemo : Form { private static int FormCount = 1 ; //定義此常量是為了統計MDI窗體數目, MainMenu mnuMain = new MainMenu ( ) ; MenuItem FileMenu ; MenuItem NewMenu ; MenuItem ExitMenu ; MenuItem WindowMenu ; public MDIDemo ( ) { this.IsMdiContainer = true ; this.Text = "MDI演示程序" ; FileMenu = new MenuItem ( ) ; FileMenu.Text = "文件" ; WindowMenu = new MenuItem ( ) ; WindowMenu.Text = "窗口(&W)" ; WindowMenu.MenuItems.Add ( "窗體層疊(&C)" , new EventHandler ( Cascade_Click ) ) ; WindowMenu.MenuItems.Add ( "水平平鋪(&H)" , new EventHandler ( TileH_Click ) ) ; WindowMenu.MenuItems.Add ( "垂直平鋪(&V)" , new EventHandler ( TileV_Click ) ) ; WindowMenu.MdiList = true ; //這一句比較重要,有了這一句就可以實現在新建一個MDI窗體后會在此主菜單項下顯示存在的MDI窗體菜單項 NewMenu = new MenuItem ( ) ; NewMenu.Text = "新建窗體(&N)" ; NewMenu.Click += new EventHandler ( New_Click ) ; ExitMenu = new MenuItem ( ) ; ExitMenu.Text = "退出(&X)" ; ExitMenu.Click += new EventHandler ( Exit_Click ) ; FileMenu.MenuItems.Add ( NewMenu ) ; FileMenu.MenuItems.Add ( new MenuItem ( "-" ) ) ; FileMenu.MenuItems.Add ( ExitMenu ) ; mnuMain.MenuItems.Add ( FileMenu ) ; mnuMain.MenuItems.Add ( WindowMenu ) ; this.Menu = mnuMain ; } private void Cascade_Click ( object sender , EventArgs e ) //實現對主窗體中的MDI窗體的層疊操作 { this.LayoutMdi ( MdiLayout.Cascade ) ; } private void TileH_Click ( object sender , EventArgs e ) //實現對主窗體中的MDI窗體的水平平鋪操作 { this.LayoutMdi ( MdiLayout.TileHorizontal ) ; } private void TileV_Click ( object sender , EventArgs e ) //實現對主窗體中的MDI窗體的垂直平鋪操作 { this.LayoutMdi ( MdiLayout.TileVertical ) ; } private void New_Click ( object sender , EventArgs e ) { Form frmTemp = new Form ( ) ; //新建一個窗體 frmTemp.MdiParent = this ; //定義此窗體的父窗體,從而此窗體成為一個MDI窗體 frmTemp.Text = "窗體0" + FormCount.ToString ( ) ; //設定MDI窗體的標題 FormCount++ ; frmTemp.Show ( ) ; //把此MDI窗體顯示出來 } private void Exit_Click ( object sender , EventArgs e ) { this.Dispose ( ); Application.Exit ( ) ; } public static void Main ( ) { Application.Run ( new MDIDemo ( ) ) ; } }
再經過以下編譯命令編譯過以后,就可以得到執行程序:
csc /t:winexe /r:system.dll /r:system.windows.forms.dll /r:system.drawing.dll mdi.cs
四.總結:
本文主要是介紹如何用Visual C#來實現對MDI窗體的編程。即:新建MDI窗體、MDI窗體層疊、MDI窗體水平平鋪、MDI窗體的垂直平鋪。通過上述介紹,可見,在Visual C#中處理MDI還是相當比較簡單的。
不過說實現在我不建議大家這樣實現了,而是喜歡使用Tabcontrol的方法,這樣容易控件,而且可以達到多任務,多操作的效果,也是目前幾乎所有瀏覽器都采用的方法
MDI窗體容器 - 放窗體的容器
窗體是頂級控件,是不允許放到其他的控件或窗體中的 (李獻策lxc)
窗體屬性中有一個屬性:IsMdiContainer - 確定該窗體是否是MDI容器
在窗體中放一個頂部菜單
點擊<銷售>按鈕會在窗體中彈出一個新的窗體
//銷售 private void 銷售ToolStripMenuItem_Click(object sender, EventArgs e) { Form5 f5 = new Form5(); f5.MdiParent = this; f5.Show(); }
內部窗體可以在父級窗體里任意移動
問題一:打開新的窗體全屏(李獻策lxc)
//銷售 private void 銷售ToolStripMenuItem_Click(object sender, EventArgs e) { Form5 f5 = new Form5(); //窗體最大化 f5.WindowState = FormWindowState.Maximized; f5.MdiParent = this; f5.Show(); }
問題二:打開后有最小化、最大化等按鈕
錯誤方法一:去掉最大化最小化按鈕——失敗
//銷售 private void 銷售ToolStripMenuItem_Click(object sender, EventArgs e) { Form5 f5 = new Form5(); //窗體最大化 f5.WindowState = FormWindowState.Maximized; //去掉最大化最小化按鈕 f5.MaximizeBox = false; f5.MinimizeBox = false; f5.MdiParent = this; f5.Show(); }
錯誤方法二:去掉邊框——失敗(李獻策lxc)
//銷售 private void 銷售ToolStripMenuItem_Click(object sender, EventArgs e) { Form5 f5 = new Form5(); //窗體最大化 f5.WindowState = FormWindowState.Maximized; //去掉邊框 f5.FormBorderStyle = FormBorderStyle.None; f5.MdiParent = this; f5.Show(); }
正確方法:先用一個panel填充窗體剩余部分,在panel中打開新窗體
//銷售 private void 銷售ToolStripMenuItem_Click(object sender, EventArgs e) { Form5 f5 = new Form5(); //窗體最大化 f5.WindowState = FormWindowState.Maximized; //去掉邊框 f5.FormBorderStyle = FormBorderStyle.None; f5.MdiParent = this; //設置新窗體的Parent f5.Parent = panel1; f5.Show(); }
問題三:在即將打開的新窗體中放入一個button1,Anchor設置為Bottom,Right,當打開新窗體並拖動窗體邊框時,按鈕並未鎖定與底部和右側的距離
panel是跟隨窗體的變化而變化,但是新窗體是不隨panel變化而變化的
解決方法:設置主窗體的size發生改變時新窗體同時改變size(李獻策lxc)
//Size改變時的事件 private void Form3_SizeChanged(object sender, EventArgs e) { //遍歷panel中的控件, foreach (var v in panel1.Controls) { //如果是新窗體 if (v is Form5) { //新窗體先變為正常大小 (v as Form5).WindowState = FormWindowState.Normal; //新窗體再變為最大化以適應新的Size (v as Form5).WindowState = FormWindowState.Maximized; } } }
問題四:在點擊<倉庫>按鈕時,會在主窗體中打開一個新的窗體,再點擊<銷售>按鈕會切回銷售窗體,但實際是又創建了一個新的銷售窗體而已,並非原來打開的窗體
解決辦法:唯一窗體(李獻策lxc)
==========================================================
權限設置 - 不同的權限登入時顯示內容不同
新建一個登入窗體
數據庫中添加一個新的權限表
1、首先設置父級Form1界面,只需要將該界面的IsMdiContainer屬性設置為true;
2、設置按鈕的事件來打開子級的窗口Form2,Form3等等;
3、在From1內設置一個容器panel,范圍為需要打開的子級界面的大小;
4、設置Form2、Form3的事件,以及唯一窗口等;
//Form2的點擊事件 private void form2ToolStripMenuItem_Click(object sender, EventArgs e) { Form2 f2 = new Form2(); f2.Name = "f2"; openwidow(f2); } //Form3的點擊件 private void form3ToolStripMenuItem_Click(object sender, EventArgs e) { Form3 f3 = new Form3(); f3.Name = "f3"; openwidow(f3); } //設置唯一窗口: //新建一個formlist集合,供唯一窗口使用 List<Form> formlist = new List<Form>(); //新建一個public的方法 private void openwidow(Form f) { //定義一個Form fff變量 Form fff = null; //定義一個bool類型的變量為false; bool open = false; //遍歷這個集合 foreach (Form ff in listfrom) { //只要遍歷到就隱藏 ff.Hide(); //如果遍歷到f.name if (ff.Name == f.Name) { open = true; //把ff放到集合內 fff = ff; } } //如果遍歷到f.name, if (open) { //關閉所有窗口 f.Close(); //重新打開這個串口 fff.Show(); } //否則 else { //設置打開的窗口為Form1的子窗體; f.MdiParent = this; //設置子窗口的大小為最大化; f.WindowState = FormWindowState.Maximized; //把子窗口放到Form1的panel1里; f.Parent = panel1; //設置無邊框 f.FormBorderStyle = FormBorderStyle.None; //打開窗口 f.Show(); //把這個窗口放到集合內 fromlist.Add(f); } }