服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - 在winform下实现左右布局多窗口界面的方法之续篇

在winform下实现左右布局多窗口界面的方法之续篇

2021-11-14 13:37梦在旅途 C#

这篇文章主要介绍了在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
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
99
100
namespace winformtest
{
partial class parentform
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private system.componentmodel.icontainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void dispose(bool disposing)
{
if (disposing && (components != null))
{
components.dispose();
}
base.dispose(disposing);
}
#region windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void initializecomponent()
{
this.menustrip1 = new system.windows.forms.menustrip();
this.windowstoolstripmenuitem = new system.windows.forms.toolstripmenuitem();
this.treeview1 = new system.windows.forms.treeview();
this.panel1 = new system.windows.forms.panel();
this.menustrip1.suspendlayout();
this.suspendlayout();
//
// menustrip1
//
this.menustrip1.items.addrange(new system.windows.forms.toolstripitem[] {
this.windowstoolstripmenuitem});
this.menustrip1.location = new system.drawing.point(0, 0);
this.menustrip1.mdiwindowlistitem = this.windowstoolstripmenuitem;
this.menustrip1.name = "menustrip1";
this.menustrip1.size = new system.drawing.size(684, 25);
this.menustrip1.tabindex = 0;
this.menustrip1.text = "menustrip1";
//
// windowstoolstripmenuitem
//
this.windowstoolstripmenuitem.name = "windowstoolstripmenuitem";
this.windowstoolstripmenuitem.size = new system.drawing.size(73, 21);
this.windowstoolstripmenuitem.text = "windows";
//
// treeview1
//
this.treeview1.dock = system.windows.forms.dockstyle.left;
this.treeview1.location = new system.drawing.point(0, 25);
this.treeview1.margin = new system.windows.forms.padding(0);
this.treeview1.name = "treeview1";
this.treeview1.size = new system.drawing.size(228, 380);
this.treeview1.tabindex = 3;
this.treeview1.nodemousedoubleclick += new system.windows.forms.treenodemouseclickeventhandler(this.treeview1_nodemousedoubleclick);
//
// panel1
//
this.panel1.anchor = ((system.windows.forms.anchorstyles)(((system.windows.forms.anchorstyles.top | system.windows.forms.anchorstyles.bottom)
| system.windows.forms.anchorstyles.left)));
this.panel1.backcolor = system.drawing.color.red;
this.panel1.borderstyle = system.windows.forms.borderstyle.fixedsingle;
this.panel1.cursor = system.windows.forms.cursors.vsplit;
this.panel1.location = new system.drawing.point(230, 28);
this.panel1.margin = new system.windows.forms.padding(0);
this.panel1.name = "panel1";
this.panel1.size = new system.drawing.size(3, 100);
this.panel1.tabindex = 5;
//
// form1
//
this.autoscaledimensions = new system.drawing.sizef(6f, 12f);
this.autoscalemode = system.windows.forms.autoscalemode.font;
this.clientsize = new system.drawing.size(684, 405);
this.controls.add(this.panel1);
this.controls.add(this.treeview1);
this.controls.add(this.menustrip1);
this.ismdicontainer = true;
this.mainmenustrip = this.menustrip1;
this.name = "form1";
this.text = "form1";
this.load += new system.eventhandler(this.form1_load);
this.resize += new system.eventhandler(this.form1_resize);
this.menustrip1.resumelayout(false);
this.menustrip1.performlayout();
this.resumelayout(false);
this.performlayout();
}
#endregion
private system.windows.forms.menustrip menustrip1;
private system.windows.forms.toolstripmenuitem windowstoolstripmenuitem;
private system.windows.forms.treeview treeview1;
private system.windows.forms.panel panel1;
}
}

编码部份:

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

?
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
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
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
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
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下实现左右布局多窗口界面的方法之续篇

在winform下实现左右布局多窗口界面的方法之续篇

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

在winform下实现左右布局多窗口界面的方法之续篇

关于在winform下实现左右布局多窗口界面的方法之续篇的相关知识就给大家介绍到这里,后续时间我会继续研究winform关于插件式编程(近期工作任务要求),到时候同样会分享给大家,也欢迎大家一起交流,当然高手可以无视。

延伸 · 阅读

精彩推荐
  • C#浅谈C# winForm 窗体闪烁的问题

    浅谈C# winForm 窗体闪烁的问题

    下面小编就为大家带来一篇浅谈C# winForm 窗体闪烁的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C#教程网7962021-12-21
  • C#c#学习之30分钟学会XAML

    c#学习之30分钟学会XAML

    一个界面程序的核心,无疑就是界面和后台代码,而xaml就是微软为构建应用程序界面而创建的一种描述性语言,也就是说,这东西是搞界面的...

    C#教程网8812021-12-10
  • C#C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    这篇文章主要介绍了C#实现的文件操作封装类,结合完整实例形式分析了C#封装文件的删除,移动,复制,重命名等操作相关实现技巧,需要的朋友可以参考下...

    Rising_Sun3892021-12-28
  • C#C#直线的最小二乘法线性回归运算实例

    C#直线的最小二乘法线性回归运算实例

    这篇文章主要介绍了C#直线的最小二乘法线性回归运算方法,实例分析了给定一组点,用最小二乘法进行线性回归运算的实现技巧,具有一定参考借鉴价值,需要...

    北风其凉8912021-10-18
  • C#聊一聊C#接口问题 新手速来围观

    聊一聊C#接口问题 新手速来围观

    聊一聊C#接口问题,新手速来围观,一个通俗易懂的例子帮助大家更好的理解C#接口问题,感兴趣的小伙伴们可以参考一下...

    zenkey7072021-12-03
  • C#C# 后台处理图片的几种方法

    C# 后台处理图片的几种方法

    本篇文章主要介绍了C# 后台处理图片的几种方法,非常具有实用价值,需要的朋友可以参考下。...

    IT小伙儿10162021-12-08
  • C#C#基础之泛型

    C#基础之泛型

    泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能。接下来通过本文给大家介绍c#基础之泛型,感兴趣的朋友一起学习吧...

    方小白7732021-12-03
  • C#Unity3D UGUI实现缩放循环拖动卡牌展示效果

    Unity3D UGUI实现缩放循环拖动卡牌展示效果

    这篇文章主要为大家详细介绍了Unity3D UGUI实现缩放循环拖动展示卡牌效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参...

    诗远3662022-03-11