分享在winform下实现左右布局多窗口界面-续篇

简介:

之前的这篇文章《分享在winform下实现左右布局多窗口界面》已经实现了左右布局多窗口界面,今天本来是研究基于winform的插件编程,没想到顺便又找到了另一种实现方案,这种实现方案更简单,要写的代码也很少,具体实现如下。

可视化设计部份:

1.父窗口:ParentForm的IsMdiContainer 设置为 true,即:this.IsMdiContainer=true;

2.在父窗口中添加一个顶部菜单:menuStrip1,并新增一个菜单项:Windows,且将menuStrip1的MdiWindowListItem设置为该Windows菜单对象,即: this.menuStrip1.MdiWindowListItem = this.windowsToolStripMenuItem;

3.在父窗口中添加一个树形菜单:treeView1,并将其Dock设为左靠齐,即:this.treeView1.Dock = System.Windows.Forms.DockStyle.Left;且将margin设为0;

4.在父窗口中添加一个Panel:panel1,且将其width设为3;

以下是设计后自动生成的代码:

编码部份:

其实上面的设计后,如果通过以下定义的方法打开一个子窗口,则直接实现了左右布局且包含多子窗口的界面。

1
2
3
4
5
6
7
8
private  void  ShowChildForm<TForm>()  where  TForm : Form,  new ()
{
     Form childForm =  new  TForm();
     childForm.MdiParent =  this ;
     childForm.Name =  "ChildForm - "  + DateTime.Now.Millisecond.ToString();
     childForm.Text = childForm.Name;
     childForm.Show();
}

当然仍然有不完美的地方,那就是左边菜单栏宽度不能动态调整,而又没有用到splitContainer,故我们只有自己来实现,其实也很简单,步骤如下: 

1.在父窗口构造函数中加入初始化panel1(用作分割器)位置及订阅相关事件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
public  ParentForm()
{
     InitializeComponent();
 
     panel1.MouseDown += panel1_MouseDown;
     panel1.MouseUp += panel1_MouseUp;
     panel1.MouseMove += panel1_MouseMove;
 
     panel1.Top = menuStrip1.Height;
     panel1.Left = treeView1.Left + treeView1.Width;
     panel1.Height = panel1.Parent.Height;
}

上述代码的作用是:1.保证panel1的高度与位置与左侧树形菜单控件相匹配;2.订阅的三个Mouse事件主要是为了后面实现移动panel1。

2.实现订阅的三个Mouse事件所对应的方法,分别为鼠标按下、鼠标移动、鼠标松开,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private  bool  startMove =  false //用于标记是否在移动中
 
         void  panel1_MouseMove( object  sender, MouseEventArgs e)
         {
             if  (startMove)
             {
                 panel1.Left += e.X;
             }
         }
 
         void  panel1_MouseUp( object  sender, MouseEventArgs e)
         {
             if  (startMove)
             {
                 panel1.Left += e.X;
                 startMove =  false ;
                 this .treeView1.Width = panel1.Left;
             }
         }
 
         void  panel1_MouseDown( object  sender, MouseEventArgs e)
         {
             startMove =  true ;
         }

上述代码作用:按下鼠标标记为开始移动,然后移动鼠标,若是标记移动中,说明是要移动panel1,故直接将鼠标当前的X坐标位置累加到panel1.Left属性上,从而实现移动,当鼠标弹起后,则将树形菜单的宽度设置为panel1.Left,从而实现树形菜单随panel1的移动而改变大小。

同时为了保证panel1的高度始终与树形菜单相同,在父窗口的Resize方法加入动态调整panel1的高度,代码如下:

1
2
3
4
private  void  ParentForm_Resize( object  sender, EventArgs e)
{
     panel1.Height = panel1.Parent.Height;
}

到此就完成了整个的实现方案,为了便于模拟在树形菜单中双击打开子窗口的效果,同时也添加了如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private  void  ParentForm_Load( object  sender, EventArgs e)
{
     LoadMenuNodes();
}
 
 
private  void  LoadMenuNodes()  //实现情况应该是从数据库及用户权限来进行动态创建菜单项
{
     this .treeView1.Nodes.Clear();
     var  root =  this .treeView1.Nodes.Add( "Root" );
     for  ( int  i = 1; i <= 10; i++)
     {
         var  section = root.Nodes.Add( "Section-"  + i);
         int  maxNodes =  new  Random(i).Next(1, 10);
         for  ( int  n = 1; n <= maxNodes; n++)
         {
             section.Nodes.Add( string .Format( "Level-{0}-{1}" , i, n));
         }
     }
}
 
 
private  void  treeView1_NodeMouseDoubleClick( object  sender, TreeNodeMouseClickEventArgs e)
{
     if  (e.Node.Nodes.Count <= 0) //当非父节点(即:实际的功能节点)
     {
         ShowChildForm<ChildForm>();
     }
}

上完整的实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
using  System;
using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Data;
using  System.Drawing;
using  System.Linq;
using  System.Text;
using  System.Threading.Tasks;
using  System.Windows.Forms;
 
namespace  WinFormTest
{
     public  partial  class  ParentForm : Form
     {
         private  bool  startMove =  false ;
 
         public  ParentForm()
         {
             InitializeComponent();
 
             panel1.MouseDown += panel1_MouseDown;
             panel1.MouseUp += panel1_MouseUp;
             panel1.MouseMove += panel1_MouseMove;
 
             panel1.Top = menuStrip1.Height;
             panel1.Left = treeView1.Left + treeView1.Width;
             panel1.Height = panel1.Parent.Height;
         }
 
         void  panel1_MouseMove( object  sender, MouseEventArgs e)
         {
             if  (startMove)
             {
                 panel1.Left += e.X;
             }
         }
 
         void  panel1_MouseUp( object  sender, MouseEventArgs e)
         {
             if  (startMove)
             {
                 panel1.Left += e.X;
                 startMove =  false ;
                 this .treeView1.Width = panel1.Left;
             }
         }
 
         void  panel1_MouseDown( object  sender, MouseEventArgs e)
         {
             startMove =  true ;
         }
 
         private  void  ParentForm_Load( object  sender, EventArgs e)
         {
             LoadMenuNodes();
         }
 
 
 
         private  void  treeView1_NodeMouseDoubleClick( object  sender, TreeNodeMouseClickEventArgs e)
         {
             if  (e.Node.Nodes.Count <= 0) //当非父节点(即:实际的功能节点)
             {
                 ShowChildForm<ChildForm>();
             }
         }
 
         private  void  ParentForm_Resize( object  sender, EventArgs e)
         {
             panel1.Height = panel1.Parent.Height;
         }
 
         private  void  LoadMenuNodes()  //实现情况应该是从数据库及用户权限来进行动态创建菜单项
         {
             this .treeView1.Nodes.Clear();
             var  root =  this .treeView1.Nodes.Add( "Root" );
             for  ( int  i = 1; i <= 10; i++)
             {
                 var  section = root.Nodes.Add( "Section-"  + i);
                 int  maxNodes =  new  Random(i).Next(1, 10);
                 for  ( int  n = 1; n <= maxNodes; n++)
                 {
                     section.Nodes.Add( string .Format( "Level-{0}-{1}" , i, n));
                 }
             }
         }
 
 
         private  void  ShowChildForm<TForm>()  where  TForm : Form,  new ()
         {
             Form childForm =  new  TForm();
             childForm.MdiParent =  this ;
             childForm.Name =  "ChildForm - "  + DateTime.Now.Millisecond.ToString();
             childForm.Text = childForm.Name;
             childForm.Show();
         }
     }
}

最终效果如下图示:

 

说明:我这里为了体现分割器,故将其背景色设为红色,便于大家观察,这种解决方案与之前的解决方案功能上是相同的,但有一点小小区别,之前的解决方案中子窗口的标题栏是在父窗口的容器内,而本文的解决方案中子窗口在最大化后,子窗口的标题栏会与父窗口合并,如下图示,至于大家用哪种依实际场景。

后续时间我会继续研究winform关于插件式编程(近期工作任务要求),到时候同样会分享给大家,也欢迎大家一起交流,当然高手可以无视。

本文转自 梦在旅途 博客园博客,原文链接:http://www.cnblogs.com/zuowj/p/5225814.html  ,如需转载请自行联系原作者

相关文章
|
4月前
|
开发者 编解码
界面适应奥秘:从自适应布局到图片管理,Xamarin响应式设计全解析
【8月更文挑战第31天】在 Xamarin 的世界里,构建灵活且适应性强的界面是每位开发者的必修课。本文将带您探索 Xamarin 的响应式设计技巧,包括自适应布局、设备服务协商和高效图片管理,帮助您的应用在各种设备上表现出色。通过 Grid 和 StackLayout 实现弹性空间分配,利用 Device 类检测设备类型以加载最优布局,以及使用 Image 控件自动选择合适图片资源,让您轻松应对不同屏幕尺寸的挑战。掌握这些技巧,让您的应用在多变的市场中持续领先。
45 0
|
4月前
|
开发框架 前端开发 搜索推荐
在WInform开发中实现工具栏/菜单的动态呈现
在WInform开发中实现工具栏/菜单的动态呈现
C#编写WinForm窗体应用程序(第四期)
在 C# 语言中 RadioButton 是单选按钮控件,多个 RadioButton 控件可以为一组,这一组内的 RadioButton 控件只能有一个被选中。
C#编写WinForm窗体应用程序(第四期)
|
Web App开发 搜索推荐 C#
用WPF窗体打造个性化界面的图片浏览器
原文:用WPF窗体打造个性化界面的图片浏览器 本文使用WPF窗体(XAML及C#)与Win Form控件(FolderBrowserDialog)结合的方式, 演示制作了一个简易漂亮的WPF图片浏览器。
834 0
|
供应链 数据可视化 UED
|
数据安全/隐私保护
UWP开发入门(九)——简单界面的布局技巧及屏幕适应
原文:UWP开发入门(九)——简单界面的布局技巧及屏幕适应   嘿嘿嘿,题目比较绕哈。本篇主要讨论一般情况下,页面的布局技巧,怎么将元素的展现尽量做到分辨率无关。基本的思路仍然是尽量少的标定具体的数字,而是用比列来标注各元素占据的空间。
1417 0