///======IOT测试工程(苏州大学嵌入式系统与物联网)=========================
///工程名称：US-Monitor                                                                            
///功能描述：接收管理服务器（MS_Prg）转发来的终端UE数据，并将数据进行实时
///          显示，然后写入到数据库中。提供回发数据到终端UE的功能。可以
///          配合网页程序（AHL-WEB）使用，为AHL-WEB提供数据库并实现数据库
///          的转发。
///版    本：2017年11月21日，V1.0；2018年2月19日，V2.0，WYH   
///=======================================================================
using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Configuration;
using Microsoft.Win32;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Reflection;
using System.Xml.Linq;
using System.Xml;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;
using System.Net.NetworkInformation;
using cn.edu.suda.sumcu.iot.data;
using cn.edu.suda.sumcu.iot.util;
using cn.edu.suda.sumcu.iot.chart;
using System.Text.RegularExpressions;
using cn.edu.suda.sumcu.iot.state;

//Form类主要针对iot应用开发，故放在cn.edu.suda.sumcu.iot空间下的form子空间中
namespace cn.edu.suda.sumcu.iot.form
{
    public delegate void refresh();
    public partial class FrmMain : Form
    {
        //（1）定义使用的全局变量
        public string[] g_IMSI = null;    //侦听的imsi号数组
        public string g_target;           //连接的目标地址（如：123.456.789:12345）
        public string g_wsTarget;         //WebSocket服务器地址（如：ws://0.0.0.0:38867）
        public string g_wsDirection;      //WebSocket二级目录（如：/wsServices/）
        public ulong g_TimeSec;           //程序已经运行的时间（秒）
        public static string myhardaddr = "";
        //（2）FrameData为存储帧结构中的变量名、变量类型、别名等信息的结构体
        public FrameData g_frmStruct1 = new FrameData();//用户信息帧（包含用户信息的所有字段）
        public FrameData g_frmStruct0 = new FrameData();//配置信息帧（存入终端flash中的数据）
        private List<string> g_ListCommandsField = new List<string>();   //存储命令对应的帧格式（如A0命令对应的内容）
        private List<string> g_ListCommands = new List<string>();        //存储命令（A0,A1,A2……）
        public Dictionary<string, FrameData> g_commandsFrame =
                                  new Dictionary<string, FrameData>();  //存储命令对应的帧（命令和FrameData对应）

        //（3）定义数据表的操作对象
        public SQLCommand sQLDevice;      //记录帧结构的变量名、类型和别名
        public SQLCommand sQLDown;        //下行帧记录表数据库操作对象
        public SQLCommand sQLUp;          //上行帧记录表数据库操作对象


        //（4）定义使用的窗体对象      
        public FrmRealtimeData frmRealtimeData = null;          //实时数据窗体
        public FrmRealtimeSeries frmRealtimeSeries = null;      //实时曲线窗体
        public FrmHistoryData frmHistoryData = null;            //历史数据窗体
        public FrmHistorySeries frmHistorySeries = null;        //历史曲线窗体
        public FrmDeviceConfig  frmDeviceConfig = null;         //基本参数窗体                    

        private FrmRealtimeData realFrm;
        private refresh refreshTest;

        /// <summary>                                                       
        /// 函 数 名:setopenstart                             
        /// 功    能:设置开机启动                                  
        /// 函数调用:无                                    
        /// </summary>                                                      
        ///-----------------------------------------------------------------
        private void setopenstart()
        {
            string strName = Environment.CurrentDirectory;  // 取得或设置当前工作目录的完整限定路径

            string files = Directory.GetFiles(strName, "AHL-IoT.exe", SearchOption.TopDirectoryOnly).FirstOrDefault();
            if (File.Exists(files))
            {
                string strNewName = Path.GetFileName(files);
                RegistryKey reg = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                if (reg == null)
                {
                    reg = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
                }
                else
                {
                    if (reg.GetValue(strNewName) == null)
                    {
                        reg.SetValue(strNewName, files);
                    }
                }
            }
        }

        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 函 数 名:IoT:类IoT的构造函数                              
        /// 功    能:完成窗体的初始化工作                                   
        /// 函数调用:InitializeComponent                                    
        /// </summary>                                                      
        ///-----------------------------------------------------------------
        public FrmMain()
        {
            setopenstart();//【191212】设置开机自启动
            InitializeComponent();   //自动生成的窗体初始化布局
            realFrm = new FrmRealtimeData();
            refreshTest += realFrm.refreshControl;
        }
        ///-----------------------------------------------------------------
        /// <summary>  
        /// 对象：窗体FrmMain（主窗体）
        /// 事件：Load事件（窗体加载事件，显示窗体是触发）                              
        /// 功能：主窗体加载时，显示该窗体，进行一系列初始化工作，见注释
        /// </summary>                                                      
        ///-----------------------------------------------------------------
        private void FrmMain_Load(object sender, EventArgs e)
        {
            try
            {
                //（1）定义并初始化变量
                int i,j,k;   //临时变量
                XmlNode xNode;               //xml文件的根节点
                string vName = "";
                string vType = "";
                string votherName = "";
                string vWR = "";
                g_TimeSec = 0;              //程序已经运行的时间（秒）
                timer_FrmMain_1S.Enabled = false;   //1S定时器暂停
                //（2）设置允许跨线程文本框赋值
                Control.CheckForIllegalCrossThreadCalls = false;
                //（3）加载“AHL.xml”文档并读取出IMSI号、目标地址等信息
                #region
                try
                {
                    //加载“AHL.xml”文件，进行解析
                    XmlDocument xmlDoc = new XmlDocument();
                    string configPath = Application.StartupPath + "/../../04_Resource/AHL.xml";  //【20200811】
                    xmlDoc.Load(configPath);    //读取AHL.xml文件到内存
                    //解析“AHL.xml”文件
                    xNode = xmlDoc.DocumentElement;    //获取根节点
                    xmlDoc.RemoveAll();                //释放“AHL.xml”文档
                    //遍历一级节点
                    foreach (XmlNode node in xNode.ChildNodes)
                    {
                        //找到appSetting节点
                        if (node.Name == "appSettings")
                        {
                            //遍历二级节点，自上而下开始读取
                            foreach (XmlNode node2 in node.ChildNodes)
                            {
                                //读取本窗体名并显示
                                if (node2.Name == "formName")  
                                    this.Text = node2.InnerText;
                                //读取要连接的目标地址HCIComTarget→target
                                else if (node2.Name == "HCIComTarget")
                                    g_target = node2.InnerText;
                                else if (node2.Name == "WebSocketTarget")
                                    g_wsTarget = node2.InnerText;
                                else if (node2.Name == "WebSocketDirection")
                                    g_wsDirection = node2.InnerText;
                                //读取要侦听的终端UE的IMSI号→g_IMSI数组
                                else if (node2.Name == "IMSI")
                                {
                                    //以“;”为间隔符将imsiList中的数据解析到g_IMSI数组中
                                    g_IMSI = node2.InnerText.ToString().Trim().Split(';');
                                    //去除长度不等于15的号码（IMSI号的长度确定为15）
                                    List<string> list = g_IMSI.ToList();
                                    for (i = 0; i < list.Count; i++)
                                    {
                                        //【20181004】去除IMSI号中的空格、换行、回车和制表符
                                        list[i] = list[i].Replace(" ", "").Replace("\r", "").Replace("\n", "").Replace("\t", "");
                                        if (list[i].Length != 15)
                                        {
                                            list.RemoveAt(i);
                                            i--;
                                        }
                                    }
                                    g_IMSI = list.ToArray();  //正确的IMSI号→g_IMSI数组
                                }
                                else if (node2.Name == "commands")
                                {
                                    //遍历三级节点
                                    foreach (XmlNode node3 in node2.ChildNodes)
                                    {
                                        g_ListCommands.Add(node3.Name);
                                        g_ListCommandsField.Add("command," + node3.InnerText);
                                    }
                                }
                                else if (node2.Name == "frames")
                                {
                                    //遍历三级节点
                                    foreach (XmlNode node3 in node2.ChildNodes)
                                    {
                                        if (node3.Name == "frame0")//若为MCU配置相关变量
                                        {
                                            //遍历四级节点
                                            foreach (XmlNode node4 in node3.ChildNodes)
                                            {
                                                //遍历五级节点
                                                foreach (XmlNode node5 in node4.ChildNodes)
                                                {
                                                    if (node5.Name == "name")    //数据类型type
                                                        vName = node5.InnerText;
                                                    else if (node5.Name == "type")    //数据类型type
                                                        vType = node5.InnerText;
                                                    else if (node5.Name == "otherName") //中文名称
                                                        votherName = node5.InnerText;
                                                    else if (node5.Name == "wr")   //读写属性
                                                    {
                                                        vWR = node5.InnerText;
                                                        //存入g_frmStruct中
                                                        g_frmStruct0.addParameter(vType, vName, votherName, vWR);
                                                    }
                                                }//遍历五级节点
                                            }//遍历四级节点
                                        }
                                        else if (node3.Name == "frame1")//若为MCU通信相关变量
                                        {
                                            //遍历四级节点
                                            foreach (XmlNode node4 in node3.ChildNodes)
                                            {
                                                //遍历五级节点
                                                foreach (XmlNode node5 in node4.ChildNodes)
                                                {
                                                    if (node5.Name == "name")    //数据类型type
                                                        vName = node5.InnerText;
                                                    else if (node5.Name == "type")    //数据类型type
                                                        vType = node5.InnerText;
                                                    else if (node5.Name == "otherName") //中文名称
                                                        votherName = node5.InnerText;
                                                    else if (node5.Name == "wr")   //读写属性
                                                    {
                                                        vWR = node5.InnerText;
                                                        //存入g_frmStruct中
                                                        g_frmStruct1.addParameter(vType, vName, votherName, vWR);
                                                    }
                                                }//遍历五级节点
                                            }//遍历四级节点
                                        }
                                    }
                                }
                            }  //遍历二级节点
                        }  //if (node.Name == "appSettings")
                    }   //遍历一级节点
                }   //try
                catch
                {
                    //显示错误信息
                    MessageBox.Show("【主窗体加载时,读取配置文件AHL.xml错误】"
                        , "金葫芦IoT友情提示：", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    //退出程序
                    Application.Exit();
                }
                #endregion
                //（4）设置底部“用户操作、云平台连接、地址、时间”显示对齐方式
                this.toolStripUserOper.Alignment=ToolStripItemAlignment.Right;
                this.toolStripConnectStatus.Alignment = ToolStripItemAlignment.Right;
                this.toolStripCloudAddr.Alignment = ToolStripItemAlignment.Right;
                this.toolStripStatusTime.Alignment = ToolStripItemAlignment.Right;
                //在主界面右下角toolStripCloudAddr中显示云平台地址
                this.toolStripCloudAddr.Text = g_target;
                this.toolStripUserOper.Text = "运行状态：将进行数据库操“AHL-IoT.mdf”操作...";
                this.Show();       //把主窗体显示出来                

                //（5）数据库操作
                #region
                //（5.1）获取App.config文件中AppSettings域的数据库连接字符串
                string connectionString = System.Configuration.
                    ConfigurationManager.AppSettings["connectionString"];
                string myconnectionString = System.Configuration.
                    ConfigurationManager.AppSettings["myconnectionString"];
                this.toolStripUserOper.Text = connectionString;  //状态栏显示
                this.Refresh();                                  //显示刷新
                //（5.2）初始化数据库中的表（3张表）
                sQLDevice = new SQLCommand(connectionString, "Device");       //设备信息记录表
                sQLDown = new SQLCommand(connectionString, "Down");           //下行帧记录表
                sQLUp = new SQLCommand(connectionString, "Up");               //上行帧记录表
                //（5.3）判断数据库是否能够正确连接，并删除多余数据
                int counts = sQLUp.count();
                if (counts < 0)
                {
                    MessageBox.Show("未能成功连接数据库，请检查：（1）DataBase文件夹位置是否正确；" +
                        "（2）DataBase文件夹中的文件是否对user用户有完全控制权限；（3）VS中是否有SQL Server Data Tools",
                        "金葫芦友情提示（加载主窗体时）：", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Application.Exit();
                }
                
                //（5.4）根据g_frmStruct1更新Up表、Down表和Command表的字段结构
                UpdateDbColumns(sQLUp, g_frmStruct1);
                UpdateDbColumns(sQLDown, g_frmStruct1);
                UpdateDbColumns(sQLDevice, g_frmStruct0);
                //（5.5）根据数据结构g_ListCommandsField、g_ListCommands和g_frmStruct1更新字典g_commandsFrame
                FrameData frame = null;
                for (i = 0; i < g_ListCommands.Count(); i++)
                {
                    frame = new FrameData();
                    string[] attr = Regex.Split(g_ListCommandsField[i].ToString(), ",", RegexOptions.IgnoreCase);
                    for (j = 0; j < attr.Count(); j++)
                    {
                        for (k = 0; k < g_frmStruct1.Parameter.Count();k++ )
                        {
                            if (attr[j] == g_frmStruct1.Parameter[k].name)
                            {
                                string variable = g_frmStruct1.Parameter[k].name;
                                string type = g_frmStruct1.Parameter[k].type;
                                string otherName = g_frmStruct1.Parameter[k].otherName;
                                string wr = g_frmStruct1.Parameter[k].wr;
                                frame.addParameter(type, variable, otherName, wr);
                                break;
                            }
                        }
                    }                       
                    g_commandsFrame.Add(g_ListCommands[i].ToString(), frame);
                }
                #endregion
                //（6）初始化全局变量
                //g_FieldCnt = g_frmStruct1.Parameter.Count; //初始化参数的个数 
                //（7）加载实时数据窗体运行
                timer_FrmMain_1S.Enabled = true;   //1S定时器启动
                mnuRealTimeData_Click(sender, e);
                mnuProBasePara_Click(sender, e);
                //frmDeviceConfig.Hide();
            }
            catch(Exception ee)  //主窗体加载系统错误
            {
                //显示错误信息
                MessageBox.Show("主窗体加载系统错误\r\n" + ee.Message,
                    "金葫芦友情提示：", MessageBoxButtons.OK, MessageBoxIcon.Error);
                //退出程序
                System.Environment.Exit(0);
            }

        }

        private void UpdateDbColumns(SQLCommand sqlTable,FrameData frame)
        {
            //1.维持数据库表结构与帧结构一致
            for(int i=0;i<frame.Parameter.Count;i++)
            {
                //申请10倍的空间
                sqlTable.insertColumn(frame.Parameter[i].name, "nvarchar(" + frame.Parameter[i].size + "0)");
            }
        }

        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 函 数 名:Form1_FormClosing                            
        /// 功    能:结束程序并释放资源                                   
        /// 函数调用:System.Environment.Exit                                    
        /// </summary>                                                      
        ///-----------------------------------------------------------------
        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            System.Environment.Exit(0);//关闭程序
            this.Dispose();
            this.Close();
        }
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 对    象:timer_FrmMain_1S_Tick                                  
        /// 事    件:该事件每1秒执行一次                                                 
        /// 功    能:（1）更新当前的系统时间（2）每30秒检测一次本机是否联网                      
        /// </summary>                                                      
        /// <param name="sender"></param>                                   
        /// <param name="e"></param>                                        
        ///-----------------------------------------------------------------
        private void timer_FrmMain_1S_Tick(object sender, EventArgs e)
        {
            //（1）更新当前的系统时间
            this.toolStripStatusTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            //（2）每60秒检测一次本机是否联网，通过ping百度实现            
            if (this.g_TimeSec % 60 == 0)
            {
                
                testNet();
            }
            refreshTest();
            this.g_TimeSec++;
        }
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 对    象:button_closeApp_Click 
        ///         （顶部主菜单中的“退出”=》“退出系统”按钮）                                     
        /// 事    件:Click（单击）                                                  
        /// 功    能:关闭本应用程序                        
        /// </summary>                                                      
        /// <param name="sender"></param>                                   
        /// <param name="e"></param>                                        
        ///-----------------------------------------------------------------
        private void button_closeApp_Click(object sender, EventArgs e)
        {
            this.Dispose();
            Application.Exit();
        }
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 对    象:ToolStrip_Help_1_Click
        ///         （顶部主菜单中的“帮助”=》“使用说明”按钮）                                     
        /// 事    件:Click（单击）                                                  
        /// 功    能:显示使用说明信息                      
        /// </summary>                                                      
        /// <param name="sender"></param>                                   
        /// <param name="e"></param>                                        
        ///-----------------------------------------------------------------
        private void mnuHelpUserManual_Click(object sender, EventArgs e)
        {
            //MessageBox.Show(userManual);
            string ddataDir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;//获取绝对地址
            System.Diagnostics.Process.Start(ddataDir + "../../04_Resource/instructions.chm");
        }
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 对    象:ToolStrip_Help_2_Click
        ///         （顶部主菜单中的“帮助”=》“程序说明”按钮）                                     
        /// 事    件:Click（单击）                                                  
        /// 功    能:显示程序说明信息                      
        /// </summary>                                                      
        /// <param name="sender"></param>                                   
        /// <param name="e"></param>                                        
        ///-----------------------------------------------------------------
        private void mnuHelpProInstruction_Click(object sender, EventArgs e)
        {
            //MessageBox.Show(prgManual);
            string ddataDir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;//获取绝对地址
            System.Diagnostics.Process.Start(ddataDir + "../../04_Resource/help.chm");
        }
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 对    象:ToolStrip_Help_3_Click
        ///         （顶部主菜单中的“帮助”=》“版本”按钮）                                     
        /// 事    件:Click（单击）                                                  
        /// 功    能:显示版本信息                      
        /// </summary>                                                      
        /// <param name="sender"></param>                                   
        /// <param name="e"></param>                                        
        ///-----------------------------------------------------------------
        private void mnuHelpVersion_Click(object sender, EventArgs e)
        {
            //MessageBox.Show(prgVersion);
            string ddataDir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;//获取绝对地址
            System.Diagnostics.Process.Start(ddataDir + "../../04_Resource/version.chm");
        }
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 对    象:mnuRealTimeData_Click
        ///         （顶部主菜单中的“实时”=》“实时数据”按钮）                                     
        /// 事    件:Click（单击）                                                  
        /// 功    能:显示实时数据界面                       
        /// </summary>                                                      
        /// <param name="sender"></param>                                   
        /// <param name="e"></param>                                        
        ///-----------------------------------------------------------------
        private void mnuRealTimeData_Click(object sender, EventArgs e)
        {
            //若已打开过，只需重新显示
            if (frmRealtimeData != null && frmRealtimeData.IsDisposed == false)
            {
                frmRealtimeData.Hide();   //置顶显示
                frmRealtimeData.Show();
                this.toolStripUserOper.Text = "Running State：Reenter realtime";
                frmRealtimeData.Refresh();
            }
            else
            {
                frmRealtimeData = new FrmRealtimeData(this);
                frmRealtimeData.MdiParent = this;
                frmRealtimeData.Show();
            }
        }
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 对    象:mnuHistoryData_Click
        ///         （顶部主菜单中的“历史”=》“历史数据”按钮）                                     
        /// 事    件:Click（单击）                                                  
        /// 功    能:显示历史数据界面                       
        /// </summary>                                                      
        /// <param name="sender"></param>                                   
        /// <param name="e"></param>                                        
        ///-----------------------------------------------------------------
        private void mnuHistoryData_Click(object sender, EventArgs e)
        {
            if (frmHistoryData != null && frmHistoryData.IsDisposed == false)
            {
                //在mdi中置顶显示
                frmHistoryData.Hide();
                frmHistoryData.Show();
                return;
            }
            frmHistoryData = new FrmHistoryData(this);
            frmHistoryData.MdiParent = this;
            frmHistoryData.Show();
        }

        ///以下为内部函数
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 函数名称：testNet                                     
        /// 传入参数：无                                                 
        /// 函数返回：无      
        /// 函数功能：通过ping百度的IP判断是否联网，并弹出MessageBox提示
        /// </summary>                                                                                          
        ///-----------------------------------------------------------------
        private bool testNet()
        {
            //bool flag = true;
            //string message = "";
            //int n;
            //n = 0;
            //try
            //{
            //    Ping p = new Ping();
            //    for (n = 0; n <= 3; n++)
            //    {
            //        PingReply pr = p.Send("www.baidu.com");  //"180.97.33.108"
            //        if (pr.Status == IPStatus.Success) break;
            //        if (n == 3) flag = false;
            //    }
            //}
            //catch (Exception e)
            //{
            //    message = e.ToString();
            //    flag = false;
            //}
            //if (flag == false)
            //{
            //    //DialogResult res = MessageBox.Show("您的计算机尚未联网，请联网之后点击确定！或点击取消关闭本程序" + message
            //    //    , "金葫芦友情提示（testNet函数错误提示信息）：", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
            //    DialogResult res = MessageBox.Show("【您的计算机尚未联网，请联网后重新启动程序！】"
            //            , "金葫芦IoT友情提示（testNet函数错误提示信息）：", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //    //if (res == DialogResult.OK)
            //    //    System.Diagnostics.Process.Start(System.Reflection.Assembly.GetExecutingAssembly().Location);
            //    if (res == DialogResult.OK)
            //    {
            //        this.Dispose();
            //        Application.Exit();
            //    }
            //}
            return true;
        }

         /// <summary>
         /// 设置状态栏中用户操作的Label文本内容，供其他窗体调用
         /// </summary>
         /// <param name="str"></param>
        public void SetToolStripUserOperText(String str)
        {
            this.toolStripUserOper.Text = str;
        }
        /// <summary>
        /// 设置状态栏中状态提示的Label文本内容，供其他窗体调用
        /// </summary>
        /// <param name="str"></param>
        public void SetToolStripConnectStatusText(String str)
        {
            this.toolStripConnectStatus.Text = str;
        }
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 对    象:mnuRealTimeLine_Click
        ///         （顶部主菜单中的“实时”=》“实时曲线”按钮）                                     
        /// 事    件:Click（单击）                                                  
        /// 功    能:显示实时数据曲线界面                       
        /// </summary>                                                      
        /// <param name="sender"></param>                                   
        /// <param name="e"></param>                                        
        ///-----------------------------------------------------------------
        private void mnuRealTimeLine_Click(object sender, EventArgs e)
        {
            frmRealtimeSeries = new FrmRealtimeSeries(this);
            frmRealtimeSeries.MdiParent = this;
            frmRealtimeSeries.Show();
        }
        ///-----------------------------------------------------------------
        /// <summary>                                                       
        /// 对    象:mnuHistoryLine_Click
        ///         （顶部主菜单中的“历史”=》“历史曲线”按钮）                                     
        /// 事    件:Click（单击）                                                  
        /// 功    能:显示历史数据曲线界面                       
        /// </summary>                                                      
        /// <param name="sender"></param>                                   
        /// <param name="e"></param>                                        
        ///-----------------------------------------------------------------
        private void mnuHistoryLine_Click(object sender, EventArgs e)
        {
            ////若已打开过，只需重新显示
            //if (frmHistorySeries != null && frmHistorySeries.IsDisposed == false)
            //{
            //    //在mdi中置顶显示
            //    frmHistorySeries.Hide();
            //    frmHistorySeries.Show();
            //    return;
            //}
            //else
            //{
                frmHistorySeries = new FrmHistorySeries(this);
                frmHistorySeries.MdiParent = this;
                frmHistorySeries.Show();
            //}
        }

        int countFrmConfig = 0;
        private void mnuProBasePara_Click(object sender, EventArgs e)
        {
            countFrmConfig++;
            if (frmDeviceConfig != null && frmDeviceConfig.IsDisposed == false)
            {
                //在mdi中置顶显示
                frmDeviceConfig.Hide();
                frmDeviceConfig.Show();
                return;
            }
            else
            {
                frmDeviceConfig = new FrmDeviceConfig(this);
                frmDeviceConfig.MdiParent = this;
                if (countFrmConfig > 1)  //第一次不显示
                    frmDeviceConfig.Show();
            }
        }

        private void 通信测试CCtrlCToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //if (frmTest != null && frmTest.IsDisposed == false)
            //{
            //    //在mdi中置顶显示
            //    frmTest.Hide();
            //    frmTest.Show();
            //    return;
            //}
            //else
            //{
            //    frmTest = new FrmTest(this);
            //    frmTest.MdiParent = this;
            //    frmTest.Show();
            //}
        }
    }
}
