首页 - 技术 - 分享winform下左右布局多窗口界面的实现 - 续集

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

2023-10-04 07:39
-->

上一篇文章《分享在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;并将边距设置为0;

4。在父窗口中添加一个Panel:panel1,并将其宽度设置为3;

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

命名空间 WinFormTest
{
部分类 ParentForm
{
///
/// 必需的设计器变量。
///

私有 System.ComponentModel.IContainer 组件 = null; ///
/// 清理所有正在使用的资源。
///

/// 如果应释放托管资源,则为 true;否则为假。
protected override void Dispose(bool dispose)
{
if (处理 && (组件!= null))
{
组件.Dispose();
}
base.Dispose(处置);
} #region Windows 窗体设计器生成的代码 ///
/// 设计器支持必需的方法 - 不支持
/// 使用代码编辑器修改该方法的内容。
///

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();
//
// 菜单条1
//
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;
www.gsm-guard.net = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(684, 25);
this.menuStrip1.TabIndex = 0;
this.menuStrip1.Text = "menuStrip1";
//
// windowsToolStripMenuItem
//
www.gsm-guard.net = "windowsToolStripMenuItem";
this.windowsToolStripMenuItem.Size = new System.Drawing.Size(73, 21);
this.windowsToolStripMenuItem.Text = "Windows";
//
// 树视图1
//
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);
www.gsm-guard.net = "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); //
// 面板1
//
this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((www.gsm-guard.net | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.panel1.BackColor = www.gsm-guard.net;
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);
www.gsm-guard.net = "panel1";
this.panel1.Size = new System.Drawing.Size(3, 100);
this.panel1.TabIndex = 5; //
// 表格1
//
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;
www.gsm-guard.net = "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 私有 System.Windows.Forms.MenuStrip menuStrip1;
私有 System.Windows.Forms.ToolStripMenuItem windowsToolStripMenuItem;
私有System.Windows.Forms.TreeView treeView1;
私有System.Windows.Forms.Panel面板1;
}
}

编码部分:

其实经过上面的设计,如果通过下面定义的方法打开一个子窗口,就直接实现了一个左右布局、多个子窗口的界面。

private void ShowChildForm() 其中 TForm : 表单,new()
{
表单childForm = new TForm();
childForm.MdiParent = this;
www.gsm-guard.net = "ChildForm - " + DateTime.Now.Millisecond.ToString();
childForm.Text = www.gsm-guard.net;
www.gsm-guard.net();
}

当然还有不完善的地方,就是左侧菜单栏的宽度不能动态调整,也没有使用splitContainer,所以得自己实现。其实很简单。步骤如下: 

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

公共家长表格()
{
初始化组件(); panel1.MouseDown += panel1_MouseDown;
panel1.MouseUp += panel1_MouseUp;
panel1.MouseMove += panel1_MouseMove; www.gsm-guard.net = menuStrip1.Height;
panel1.Left = treeView1.Left + treeView1.Width;
panel1.Height = panel1.Parent.Height;
}

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

2。实现订阅的三个Mouse事件对应的方法,即鼠标按下、鼠标移动、鼠标释放。代码如下:

私有布尔startMove = false; //用于标记是否在移动 void panel1_MouseMove(对象发送者, MouseEventArgs e)
{
if (开始移动)
{
panel1.Left += e.X;
}
} void panel1_MouseUp(对象发送者, MouseEventArgs e)
{
if (开始移动)
{
panel1.Left += e.X;
startMove = false;
this.treeView1.Width = panel1.Left;
}
} void panel1_MouseDown(对象发送者, MouseEventArgs e)
{
startMove = true;
}

以上代码的功能:按下鼠标标记开始移动,然后移动鼠标。如果该标记是移动的,则说明要移动panel1,所以直接将鼠标当前的X坐标位置添加到panel1.Left属性中,实现移动。 ,当鼠标弹出时,树形菜单的宽度被设置为panel1.Left,这样树形菜单就会随着panel1的移动而改变大小。

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

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

至此,整个实施计划就完成了。为了模拟树形菜单中双击打开子窗口的效果,还添加了以下代码:

private void ParentForm_Load(对象发送者, EventArgs e)
{
LoadMenuNodes();
} private void LoadMenuNodes() //实现应该是从数据库和用户权限动态创建菜单项
{
this.treeView1.Nodes.Clear();
var root = this.treeView1.Nodes.Add("Root");
for (int i = 1; i <= 10; i++)
{
varsection = 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(对象发送者, TreeNodeMouseClickEventArgs e)
{
if (e.Node.Nodes.Count <= 0)//当非父节点(即:实际功能节点)
{
ShowChildForm();
}
}

附上完整的实现代码:

使用系统;
使用 System.Collections.Generic;
使用 System.ComponentModel;
使用系统数据;
使用 System.Drawing;
使用 System.Linq;
使用 System.Text;
使用 System.Threading.Tasks;
使用 System.Windows.Forms; 命名空间 WinFormTest
{
公共部分类 ParentForm : Form
{
私有布尔startMove = false; 公共家长表格()
{
初始化组件(); panel1.MouseDown += panel1_MouseDown;
panel1.MouseUp += panel1_MouseUp;
panel1.MouseMove += panel1_MouseMove; www.gsm-guard.net = menuStrip1.Height;
panel1.Left = treeView1.Left + treeView1.Width;
panel1.Height = panel1.Parent.Height;
} void panel1_MouseMove(对象发送者, MouseEventArgs e)
{
if (开始移动)
{
panel1.Left += e.X;
}
} void panel1_MouseUp(对象发送者, MouseEventArgs e)
{
if (开始移动)
{
panel1.Left += e.X;
startMove = false;
this.treeView1.Width = panel1.Left;
}
} void panel1_MouseDown(对象发送者, MouseEventArgs e)
{
startMove = true;
} private void ParentForm_Load(对象发送者, EventArgs e)
{
LoadMenuNodes();
}private void treeView1_NodeMouseDoubleClick(对象发送者, TreeNodeMouseClickEventArgs e)
{
if (e.Node.Nodes.Count <= 0)//当非父节点(即:实际功能节点)
{
ShowChildForm();
}
} 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++)
{
varsection = 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 : 表单,new()
{
表单childForm = new TForm();
childForm.MdiParent = this;
www.gsm-guard.net = "ChildForm - " + DateTime.Now.Millisecond.ToString();
childForm.Text = www.gsm-guard.net;
www.gsm-guard.net();
}
}
}

最终效果如下图:

注:这里为了体现分隔线,我将其背景色设置为红色,方便大家观察。该解决方案在功能上与之前的解决方案相同,但存在细微差别。之前的解决方案 在该解决方案中,子窗口的标题栏位于父窗口的容器内。在本文的解决方案中,子窗口最大化后,子窗口的标题栏会与父窗口合并,如下图所示。使用哪一种取决于实际情况。场景。

以后会继续研究winform的插件编程(近期工作任务要求)。到时候我也会分享给大家。欢迎大家与我交流。当然,专家可以忽略它。

-->