在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;

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

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;
}
}

编码部份:

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

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(用作分割器)位置及订阅相关事件,代码如下:

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事件所对应的方法,分别为鼠标按下、鼠标移动、鼠标松开,代码如下:

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的高度,代码如下:

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

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

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>();
}
}

附上完整的实现代码:

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关于插件式编程(近期工作任务要求),到时候同样会分享给大家,也欢迎大家一起交流,当然高手可以无视。

(0)

相关推荐

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

    在web页面上我们可以通过frameset,iframe嵌套框架很容易实现各种导航+内容的布局界面,而在winform.WPF中实现其实也很容易,我这里就分享一个:在winform下实现左右布局多窗口界面. 我这里说的多窗口是指一个父窗口包含多个子窗口,在winform中实现这种效果很简单,即将某个窗口的IsMdiContainer设为true,然后将其它子窗口的MdiParent设为其父窗口对象即可,这样就完成了一个多窗口界面,效果如下: 点击NEW新打开一个窗口,其效果如下: 请看我上图红色

  • winform 使用Anchor属性进行界面布局的方法详解

    每个控件的定位方法: 一.使用Anchor: Anchor分为Left.Top.Right.Bottom四个属性. 它们的含义如下: Top--表示控件中与父窗体(或父控件)相关的顶部应该保持固定. Bottom--表示控件中与父窗体(或父控件)相关的底边应该保持固定. Left--表示控件中与父窗体(或父控件)相关的左边缘应该保持固定. Right--表示控件中与父窗体(或父控件)相关的右边缘应该保持固定. 一般控件默认为Left | Top,定位根据为左上方的边界.控件的Anchor为:To

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

    在上篇文章在winform下实现左右布局多窗口界面的方法已经实现了左右布局多窗口界面,今天本来是研究基于winform的插件编程,没想到顺便又找到了另一种实现方案,这种实现方案更简单,要写的代码也很少,具体实现如下. 可视化设计部份: 1.父窗口:ParentForm的IsMdiContainer 设置为 true,即:this.IsMdiContainer=true; 2.在父窗口中添加一个顶部菜单:menuStrip1,并新增一个菜单项:Windows,且将menuStrip1的MdiWin

  • C# winform实现右下角弹出窗口结果的方法

    本文实例讲述了C# winform实现右下角弹出窗口结果的方法.分享给大家供大家参考,具体如下: using System.Runtime.InteropServices; [DllImport("user32")] private static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags); //下面是可用的常量,按照不合的动画结果声明本身须要的 private const int AW_HOR_POS

  • python在windows下创建隐藏窗口子进程的方法

    本文实例讲述了python在windows下创建隐藏窗口子进程的方法.分享给大家供大家参考.具体实现方法如下: import subprocess IS_WIN32 = 'win32' in str(sys.platform).lower() def subprocess_call(*args, **kwargs): #also works for Popen. #It creates a new *hidden* window, #so it will work in frozen apps

  • C# Winform中实现主窗口打开登录窗口关闭的方法

    在使用C#进行Winform编程时,我们经常需要使用一个登录框来进行登录,一旦输入的用户名密码登录成功,这时登录窗口应该关闭,而且同时打开主程序窗口.该如何来实现呢? 乍一想,很简单啊,打开主窗口就用主窗口的Show()方法,而关闭登录窗口就用登录窗口的Close()方法即可.即代码如下: Program.cs中代码: 复制代码 代码如下: Application.Run(new FormLogin()); 登录窗口(FormLogin)代码: 复制代码 代码如下: private void b

  • C#实现Winform鼠标拖动窗口大小时设定窗口最小尺寸的方法

    本文实例讲述了C#实现Winform鼠标拖动窗口大小时设定窗口最小尺寸的方法.分享给大家供大家参考,具体如下: winform 程序运行过程中,用户用鼠标拖动窗体大小时,如将窗体调整得极小,可能窗体上的控件就面目全非(或看不到了),用下面的代码可以设定窗口的最小尺寸,以防止这种情况 private void Form1_ResizeEnd(object sender, EventArgs e) { //this.Text = "2width:" + this.Width.ToStrin

  • Winform下实现图片切换特效的方法

    本文实例讲述了Winform下实现图片切换特效的方法,是应用程序开发中非常实用的一个功能.分享给大家供大家参考之用.具体方法如下: 本实例源自网络,功能较为齐全.丰富!主要功能代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Drawin

  • Nuxt pages下不同的页面对应layout下的页面布局操作

    有时候我们pages中不同的页面需要不同的个性化布局这时候layout就起作用了 layouts 根目录下的所有文件都属于个性化布局文件,可以在页面组件中利用 layout 属性来引用. pages文件下组件的layout属性值为layout文件下的所对应的布局组件的名称 请确保在布局文件里面增加 <nuxt/> 组件用于显示页面非布局内容. 举个例子 1.layouts/custom_layout.vue: <template> <div> <div class

  • Windows下通过cmd进入DOS窗口访问MySQL数据库

    1.win + R 键入cmd,进入dos窗口. 2.切换进入mysql server的安装目录,即mysql.exe的所在目录. 例如:cd C:\Program Files\MySQL\MySQL Server 5.5\bin 3.执行访问数据库的命令: 例如:mysql -hlocalhost -P3306 -uroot -p -h:服务器IP,localhost表示本地: -P:端口号,默认为3306,可不加. -u:数据库连接用户名 -p:密码,如果设置了密码,可直接在-p后添加:如果

  • 易语言窗口界面与菜单功能详解

    一.系统主窗口布局 在系统安装后第一次进入时,主窗口的顶端为菜单条,菜单条的下面为标准工具条,左边为工作夹,下边为状态夹,中间为"_启动窗口"的窗口设计界面,右边为窗口单元工具箱.另外,系统状态行默认是不显示的,使用组合夹可以将工作夹与输出夹组合到一起,编写程序时将使用程序编辑窗口. 在主窗口或其各类工具条上单击鼠标右键可以弹出用作设置各种工具条.工具夹显示状态的菜单. 二.工作夹 在工作夹中包括三个子夹,名为:"支持库"."程序"."

随机推荐