实现目标:
1、在主窗体上有菜单栏和状态栏,菜单栏的按钮可以随意打开子窗体,如果子窗体已经打开就激活,
2、子窗体打开后在主窗体的状态栏动态生成按钮,该按钮可激活相应的子窗体,子窗体关闭后,该按钮消失,状态栏功能类似windows的任务栏;
3、主窗体启动时自动打开一个子窗体,并同样在状态栏生成一个按钮,这个子窗体有按钮若干,这些按钮实现与主窗体的菜单栏的按钮一样的功能;
项目文件说明
父窗体容器 :Form1
子窗体: console.cs + form_m1.cs + form_m2.cs
基类窗体:menu.cs
关系:form_m1.cs + form_m2.cs继承自menu.cs
menu代码
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace 子窗口打开其他子窗口并在父窗口新建按钮 12 { 13 public partial class menu : Form 14 { 15 public menu() 16 { 17 InitializeComponent(); 18 } 19 public delegate void FormMain_button(string name); 20 public event FormMain_button Button_event; 21 public event FormMain_button Button_event_Dispose; 22 23 public void load_display() 24 { 25 Button_event(Name); 26 // MessageBox.Show(Name); 27 } 28 public void close_dispose() 29 { 30 Button_event_Dispose(Name); 31 } 32 33 34 35 } 36 }
form_m1.cs代码
其中Form1.text = this.Text;是在子窗体启动时给父窗体的方法传参,让父窗体的状态栏生成的按钮的名字和这个子窗体显示的名字相同。
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace 子窗口打开其他子窗口并在父窗口新建按钮 12 { 13 public partial class form_m1 : menu 14 { 15 public form_m1() 16 { 17 InitializeComponent(); 18 } 19 protected override void OnShown(EventArgs e) 20 { 21 Form1.text = this.Text; 22 base.load_display(); 23 } 24 protected override void OnClosed(EventArgs e) 25 { 26 //base.OnClosed(e); 27 28 base.close_dispose(); 29 } 30 } 31 }
form_m2.cs代码与form_m1.cs代码类似,不赘
1、在主窗体上有菜单栏和状态栏,菜单栏的按钮可以随意打开子窗体,如果子窗体已经打开就激活,
2、子窗体打开后在主窗体的状态栏动态生成按钮,该按钮可激活相应的子窗体,子窗体关闭后,该按钮消失,状态栏功能类似windows的任务栏;
先实现功能1和功能2
Form1.cs代码
解释:
15 行的 static public string text;给按钮命名用,在子窗口赋值;
16-27 产生按钮的方法 ①
用label做了一个按钮,这个按钮的名字是子窗口传递的和子窗体相同,后面需要使用按钮的名字来定位子窗口,显示的文字是子窗口给的,文字可以在子窗口任意指定;
生成的这个按钮有四条边,如24行。带了一个一个事件,如第25行
32-39 生成的按钮的事件 ,首先找一下是哪个按钮触发了这个事件,并获得这个按钮的名字,按钮的名字就是子窗体的名字,
所以可以在Application.OpenForms里面寻找这个名字的子窗体,找到后激活,并让这个窗体显示默认大小;这个窗体一定能找到吗?需不需要做异常检测呢?
这个按钮是伴随子窗体OnShow事件创建的,子窗体消失OnClose,则按钮消失,所以理论上不需要做异常检测。这个问题留着以后考虑吧,现在是2019-03-11 23:14:33
28-31 让按钮消失的方法②
给一个名字,让这个名字的按钮从状态栏消失
42-46 加载Form1的窗体,并让这个窗体成为MDI
48-66 传入继承自menu的窗体的实例并传入一个名字,传入名字是为了检查这个窗体有没有被打开,如果打开了就激活,我很多地方都用名字来定位窗体,好用!
Form test = Application.OpenForms[name];找找看有没有这个名字的窗体
f.Button_event += new menu.FormMain_button(button_form1);
f.Button_event_Dispose += new menu.FormMain_button(mess);监控一下有没有发生这两个事件,并分别调用产生按钮和释放按钮的方法
68-79 这几行,应该不会在某天不知道是啥意思吧,如果这都能忘了,那我应该老早没干这行了,实在不行了,只要还记得复制到编译器里面就行
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace 子窗口打开其他子窗口并在父窗口新建按钮 12 { 13 public partial class Form1 : Form 14 { 15 static public string text; 16 private System.Windows.Forms.ToolStripStatusLabel Lab; 17 public void button_form1(string name) 18 { 19 this.Lab = new System.Windows.Forms.ToolStripStatusLabel(); 20 this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] 21 {this.Lab}); 22 this.Lab.Name = name; 23 this.Lab.Text = text; 24 this.Lab.BorderSides = ToolStripStatusLabelBorderSides.All; 25 this.statusStrip1.Items[name].Click += Form1_Click; 26 27 } 28 public void mess(string name) 29 { 30 this.statusStrip1.Items[name].Dispose(); 31 } 32 private void Form1_Click(object sender, EventArgs e) 33 { 34 //throw new NotImplementedException(); 35 string for_name = ((System.Windows.Forms.ToolStripStatusLabel)sender).Name; 36 Form test = Application.OpenForms[for_name]; 37 test.Activate(); 38 test.WindowState = FormWindowState.Normal; 39 } 40 41 42 public Form1() 43 { 44 InitializeComponent(); 45 this.IsMdiContainer = true; 46 } 47 48 public void openform_menu(menu f, string name) 49 { 50 Form test = Application.OpenForms[name]; 51 f.MdiParent = this; 52 53 if (test == null/* || test.IsDisposed*/) 54 { 55 56 f.WindowState = FormWindowState.Maximized; 57 f.Button_event += new menu.FormMain_button(button_form1); 58 f.Button_event_Dispose += new menu.FormMain_button(mess); 59 f.Show(); 60 61 } 62 else 63 { 64 test.Activate(); 65 } 66 } 67 68 private void toolStripButton1_Click(object sender, EventArgs e) 69 { 70 form_m1 f1 = new form_m1(); 71 string name = f1.Name; 72 openform_menu(f1,name); 73 } 74 75 private void toolStripButton2_Click(object sender, EventArgs e) 76 { 77 form_m2 f2 = new form_m2(); 78 string name = f2.Name; 79 openform_menu(f2, name); 80 } 81 } 82 }
好了,前两个功能完成 弄俩图片看下效果
3、主窗体启动时自动打开一个子窗体,并同样在状态栏生成一个按钮,这个子窗体有按钮若干,这些按钮实现与主窗体的菜单栏的按钮一样的功能;
这个功能有些麻烦,不过也只是把上面的东西复制粘贴了一遍
好吧,开启搬砖模式
分析 ①自动打开的这个子窗体要生成一个按钮,所以就要调用父窗体下的生成和释放功能,要想调用这俩功能就要用到menu中的那几行委托和事件声明代码,复制
②要想窗体创建时生成按钮,窗体关闭时释放按钮,那么form_m1中的 OnShown和OnClosed也必不可少,复制
这个子窗体的按钮的功能与主窗体的功能一样,这又该咋办呢,我想想。。。。。。。。。。嗯。。。子窗口的按钮触发的事件等于父窗口的按钮的事件,这个功能还真有些蛋疼。
那么就继续复制,
③复制Form1中的48-66行 记得将 f.MdiParent = this;改为 f.MdiParent = Form1 窗体 然后复制两个按钮的代码
好吧,看看复制好后的完整代码
19-21 复制代码,这里更改了下事件的名字,便于理解后面的代码
25行 给按钮起了个名字(text值)
29-40 窗体创建和关闭的事件触发了委托声明的事件
42-58 的重点在于
f.Button_event += new menu.FormMain_button(Button_event_console);
f.Button_event_Dispose += new menu.FormMain_button(Button_event_Dispose_console);
这两行代码有点难以理解,但是仔细看下,就会发现,是把这两个事件做了关联。还好我更改了事件的名字
60-72 同样的传参调用
console.cs代码
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace 子窗口打开其他子窗口并在父窗口新建按钮 12 { 13 public partial class console : Form 14 { 15 public console() 16 { 17 InitializeComponent(); 18 } 19 public delegate void FormMain_button(string name); 20 public event FormMain_button Button_event_console; 21 public event FormMain_button Button_event_Dispose_console; 22 23 public void load_display() 24 { 25 Form1.text = "控制台"; 26 Button_event_console(Name); 27 28 } 29 public void close_dispose() 30 { 31 Button_event_Dispose_console(Name); 32 } 33 protected override void OnShown(EventArgs e) 34 { 35 load_display(); 36 } 37 protected override void OnClosed(EventArgs e) 38 { 39 close_dispose(); 40 } 41 42 public void openform_menu(menu f, string name) 43 { 44 Form test = Application.OpenForms[name]; 45 f.MdiParent = Form1.ActiveForm; 46 47 if (test == null/* || test.IsDisposed*/) 48 { 49 f.WindowState = FormWindowState.Maximized; 50 f.Button_event += new menu.FormMain_button(Button_event_console); 51 f.Button_event_Dispose += new menu.FormMain_button(Button_event_Dispose_console); 52 f.Show(); 53 } 54 else 55 { 56 test.Activate(); 57 } 58 } 59 60 private void button1_Click(object sender, EventArgs e) 61 { 62 form_m1 f1 = new form_m1(); 63 string name = f1.Name; 64 openform_menu(f1, name); 65 } 66 67 private void button2_Click(object sender, EventArgs e) 68 { 69 form_m2 f2 = new form_m2(); 70 string name = f2.Name; 71 openform_menu(f2, name); 72 } 73 } 74 }
在Form1窗体中为新的子窗体添加代码
1-4 在Form1启动时调用这个方法
9-10 子窗体console的两个事件订阅了Form1的两个方法,并将这两个方法给console下的两个委托调用
1 protected override void OnShown(EventArgs e) 2 { 3 console_f(); 4 } 5 6 private void console_f() 7 { 8 console console_from = new console(); 9 console_from.Button_event_console += new console.FormMain_button(button_form1); 10 console_from.Button_event_Dispose_console += new console.FormMain_button (mess); 11 string name = console_from.Name; 12 console_from.MdiParent = this; 13 console_from.Show(); 14 }
所以整个Form1.cs的代码
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace 子窗口打开其他子窗口并在父窗口新建按钮 12 { 13 public partial class Form1 : Form 14 { 15 static public string text; 16 private System.Windows.Forms.ToolStripStatusLabel Lab; 17 public void button_form1(string name) 18 { 19 this.Lab = new System.Windows.Forms.ToolStripStatusLabel(); 20 this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] 21 {this.Lab}); 22 this.Lab.Name = name; 23 this.Lab.Text = text; 24 this.Lab.BorderSides = ToolStripStatusLabelBorderSides.All; 25 this.statusStrip1.Items[name].Click += Form1_Click; 26 27 } 28 public void mess(string name) 29 { 30 this.statusStrip1.Items[name].Dispose(); 31 } 32 private void Form1_Click(object sender, EventArgs e) 33 { 34 //throw new NotImplementedException(); 35 string for_name = ((System.Windows.Forms.ToolStripStatusLabel)sender).Name; 36 Form test = Application.OpenForms[for_name]; 37 test.Activate(); 38 test.WindowState = FormWindowState.Normal; 39 } 40 41 42 public Form1() 43 { 44 InitializeComponent(); 45 this.IsMdiContainer = true; 46 } 47 48 public void openform_menu(menu f, string name) 49 { 50 Form test = Application.OpenForms[name]; 51 f.MdiParent = this; 52 53 if (test == null/* || test.IsDisposed*/) 54 { 55 56 f.WindowState = FormWindowState.Maximized; 57 f.Button_event += new menu.FormMain_button(button_form1); 58 f.Button_event_Dispose += new menu.FormMain_button(mess); 59 f.Show(); 60 61 } 62 else 63 { 64 test.Activate(); 65 } 66 } 67 68 private void toolStripButton1_Click(object sender, EventArgs e) 69 { 70 form_m1 f1 = new form_m1(); 71 string name = f1.Name; 72 openform_menu(f1,name); 73 } 74 75 private void toolStripButton2_Click(object sender, EventArgs e) 76 { 77 form_m2 f2 = new form_m2(); 78 string name = f2.Name; 79 openform_menu(f2, name); 80 } 81 82 protected override void OnShown(EventArgs e) 83 { 84 console_f(); 85 } 86 87 private void console_f() 88 { 89 console console_from = new console(); 90 console_from.Button_event_console += new console.FormMain_button(button_form1); 91 console_from.Button_event_Dispose_console += new console.FormMain_button (mess); 92 string name = console_from.Name; 93 console_from.MdiParent = this; 94 console_from.Show(); 95 } 96 97 98 } 99 }
效果
正式投入使用时还需稍作修改
该内容来源于我正制作的一个小系统,一个小小的想法,给实现了下