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

    出处:https://www.cnblogs.com/zuowj/p/5225814.html

  • 相关阅读:
    第三讲:增长全局观
    搭建安卓环境
    ~~
    天气阴
    天气晴
    Spark性能优化指南——高级篇
    Ceph Jewel 10.2.3 环境部署
    《你只是看起来很努力》--读书笔记
    博客园基础环境配置
    Spark 1.3.0 单机安装
  • 原文地址:https://www.cnblogs.com/mq0036/p/16710534.html
Copyright © 2020-2023  润新知