利用委托技术实现多个子窗口与主窗口之间交互通信——修订版

发布时间 2023-09-13 15:12:25作者: Stephen_Young

上次发的《利用委托技术实现多个子窗口与主窗口之间交互通信》存在如下几个问题:
1.没有详细注释说明采用了哪几个委托,分别是干什么的,委托的5要素没有清晰的标识出来——详细注释出来;
2.当子窗口先打开,再关闭了以后,程序仍然可以响应“警告”“问题”....等弹框。——通过判断自创的isDispose值
3.其他一些细节,比如:显示框的垂直进度条不会自动滑动到最新一行;显示框可以直接输入,不防呆;——设置控件Readonly属性
4.ChildForm的唯一标识号,按顺序增加减少存在bug,导致频繁新建子窗口,关闭,时窗体tile将会出现重复;——此次改为6位随机数后缀
针对以上问题,修改代码如下:
MainForm:

点击查看代码
using System;
using System.Windows.Forms;
/*
 说明:本实例演示了利用委托技术来实现跨类(Form)来传递信息
共用了2个委托:
一个【1】【2】【3】【4】【5】子窗体的信息给到主窗口
一个【a】【b】【c】【d】【e】子窗体接受来自主窗体的信息
 */
namespace DelegateTestForm
{
    //定义委托
    public delegate void SendMsgDelegate(string msg);//【1】定义委托1类型:子窗口往主窗口发送消息

    public delegate string ChildReceiveDelegate(string data);//【a】定义委托2类型:接受来自主窗口的信息
    public partial class MainFrm : Form
    {
        string child_frm_tile_append = null;//定义一个子窗口标题后缀的变量

        ChildReceiveDelegate _childReceive = null;//【b】定义主发给你从的委托变量

        public MainFrm()
        {
            InitializeComponent();
            this.Indicator.ScrollBars = ScrollBars.Both;
            Indicator.Enabled = true;
            Indicator.ReadOnly = true;
        }

        private void button1_Click(object sender, EventArgs e)//新建子窗口的按钮按下事件
        {
            ChildForm childFrm = new ChildForm();//实例化一个子窗口的对象,此时委托变量sdn就会被定义
            child_frm_tile_append = Random6String(6);
            childFrm.Text = "ChildForm"+ child_frm_tile_append;//修改打开的子窗口的标题,带上序号

            _childReceive += childFrm.RecMainMsg;//【d】绑定委托
            childFrm.sdn += MainReceMsg;//【4】绑定委托,sdn这个委托变量是在ChildForm.cs中定义的,这里在便绑定一个MainReceMsg(string data)方法

            childFrm.Show();
        }

        private void MainReceMsg(string data)//【3】委托方法
        {
            this.Indicator.Text += $"[{this.Text}]" + data;
        }
        private void button2_Click(object sender, EventArgs e)//发送按钮按下事件
        {
            if (this.textBox1.Text!="") {
                Indicator.Text += "[MainForm广播]:" + this.textBox1.Text + "\r\n";//本地的发送直接显示在indicator上,无须用什么委托
                if (_childReceive!=null)
                {
                    _childReceive.Invoke("[MainForm广播]:" + this.textBox1.Text);//【e】使用委托
                }
            }
            else{
                MessageBox.Show("警告:发送的信息不能为空", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }
        private void button3_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("确定要清空显示吗?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (dr == DialogResult.OK)
            {
                this.Indicator.Clear();
            }
        }

        private void Indicator_TextChanged(object sender, EventArgs e)
        {
            Indicator.SelectionStart = Indicator.Text.Length;//将光标位置设置到当前内容的末尾
            Indicator.ScrollToCaret();//滚动到光标位置
        }
        /// <summary>
        /// 产生一个定义长度的6位随机数字的字符串
        /// </summary>
        /// <param name="stringlen"></param要生成的字串长度>
        /// <returns>str</returns>
        private string Random6String(int stringlen)
        {
            // Creating object of random class
            Random rand = new Random();
            int randValue;
            string str = "";
            char letter;
            for (int i = 0; i < stringlen; i++)
            {
                // Generating a random number.
                randValue = rand.Next(0, 9);
                // Generating random character by converting
                // the random number into character.
                letter = Convert.ToChar(randValue+48);// Appending the letter to string.
                str = str + letter;
            }
            return str;
        }
    }
}

ChildForm代码:

点击查看代码
using System;
using System.Windows.Forms;
using static DelegateTestForm.MainFrm;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;


namespace DelegateTestForm
{
    public partial class ChildForm : Form
    {
        public SendMsgDelegate sdn = null;//【2】定义委托变量


        MessageBoxEx messageBoxEx = new MessageBoxEx();

        public ChildForm()
        {
            InitializeComponent();
            this.Indicator.ScrollBars = ScrollBars.Both;
            Indicator.ReadOnly = true;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (this.textBox1.Text != String.Empty) {
                string data_out = this.textBox1.Text + "\r\n";
                sdn.Invoke($"<--[{this.Text}]:" + data_out);//【5】调用委托,是的MainFrm接受到ChildFrm发送的信息
                Indicator.Text += $"[{this.Text}]-->" + "[MainForm]:" + data_out;
            }
            else {
                MessageBox.Show("警告:发送的信息不能为空", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void ChildForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.Dispose();
        }
        public string RecMainMsg(string data)//【c】定义委托方法
        {
            if (!this.IsDisposed)//判断窗口是否被关闭了;
            {
                this.Indicator.Text += data + "\r\n";
                String tempData = data.Substring(13, 2);
                switch (tempData)
                {
                    case "警告":
                        MessageBox.Show("警告:响应弹出框", "信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        break;
                    case "问题":
                        MessageBox.Show("问题:响应弹出框", "信息", MessageBoxButtons.OK, MessageBoxIcon.Question);
                        break;
                    case "错误":
                        MessageBoxEx.Show(this, "错误:响应弹出框", "错误信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        break;
                    default:
                        break;
                }
            }
            return data;//委托的有返回string类型,这里也必须有
        }
        private void button3_Click(object sender, EventArgs e)
        {
            DialogResult dr = MessageBox.Show("确定要清空显示吗?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (dr == DialogResult.OK)
            {
                this.Indicator.Clear();
            }
            else
            {
            }
        }

        //[DllImport("User32.dll", EntryPoint = "FindWindow")]
        //private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        private void ChildForm_Load(object sender, EventArgs e)
        {
    }

        private void Indicator_TextChanged(object sender, EventArgs e)
        {
            Indicator.SelectionStart = Indicator.Text.Length;//将光标位置设置到当前内容的末尾
            Indicator.ScrollToCaret();//滚动到光标位置
        }
    }

}



最终实现的效果: