cxs 2 тижнів тому
батько
коміт
73a8a897ed

+ 1 - 2
OTSIncAMeasureApp/5-OTSMeasureStatuImageFun/OTSMeasureStatusWindow.cs

@@ -1567,7 +1567,6 @@ namespace OTSMeasureApp
             control_Ruler.RulerWidth = Convert.ToInt32(f_ruler_size * m_ZoomRecord);
             control_Ruler.Value = 100;
             double width = GetZoomedImageRect(picBox).Width;
-            int[] RulerVal = { 1, 2, 5, 10, 20, 50, 100, 200, 500 };
             foreach (int i in RulerVal)
             {
                 double obj = Convert.ToInt32(control_Ruler.RulerWidth * i / 100);
@@ -1767,13 +1766,13 @@ namespace OTSMeasureApp
             }
         }
         #region 显示标尺
+        int[] RulerVal = { 1, 2, 5, 10, 20, 50, 100, 200, 500 };
         public void RulerInit()
         {
             control_Ruler.Value = 100;
             int realwidth = m_MeasureAppForm.m_ProjRstData.GetWorkingSample().GetSEMDataMsr().GetScanFieldSize();
             double width = GetZoomedImageRect(picBox).Width;
             f_ruler_size = width * 100 / realwidth;
-            int[] RulerVal = { 1, 2, 5, 10, 20, 50, 100, 200, 500 };
             foreach (int i in RulerVal)
             {
                 double obj = Convert.ToInt32(f_ruler_size * i / 100);

+ 682 - 0
OTSSysMgrApp/Control_XRayTable.cs

@@ -0,0 +1,682 @@
+using OTSPeriodicTable;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace OTSSysMgrApp
+{
+    /// <summary>
+    /// 能谱图类
+    /// </summary>
+    public partial class Control_XRayTable : UserControl
+    {
+        #region 变量定义
+        //定义两个能量值线,用来显示使用
+        float[] m_f_show2 = new float[2000];
+
+        //用来保存实际传入的xray值数,用该数据转换成显示的值
+        uint[] m_analysis_xray = new uint[2000];
+
+        List<TwoPoint> m_list_twopoint1 = new List<TwoPoint>();
+        List<TwoPoint> m_list_twopoint2 = new List<TwoPoint>();
+
+        //记录鼠标所在位置
+        Point m_mouse_point = new Point();
+
+        //字体
+        Font m_thisfont = new Font("微软雅黑", 8, FontStyle.Regular);
+        Font m_thisfont_bold = new Font("微软雅黑", 8, FontStyle.Bold);
+
+        //下标尺分界位置
+        float m_f_rulerX_location = 160;
+
+        //下坐标尺设定参数
+        float m_i_smalkd = 5;                                           //5像素一个小刻度
+        float m_i_bigkd = 25;                                           //25像素一个大刻度
+        float m_i_smallkd_number = 200;                                //小刻度的个数
+        float m_i_bigkd_number = 40;                                    //大刻度的个数
+
+        float m_i_draw_start = 40;                                       //整个界面绘制的起始点
+        float m_i_draw_end = 1004;                                      //整个界面绘制的边界
+
+        float m_Y_draw_end = 175;                                      //整个界面绘制的边界高
+        float m_Y_draw_TopDiff = 15;                                    //Y轴距离顶部距离
+        float m_Y_MaxValue = 0;                                         //Y轴显示的最大刻度长度
+        uint m_Y_Value = 50;                                           //Y轴大刻度包含像素数
+
+        float m_i_rightdrawlabellocation_x = 850;                       //右上角要显示文字的位置
+        float m_i_rightdrawlabellocation_y = 5;                         //右上角要显示文字的位置
+
+        SolidBrush m_this_sb = new SolidBrush(Color.Black);             //画刷
+        SolidBrush m_this_sb_blue = new SolidBrush(Color.Blue);         //
+        Pen m_this_p = new Pen(Color.Black, 0.5f);                      //画笔的颜色
+        Pen m_this_p_blue = new Pen(Color.DimGray, 0.5f);               //画笔的颜色 , 分析xray的颜色
+        Pen m_mousemove_p = new Pen(Color.PowderBlue, 0.1f);            //鼠标移动画的竖线的画笔颜色
+
+        float m_kml_fz_top = 0;                                         //计算KML峰值记录最高点变量
+
+        float m_xraytopixel_multiple = 40;                              //比如,从xray0-6000的值,转到显示像素中0-150的比例倍数
+
+        float m_xraysum2 = 0;                                           //xray计数总和2
+        List<Periodic> m_list_periodic;                                 //元素周期表,相关数据,窗体加载时初始化,然后用来计算使用
+        List<KMLFPoint> m_list_kmlfpoint;                               //KML峰值,对应的位置和元素名
+
+        //属性相关变量,用来显示使用
+        private bool m_b_show_analysisxray = true;                      //设置是否绘制分析xray线
+        private List<ShowElementInfo> m_list_showelementinfo = null;    //需要显示的元素信息列表
+
+        float m_f_zl = 0.5f;                                            //2000个数据放到1000个像素中计算出的增量
+
+        float m_f_kmlfzpd_max = 30;                                     //KML峰值上界限,进行记数的值,峰值判断的界限,需要按峰值最高值,和
+        float m_f_kmlfzpd_mix = 5;                                      //KML峰值下界限
+        string m_ParticleInfo = "";                                    //颗粒相关信息
+        #endregion
+
+        #region 属性相关
+
+        /// <summary>
+        /// 显示元素列表相关信息
+        /// </summary>
+        public List<ShowElementInfo> List_ShowElementInfo
+        {
+            get { return m_list_showelementinfo; }
+            set { m_list_showelementinfo = value; }
+        }
+
+        /// <summary>
+        /// 设置是否绘制分析Xray,默认为显示
+        /// </summary>
+        public bool ShowAnalysisXray
+        {
+            get { return m_b_show_analysisxray; }
+            set { m_b_show_analysisxray = value; }
+        }
+
+        /// <summary>
+        /// 显示颗粒相关信息
+        /// </summary>
+        public string ParticleInfo
+        {
+            get { return m_ParticleInfo; }
+            set { m_ParticleInfo = value; }
+        }
+        #endregion
+
+        #region 构造函数
+        public Control_XRayTable()
+        {
+            InitializeComponent();
+        }
+        
+        /// <summary>
+        /// 需要确定下来倍数后,从xray最大值6000,转换成显示最大值150的比例转换
+        /// </summary>
+        /// <param name="in_value"></param>
+        /// <returns></returns>
+        private float GetValueByRatio(uint in_value)
+        {
+            return in_value / m_xraytopixel_multiple;
+        }
+
+        public void SetParticleInfo(string a_ParticleInfo)
+        {
+            m_ParticleInfo = a_ParticleInfo;
+        }
+
+        /// <summary>
+        /// 设置搜索xray和分析xray值到,记录变量中,及转换成显示变量中,用来供XrayTable显示及计算使用
+        /// </summary>
+        /// <param name="search_xray"></param>
+        /// <param name="analysis_xray"></param>
+        public void SetXRayShowLineValue(uint[] analysis_xray, List<ShowElementInfo> in_list_showelementinfo)
+        {
+            //重新加载时,对当前的宽度等重新加载并计算
+            m_i_draw_end = this.Width-20;
+            m_Y_draw_end = this.Height-20;
+            m_f_rulerX_location = m_Y_draw_end-75;
+            m_i_smalkd = (m_i_draw_end- m_i_draw_start - 4) / m_i_smallkd_number;//按宽度重新计算小刻度的长度 -4是有4像素的边框差
+            m_i_bigkd = (m_i_draw_end- m_i_draw_start - 4) / m_i_bigkd_number;   //按宽度重新计算大刻度的长度
+
+
+            #region 重新初始化相关全局变量
+            m_list_periodic = CListPeriodic.GetListPeriodic();
+            m_list_kmlfpoint = new List<KMLFPoint>();
+
+            m_f_show2 = new float[2000];
+
+            //用来保存实际传入的xray值数,用该数据转换成显示的值
+            m_analysis_xray = new uint[2000];
+
+            m_list_twopoint1 = new List<TwoPoint>();
+            m_list_twopoint2 = new List<TwoPoint>();
+
+            m_list_showelementinfo = new List<ShowElementInfo>();
+
+            //初始化xray之和为0,之后开始进行求和计算
+            m_xraysum2 = 0;
+            //重新初始化高度比例尺
+            m_xraytopixel_multiple = 0;
+            #endregion
+
+            //校验数据错误,防止空数据
+            if (analysis_xray.Count() == 0)
+            {
+                return;
+            }
+            //再防止全数据为0
+            uint ls_u_jcwl = 0;
+            for (int i = 0; i < analysis_xray.Count(); i++)
+            {
+                if (analysis_xray[i] > ls_u_jcwl)
+                    ls_u_jcwl = analysis_xray[i];
+            }
+            if (ls_u_jcwl == 0)
+            {
+                return;
+            }
+
+            //比例尺,要根据传入的数据,自动进行计算的
+            //逻辑那就应该是取最大的xray得到的值,加一点,然后除以我可以显示的像素分辨率,得到的倍数,后面都用这个倍数进行计算
+
+            //取出最大的xray值,计算倍数---------------------------------------------------
+            uint max_xra = 0;
+            for (int i = 0; i < analysis_xray.Length; i++)
+            {
+                if (max_xra < analysis_xray[i])
+                {
+                    max_xra = analysis_xray[i];
+                }
+            }
+            //用最大的值除以可用来显示的像素,得到倍数
+            m_xraytopixel_multiple = (float)(Convert.ToDouble(max_xra) / Convert.ToDouble(m_f_rulerX_location- m_Y_draw_TopDiff-20));
+
+
+            //如果长度不是2000的话,不操作
+            if (analysis_xray.Length == 2000)
+            {
+                //保存实际传入的值
+                m_analysis_xray = analysis_xray;
+                for (int i = 0; i < analysis_xray.Length; i++)
+                {
+                    //这里按比例进行转换
+                    m_f_show2[i] = GetValueByRatio(analysis_xray[i]);
+                    m_xraysum2 = m_xraysum2 + analysis_xray[i];
+                }
+            }
+
+            //生成xray对应的绘制线段
+            float old_value = m_f_rulerX_location - 2;//从基础线-2的位置上进行绘制
+                                                      //float f_zl = 0.5f;//坐标值的增量,以小数做为增量的值,,,,这个坐标的增量应该根据实际的显示长度进行修改
+                                                      //当1000个像素时显示2000个数据,需要2000/1000=0.5f
+                                                      //0.5f就是2000个数据需要放到1000个像素中的计算系数
+
+            double ls_width = m_i_draw_end;//改成固定值,整个绘制浪线的总长
+            double ls_cs = 2000;
+            m_f_zl = (float)((ls_width- m_i_draw_start - 4) / ls_cs);
+
+            //计算KML峰值判定的上标值与下标值
+            GetKMLFPD_MAXANDMIN(m_analysis_xray);
+            for (int i = 0; i < m_f_show2.Length; i++)
+            {
+                TwoPoint tp = new TwoPoint();
+                tp.pf1.X = i * m_f_zl;
+                tp.pf1.Y = old_value;
+
+                tp.pf2.X = i * m_f_zl + m_f_zl;
+                tp.pf2.Y = m_f_rulerX_location - 2 - m_f_show2[i];
+                tp.value = m_analysis_xray[i];
+                tp.kmlf_value = (float)(Convert.ToDouble(i) / Convert.ToDouble(100));
+
+                //重新实现计算峰值上显示元素的计算方法
+                //CalcKMLFPoint(tp);
+
+                old_value = m_f_rulerX_location - 2 - m_f_show2[i];
+
+                m_list_twopoint2.Add(tp);
+            }
+            List<ShowElementInfo> in_list_showelementinfo2 = new List<ShowElementInfo>();
+            if (in_list_showelementinfo != null)
+            {
+                if (in_list_showelementinfo.Count > 10) in_list_showelementinfo2 = in_list_showelementinfo.GetRange(0, 10);
+                else in_list_showelementinfo2 = in_list_showelementinfo;
+                //重新实现的计算峰值上显示元素的计算方法
+                CalcKMLFPoint(in_list_showelementinfo2);
+
+                m_list_showelementinfo = in_list_showelementinfo2;
+            }
+
+            this.Invalidate();
+        }
+
+        /// <summary>
+        /// 根据传入的2000个峰值点,计算出有效参与计算的峰值判定高点,和低点,两个点
+        /// </summary>
+        /// <param name="in_xray"></param>
+        /// <returns></returns>
+        private void GetKMLFPD_MAXANDMIN(uint[] in_xray)
+        {
+            float f_lsmax = 0;
+            //方法是,按50%为高点,10%为低点
+            for (int i = 0; i < in_xray.Count(); i++)
+            {
+                if (f_lsmax < in_xray[i])
+                {
+                    f_lsmax = in_xray[i];
+                }
+            }
+
+            m_f_kmlfzpd_max = (float)(f_lsmax * 0.3);//最顶点的峰
+            m_f_kmlfzpd_mix = (float)(f_lsmax * 0.1);
+            return;
+        }
+
+        /// <summary>
+        /// 根据传入的值,及获取的范围,来判断,该值大概为是什么元素的
+        /// </summary>
+        /// <param name="kml_value">传入的峰值</param>
+        /// <param name="f_rect">范围</param>
+        /// <returns></returns>
+        private string GetElementNameByKMLRange(float kml_value, float f_rect)
+        {
+            string str_ret = "";
+            float ls_f_sx1 = 0;
+            float ls_f_sx2 = 0;
+            float ls_f_sx3 = 0;
+            for (int i = 0; i < m_list_periodic.Count(); i++)
+            {
+                //先对三个值进行转换,转出应有的值
+                if (m_list_periodic[i].K_Peak != "" && m_list_periodic[i].K_Peak != "-")
+                {
+                    ls_f_sx1 = (float)Convert.ToDouble(m_list_periodic[i].K_Peak);
+                }
+                if (m_list_periodic[i].L_Peak != "" && m_list_periodic[i].L_Peak != "-")
+                {
+                    ls_f_sx2 = (float)Convert.ToDouble(m_list_periodic[i].L_Peak);
+                }
+                if (m_list_periodic[i].M_Peak != "" && m_list_periodic[i].M_Peak != "-")
+                {
+                    ls_f_sx3 = (float)Convert.ToDouble(m_list_periodic[i].M_Peak);
+                }
+
+                //然后再对该值进行判断,如果在范围内,则判断为该元素
+                if (kml_value >= (ls_f_sx1 - f_rect) && kml_value < (ls_f_sx1 + f_rect))
+                {
+                    str_ret = m_list_periodic[i].Symbol;
+                    break;
+                }
+                if (kml_value >= (ls_f_sx2 - f_rect) && kml_value < (ls_f_sx2 + f_rect))
+                {
+                    str_ret = m_list_periodic[i].Symbol;
+                    break;
+                }
+                if (kml_value >= (ls_f_sx3 - f_rect) && kml_value < (ls_f_sx3 + f_rect))
+                {
+                    str_ret = m_list_periodic[i].Symbol;
+                    break;
+                }
+            }
+
+            return str_ret;
+        }
+
+
+        /// <summary>
+        /// 在循环遍历中,计算KML峰值中心点
+        /// </summary>
+        /// <param name="tp"></param>
+        private void CalcKMLFPoint(TwoPoint tp)
+        {
+            //大于平均点值 max时,开始记录,2018-10-23重新实现
+            if (tp.value > m_f_kmlfzpd_max)
+            {
+                m_kml_fz_top = tp.kmlf_value;
+            }
+            else if (tp.value < m_f_kmlfzpd_mix && m_kml_fz_top != 0)//平均小于平均峰值 min时,结束记录,并将峰值保存,记录峰值元素
+            {
+                //构造KML峰值list对象
+                KMLFPoint ls_lkmfpoint = new KMLFPoint();
+                ls_lkmfpoint.kml_x = m_kml_fz_top;
+
+                //查找出该峰值是什么元素的, 待完成
+                ls_lkmfpoint.ysm = GetElementNameByKMLRange(m_kml_fz_top, 0.2f);
+
+                //将该峰值保存到峰值上
+                m_list_kmlfpoint.Add(ls_lkmfpoint);
+                m_Y_MaxValue = m_kml_fz_top;
+                m_kml_fz_top = 0;
+            }
+        }
+
+        private void CalcKMLFPoint(List<ShowElementInfo> in_list_showelementinfo)
+        {
+            for (int i = 0; i < in_list_showelementinfo.Count; i++)
+            {
+                KMLFPoint ls_lkmfpoint = new KMLFPoint();
+                ls_lkmfpoint.ysm = in_list_showelementinfo[i].ElementName;
+                ls_lkmfpoint.kml_x = (float)in_list_showelementinfo[i].dKF;
+                ls_lkmfpoint.lml_x = (float)in_list_showelementinfo[i].dLF;
+                //将该峰值保存到峰值上
+                m_list_kmlfpoint.Add(ls_lkmfpoint);
+            }
+        }
+
+        private void Control_XRayTable_Load(object sender, EventArgs e)
+        {
+            #region 设置背景透明及开启双缓冲
+            //设置Style支持透明背景色
+            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
+
+            SetStyle(ControlStyles.UserPaint, true);
+            SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景.
+            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); // 双缓冲
+            this.BackColor = Color.FromArgb(180, 255, 255, 255);
+            #endregion
+
+            //初始化变量,如果不初始化会在设计模式下报错
+            m_list_showelementinfo = new List<ShowElementInfo>();
+        }
+        #endregion
+
+
+
+
+        #region 绘制事件
+        protected override void OnPaint(PaintEventArgs e)
+        {
+            Graphics g = e.Graphics;
+            DrawXrayImage(g);
+        }
+
+        /// <summary>
+        /// 封装绘制能谱数据方法
+        /// </summary>
+        /// <param name="g"></param>
+        protected void DrawXrayImage(Graphics g)
+        {
+            #region //绘制标尺表盘部份----------------------------------------------------------------------------------------------
+            //宽度比的缩放基数
+            float f_js_width = 1;//经过考虑,先定为1,为固定的像素进行绘制
+            #region 绘制下面的标尺
+            //x轴标尺的线
+            g.DrawLine(m_this_p, m_i_draw_start, m_f_rulerX_location, m_i_draw_end * f_js_width, m_f_rulerX_location);
+            //y轴标尺的线
+            g.DrawLine(m_this_p, m_i_draw_start, m_f_rulerX_location, m_i_draw_start, m_Y_draw_TopDiff);
+
+            ////200个小刻度
+            //for (int i = 0; i < m_i_smallkd_number; i++)
+            //{
+            //    g.DrawLine(m_this_p, m_i_draw_start + (i * m_i_smalkd * f_js_width), m_f_rulerX_location, m_i_draw_start + (i * m_i_smalkd * f_js_width), m_f_rulerX_location + 5);
+            //}
+
+
+
+
+
+
+            int i_count = 0;
+            //40个大刻度
+            for (int i = 0; i < m_i_bigkd_number; i++)
+            {
+                g.DrawLine(m_this_p, m_i_draw_start + (i * m_i_bigkd * f_js_width), m_f_rulerX_location, m_i_draw_start + (i * m_i_bigkd * f_js_width), m_f_rulerX_location + 10);
+                //每隔两刻度增长写字
+                if (i % 2 == 0)
+                {
+                    i_count++;
+                    g.DrawString((i_count - 1).ToString(), m_thisfont_bold, m_this_sb, m_i_draw_start + (i * m_i_bigkd * f_js_width) , m_f_rulerX_location + 10);
+                }
+            }
+            float max_xra = 0;
+            for (int i = 0; i < m_f_show2.Length; i++)
+            {
+                if (max_xra < m_f_show2[i])
+                {
+                    max_xra = m_f_show2[i];
+                }
+            }
+            int m_Y_Value_Count = (int)Math.Floor(max_xra / 25);
+            m_Y_Value = (uint)(m_Y_Value_Count/4) * 25;
+            if(m_Y_Value==0)
+            {
+                m_Y_Value = (uint)Math.Floor(max_xra / 2);
+            }
+            if (m_xraytopixel_multiple != 0)
+            {
+                //纵坐标
+                for (int i = 0; i < 30; i++)
+                {
+                    if (i * m_Y_Value <= max_xra)
+                    {
+                        g.DrawLine(m_this_p, m_i_draw_start, m_f_rulerX_location - (i * m_Y_Value * f_js_width), m_i_draw_start + 3, m_f_rulerX_location - (i * m_Y_Value * f_js_width));
+                        int aa = i * Convert.ToInt16(m_Y_Value);
+                        g.DrawString(aa.ToString(), m_thisfont_bold, m_this_sb, m_i_draw_start - 10 - ((aa.ToString().Length - 1) * 6), m_f_rulerX_location - (i * m_Y_Value * f_js_width) - 7);
+                    }
+                }
+            }
+
+            //补充输入文字,为了美观
+            //g.DrawString("kv", m_thisfont_bold, m_this_sb, 8, m_f_rulerX_location + 10);
+            Font m_thisfont_bold2 = new Font("微软雅黑", 11, FontStyle.Bold);
+            g.DrawString("Kev", m_thisfont_bold2, m_this_sb, (m_i_draw_end- m_i_draw_start) / 2+m_i_draw_start, m_f_rulerX_location + 23);
+            g.TranslateTransform(m_i_draw_start-45, m_f_rulerX_location-25); // 移动到绘图起始点
+            g.RotateTransform(-90); // 逆时针旋转90度
+            g.DrawString("Counts", m_thisfont_bold2, m_this_sb, 0,0);
+            g.ResetTransform();
+            #endregion
+
+            #region 绘制x-ray线的边框
+            //x-ray画线的左边线
+            g.DrawLine(m_this_p, m_i_draw_start, m_i_draw_start + m_Y_draw_TopDiff, m_i_draw_start * f_js_width, m_f_rulerX_location - 2);
+            //x-ray画线的底盘
+            //g.DrawLine(m_this_p, m_i_draw_start, m_f_rulerX_location - 2, m_i_draw_end* f_js_width, m_f_rulerX_location - 2);
+            #endregion
+
+
+            #endregion //--------------------------------------------------------------------------------------------------------
+
+            #region 绘制波浪线及线上文字--------------------------------------------------------------------------------------
+            if (m_b_show_analysisxray == true)
+            {
+                //画波浪线----第二条线
+                for (int i = 0; i < m_list_twopoint2.Count(); i++)
+                {
+                    PointF ls_pf1_2 = m_list_twopoint2[i].pf1;
+                    ls_pf1_2.X = (ls_pf1_2.X) * f_js_width+ m_i_draw_start ;
+                    PointF ls_pf2_2 = m_list_twopoint2[i].pf2;
+                    ls_pf2_2.X = (ls_pf2_2.X) * f_js_width+ m_i_draw_start ;
+
+                    g.DrawLine(m_this_p_blue, ls_pf1_2, ls_pf2_2);
+
+                    //找到最高值再输出的方式
+                    //if (list_twopoint2[i].pf2.Y < 60)
+                    //{
+                    //    g.DrawString(list_twopoint2[i].value.ToString() + "@ev", thisfont_bold, this_sb_blue, list_twopoint2[i].pf2.X + 3, list_twopoint2[i].pf2.Y);
+                    //}
+                }
+            }
+
+            #endregion //----------------------------------------------------------------------------------------------------------------
+
+            #region //绘制峰值上的线-----------------------------------------------------------------------------------------------
+            if (m_list_kmlfpoint != null)
+            {
+                for (int i = 0; i < m_list_kmlfpoint.Count(); i++)
+                {
+                    //为了让元素标签不在同一高度显示,为了美观,也是防止会重叠,所以这里计算一下
+                    int i_py = 0;//设置元素标签的偏移
+                    if (i % 2 == 1)
+                        i_py = 0;
+                    else
+                        i_py = 20;
+
+                    //绘制竖线
+                    g.DrawLine(new Pen(Color.Wheat, 0.5f), f_js_width * (m_list_kmlfpoint[i].kml_x * ((m_i_draw_end- m_i_draw_start - 4) / 20)) + m_i_draw_start, m_f_rulerX_location / 3 + i_py, f_js_width * (m_list_kmlfpoint[i].kml_x * ((m_i_draw_end - m_i_draw_start - 4) / 20) + m_i_draw_start), m_f_rulerX_location - 3);
+                    //输出文字,并将字输出到线的上面
+                    SizeF out_testsizef = g.MeasureString(m_list_kmlfpoint[i].ysm, m_thisfont);
+                    PointF ut_test_pointF = new PointF(m_mouse_point.X - (out_testsizef.Width / 2), 2);
+                    g.FillRectangle(Brushes.Goldenrod, new RectangleF(new PointF(f_js_width * ((m_list_kmlfpoint[i].kml_x * ((m_i_draw_end - m_i_draw_start - 4) / 20)) + m_i_draw_start - out_testsizef.Width / 2), m_f_rulerX_location / 3 - 20 + i_py), out_testsizef));
+                    g.DrawString(m_list_kmlfpoint[i].ysm,
+                        m_thisfont_bold,
+                        m_this_sb,
+                        new PointF(f_js_width * ((m_list_kmlfpoint[i].kml_x * ((m_i_draw_end - m_i_draw_start - 4) / 20)) + m_i_draw_start - out_testsizef.Width / 2), m_f_rulerX_location / 3 - 20 + i_py));
+
+                    if (m_list_kmlfpoint[i].lml_x != 0)
+                    {
+                        //绘制竖线
+                        g.DrawLine(new Pen(Color.Wheat, 0.5f), f_js_width * (m_list_kmlfpoint[i].lml_x * ((m_i_draw_end - m_i_draw_start - 4) / 20)) + m_i_draw_start, m_f_rulerX_location / 3 + i_py, f_js_width * (m_list_kmlfpoint[i].lml_x * ((m_i_draw_end - m_i_draw_start - 4) / 20) + m_i_draw_start), m_f_rulerX_location - 3);
+                        //输出文字,并将字输出到线的上面
+                        SizeF out_testsizef2 = g.MeasureString(m_list_kmlfpoint[i].ysm, m_thisfont);
+                        PointF ut_test_pointF2 = new PointF(m_mouse_point.X - (out_testsizef.Width / 2), 2);
+                        g.FillRectangle(Brushes.Goldenrod, new RectangleF(new PointF(f_js_width * ((m_list_kmlfpoint[i].lml_x * ((m_i_draw_end - m_i_draw_start - 4) / 20))+ m_i_draw_start - out_testsizef.Width / 2), m_f_rulerX_location / 3 - 20 + i_py), out_testsizef));
+                        g.DrawString(m_list_kmlfpoint[i].ysm,
+                            m_thisfont_bold,
+                            m_this_sb,
+                            new PointF(f_js_width * ((m_list_kmlfpoint[i].lml_x * ((m_i_draw_end - m_i_draw_start - 4) / 20)) + m_i_draw_start - out_testsizef.Width / 2), m_f_rulerX_location / 3 - 20 + i_py));
+                    }
+                }
+            }
+            #endregion 
+
+            #region 绘制鼠标移动显示的线及线上文字---------------------------------------------------------------------------------------
+            //再绘制鼠标所在位置的竖线---------------------第一条线
+            g.DrawLine(m_mousemove_p, m_mouse_point.X, m_i_draw_start, m_mouse_point.X, m_f_rulerX_location - 3);
+
+            string ls_label_str = "";
+            for (int i = 0; i < m_list_twopoint2.Count(); i++)
+            {
+                //判断要按条件进行显示,值大于200才进行显示,用循环i的位置进行判断,在不变动这些数组时,这种写法是正确的
+                if (m_analysis_xray[i] > m_f_kmlfzpd_mix)
+                {
+                    //用绘线线段,的起始点与鼠标当前位置进行对应上的话,那么就进行取kmlf值,进行显示
+                    if (Convert.ToInt32(m_list_twopoint2[i].pf1.X * f_js_width) == m_mouse_point.X+ m_i_draw_start)
+                    {
+                        ls_label_str = m_list_twopoint2[i].kmlf_value.ToString();
+                    }
+                    if (Convert.ToInt32(m_list_twopoint2[i].pf2.X * f_js_width) == m_mouse_point.X + m_i_draw_start)
+                    {
+                        ls_label_str = m_list_twopoint2[i].kmlf_value.ToString();
+                    }
+                }
+            }
+            if (ls_label_str != "")
+                ls_label_str = Convert.ToDouble(ls_label_str).ToString("0.000");//显示浮点数,为了美观
+
+            //绘制鼠标竖线上的定位文字
+            SizeF sizeF = g.MeasureString(ls_label_str, m_thisfont);
+            PointF pointF = new PointF(m_mouse_point.X - (sizeF.Width / 2), 2);
+            g.FillRectangle(Brushes.SkyBlue, new RectangleF(pointF, sizeF));
+            g.DrawString(ls_label_str, m_thisfont_bold, m_this_sb, pointF);
+            #endregion
+
+            #region //右上角输出文字设置-------------------------------------------------------------------------------------------------
+            m_i_rightdrawlabellocation_x = m_i_draw_end * f_js_width - 260;
+           
+            //国际化
+            Language lan = new Language();
+            Hashtable table = lan.GetNameTable("Control_XRayTable");
+            string str1 = table["str1"].ToString();
+            string str2 = table["str2"].ToString();
+            g.DrawString(str1, m_thisfont, m_this_sb, new PointF(m_i_rightdrawlabellocation_x, m_i_rightdrawlabellocation_y + 20));
+            //g.DrawString("高度比例尺:", m_thisfont, m_this_sb, new PointF(m_i_rightdrawlabellocation_x, m_i_rightdrawlabellocation_y + 20));
+            g.DrawString(str2, m_thisfont, m_this_sb, new PointF(m_i_rightdrawlabellocation_x, m_i_rightdrawlabellocation_y + 40));
+
+            //计算值显示,计数率
+            g.DrawString(m_xraysum2.ToString(), m_thisfont_bold, m_this_sb, new PointF(m_i_rightdrawlabellocation_x + 50, m_i_rightdrawlabellocation_y + 20));
+            //高度比例尺值显示
+            //g.DrawString(m_xraytopixel_multiple.ToString("0.0"), m_thisfont_bold, m_this_sb, new PointF(m_i_rightdrawlabellocation_x + 50, m_i_rightdrawlabellocation_y + 20));
+            
+            //show element list information,using the elementlist number to make sure width,number take width 25 growth
+
+            if (m_list_showelementinfo != null)
+            {
+                //make it 100%
+                double sumpercentage = 0;
+                for (int i = 0; i < m_list_showelementinfo.Count; i++)
+                {
+                    sumpercentage += m_list_showelementinfo[i].Percentage;
+                
+                }
+                for (int i = 0; i < m_list_showelementinfo.Count; i++)
+                {
+                    m_list_showelementinfo[i].percentageIn100 = m_list_showelementinfo[i].Percentage / sumpercentage * 100;
+
+                }
+                StringBuilder sb = new StringBuilder();
+                for (int i = 0; i < m_list_showelementinfo.Count; i++)
+                {
+                    if (i > 6&& m_list_showelementinfo[i].Percentage<0.1) break;
+                    sb.Append(m_list_showelementinfo[i].ElementName);
+                    sb.Append("(");
+                    sb.Append(m_list_showelementinfo[i].Percentage.ToString("0.00)  "));
+                }
+                sb.Append("\n");
+                sb.Append(m_ParticleInfo);
+                string str_element = sb.ToString();
+                SizeF out_testsizef = g.MeasureString(str_element, m_thisfont);
+                PointF ls_pt = new PointF(m_i_rightdrawlabellocation_x , m_i_rightdrawlabellocation_y + 42);
+                ls_pt.X = m_i_rightdrawlabellocation_x + 50;
+                g.DrawString(str_element, m_thisfont_bold, new SolidBrush(Color.Black), ls_pt);
+            }
+          
+            #endregion //------------------------------------------------------------------------------------------------------------------
+
+        }
+        #endregion
+
+        #region 鼠标移动事件
+        protected override void OnMouseMove(MouseEventArgs e)
+        {
+            //记录鼠标移动到的点,用来绘制用
+            m_mouse_point = new Point(e.X, e.Y);
+            this.Invalidate();
+        }
+        #endregion
+
+        private void label_close_Click(object sender, EventArgs e)
+        {
+            this.Visible = false;
+        }
+    }
+
+    #region 用来显示连接线封装的类
+    /// <summary>
+    /// 封装两个点的一个类
+    /// </summary>
+    [Serializable]
+    public class TwoPoint
+    {
+        public PointF pf1;
+        public PointF pf2;
+        public float value;
+        public float kmlf_value;
+    }
+
+    /// <summary>
+    /// 记录显示的KML峰值类,分别记录kml峰值的x坐标,和峰值对应的一左一右的元素名
+    /// </summary>
+    [Serializable]
+    public class KMLFPoint
+    {
+        public float kml_x;
+        public float lml_x;
+        public string ysm;
+    }
+
+    /// <summary>
+    /// show x-ray info with element list,the element information class
+    /// </summary>
+    [Serializable]
+    public class ShowElementInfo
+    {
+        public string ElementName;
+        public double Percentage;//实际能谱返回的质量百分比
+        public double dKF;//K峰,元素周期表中固定值
+        public double dLF;//L峰
+        public double percentageIn100;//归一化后的百分比
+    }
+    #endregion
+
+}

+ 62 - 0
OTSSysMgrApp/Control_XRayTable.designer.cs

@@ -0,0 +1,62 @@
+namespace OTSSysMgrApp
+{
+    partial class Control_XRayTable
+    {
+        /// <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 组件设计器生成的代码
+
+        /// <summary> 
+        /// 设计器支持所需的方法 - 不要修改
+        /// 使用代码编辑器修改此方法的内容。
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.label_close = new System.Windows.Forms.Label();
+            this.SuspendLayout();
+            // 
+            // label_close
+            // 
+            this.label_close.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.label_close.AutoSize = true;
+            this.label_close.Location = new System.Drawing.Point(990, 0);
+            this.label_close.Name = "label_close";
+            this.label_close.Size = new System.Drawing.Size(11, 12);
+            this.label_close.TabIndex = 1;
+            this.label_close.Text = "X";
+            this.label_close.Visible = false;
+            this.label_close.Click += new System.EventHandler(this.label_close_Click);
+            // 
+            // Control_XRayTable
+            // 
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
+            this.BackColor = System.Drawing.Color.White;
+            this.Controls.Add(this.label_close);
+            this.Name = "Control_XRayTable";
+            this.Size = new System.Drawing.Size(1004, 220);
+            this.Load += new System.EventHandler(this.Control_XRayTable_Load);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+        public System.Windows.Forms.Label label_close;
+    }
+}

+ 120 - 0
OTSSysMgrApp/Control_XRayTable.resx

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>