using System; using System.Collections.Generic; using System.Drawing; using System.Data; using System.Windows.Forms; namespace SpectrumSTDEditor { public partial class UXrayControl : UserControl { // 画能谱图的矩形区域 protected Rectangle m_XrayArea; protected PointF[] m_xraypointf = null; protected bool m_bShowElementLines = true; // 水平刻度分成20等分 protected const int m_iHscale = 20; protected bool m_bMouseMove = false; protected Point m_curCurssorPos; private DataTable dt = null; private DataRow dr = null; public DataRow Dr { get => dr; set => dr = value; } public DataTable Dt { get => dt; set => dt = value; } public UXrayControl() { InitializeComponent(); // 设置双缓冲 SetDoubleBufferByIsDraw(); } public void SetDoubleBufferByIsDraw() { SetStyle(ControlStyles.UserPaint, true);//没什么效果,开与关 SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景,关了闪 this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); // 双缓冲,关了闪 //上面是必须有的 SetStyle(ControlStyles.UserMouse, true);//执行自己的鼠标行为,这个打开后,在win7下鼠标操作明显改善 } private void UXrayControl_Load(object sender, EventArgs e) { } private void UXrayControl_Resize(object sender, EventArgs e) { this.RefreshCtrl(); //setControls(newx, newy, this.tabSTDStandrad.TabPages[0]); } private void UXrayControl_Paint(object sender, PaintEventArgs e) { Graphics graphic = e.Graphics; DrawSpecture(ref graphic); if (m_bMouseMove) { ShowMouseMoveInfo(m_curCurssorPos.X, m_curCurssorPos.Y, ref m_XrayArea, ref graphic); } } public void RefreshCtrl() { this.Invalidate(); Graphics graph = Graphics.FromHwnd(this.Handle); DrawSpecture(ref graph); m_bMouseMove = false; } public void DrawSpecture(ref Graphics graph) { // 设置设置能谱的区域大小 // 首先预留出刻度的大小 String strLabel = "99999"; SizeF size = graph.MeasureString(strLabel, this.Font); // 上下左右四顶点预留2个像素空白, 扣除标签的宽高 // Rectangle XrayArea = new Rectangle(); m_XrayArea.X = 2 + (int)size.Width; m_XrayArea.Y = 5; m_XrayArea.Width = this.Width - 2 - m_XrayArea.X; m_XrayArea.Height = this.Height - 2 - m_XrayArea.Y - (int)size.Height; Pen pen = new Pen(Color.FromArgb(150, Color.Black), 1); // 画矩形框 graph.DrawRectangle(pen, m_XrayArea); // 画横坐标刻度 Point point = new Point(); Point next = new Point(); Point adapt = new Point(); // 微调参数 SolidBrush brush = new SolidBrush(Color.FromArgb(255, Color.Black)); pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; for (int i = 0; i < m_iHscale; i++) { point.X = m_XrayArea.X + i * m_XrayArea.Width / m_iHscale; point.Y = m_XrayArea.Y + m_XrayArea.Height; // 画横坐标数字刻度 adapt.X = (i > 9) ? 6 : 4; adapt.Y = 2; graph.DrawString(Convert.ToString(i), this.Font, brush, new Point(point.X - adapt.X, point.Y + adapt.Y)); // 画垂直方向刻度 next.X = point.X; next.Y = m_XrayArea.Y; pen.Color = Color.FromArgb(70, Color.Black); graph.DrawLine(pen, point, next); } // 画纵坐标的刻度 int iRows = 0; int iMaxValue = 0; int iScale = GetYScale(ref iMaxValue); iRows = iMaxValue / iScale; for (int i = 1; i < iRows; i++) { point.Y = m_XrayArea.Y + m_XrayArea.Height - i * m_XrayArea.Height / iRows; point.X = m_XrayArea.X; // 画纵坐标数字刻度 adapt.X = (i * iScale >= 100) ? 22 : 16; adapt.X = (i * iScale >= 1000) ? 28 : adapt.X; adapt.Y = 6; string drawstring = Convert.ToString(iScale * i); int a1= strLabel.Length-drawstring.Length; graph.DrawString(drawstring, this.Font, brush, new Point(point.X-7 - adapt.X, point.Y +2 - adapt.Y)); // 画水平方向刻度 next.X = point.X + m_XrayArea.Width; next.Y = point.Y; graph.DrawLine(pen, point, next); } // 画能谱数据 // ShowXray(ref m_XrayArea, iMaxValue, ref graph, m_bShowElementLines); ShowXrayClr(ref m_XrayArea, iMaxValue, ref graph, m_bShowElementLines); } protected void ShowXrayClr(ref Rectangle XrayArea, int iMaxValue, ref Graphics graph, bool bShowElementLines) { ShowXray( Dr, ref XrayArea, iMaxValue, ref graph); if (bShowElementLines) { // 元素线的高度为能谱图矩形高度一半 ShowElementLines(Dr, XrayArea.Height / 2, ref XrayArea, ref graph); } if (null != Dr) { int iDelt = 0; SizeF size = graph.MeasureString("Test", this.Font); for (int i = 0; i < 1; i++) { //DataRow dr = Dt.Rows[i]; ShowXray(Dr, ref XrayArea, iMaxValue, ref graph, true); if (bShowElementLines) { iDelt = (0 == i % 2) ? (-i - 1) * (int)size.Height : i * (int)size.Height; ShowElementLines(dr, iDelt + XrayArea.Height / 2, ref XrayArea, ref graph); } } } } protected int[] bytesToInt(byte[] src, int offset) { int[] values = new int[src.Length / 4]; for (int i = 0; i < values.Length; i++) { values[i] = BitConverter.ToInt32(src, offset); offset += 4; } return values; } public void ShowXray(DataRow dr, ref Rectangle XrayArea, int iMaxValue, ref Graphics graph, bool bComp = false) { if (null != dr) { int[] SPEC= bytesToInt((byte[])dr["SPEC"], 0); int iXrayDataLen = SPEC.Length; if (null == m_xraypointf) { m_xraypointf = new PointF[iXrayDataLen]; } for (int i = 0; i < iXrayDataLen; i++) { m_xraypointf[i].X = XrayArea.X + i * XrayArea.Width / iXrayDataLen; m_xraypointf[i].Y = XrayArea.Y + XrayArea.Height - SPEC[i] * XrayArea.Height / iMaxValue; } int ColorValue = 0; if (!dr["Color"].ToString().Equals("")) { ColorValue = Convert.ToInt32(dr["Color"]); } if (bComp) { Pen pen = new Pen(Color.FromArgb(150, Color.FromArgb(ColorValue % 256, (ColorValue >> 8) % 256, (ColorValue >> 16) % 256)), 1); graph.DrawPolygon(pen, m_xraypointf); } else { SolidBrush brush = new SolidBrush(Color.FromArgb(150, Color.FromArgb(ColorValue % 256, (ColorValue >> 8) % 256, (ColorValue >> 16) % 256))); graph.FillPolygon(brush, m_xraypointf); } } } protected void ShowElementLines(DataRow dr, int iLineHeight, ref Rectangle XrayArea, ref Graphics graph) { if (null == dr) { return; } //double dEnergy = 0; String str = "Test"; SizeF size = graph.MeasureString(str, this.Font); // 判断元素线高度的合法性 iLineHeight = (iLineHeight > size.Height) ? iLineHeight : (int)size.Height; iLineHeight = ((iLineHeight + (int)size.Height) > XrayArea.Height) ? (XrayArea.Height - (int)size.Height) : iLineHeight; //PointF point = new PointF(); //PointF next = new PointF(); //RectangleF rect = new RectangleF(); Pen pen = new Pen(Color.FromArgb(255, 150, 100, 50), 1); int ColorValue = 0; if (!dr["Color"].ToString().Equals("")) { ColorValue = Convert.ToInt32(dr["Color"]); } SolidBrush brush = new SolidBrush(Color.FromArgb(255, Color.FromArgb(ColorValue % 256, (ColorValue >> 8) % 256, (ColorValue >> 16) % 256))); //for (int i = 0; i < 1; i++) //{ // //CElementClr elementclr = stdmineralclr.GetElement(i); // str = "0";//elementclr.GetName(); // size = graph.MeasureString(str, this.Font); // dEnergy = 2.3;//elementclr.GetEnergyValueK(); // point.X = XrayArea.X + (float)dEnergy * XrayArea.Width / m_iHscale; // point.Y = XrayArea.Y + XrayArea.Height; // next.X = point.X; // next.Y = (0 == i % 2) ? (point.Y - iLineHeight) : (point.Y - iLineHeight + 2 + (int)size.Height); // // 画线 // graph.DrawLine(pen, point, next); // // 画矩形框 // rect.X = next.X - size.Width / 2; // rect.Y = next.Y - size.Height; // rect.Width = size.Width; // rect.Height = size.Height; // brush.Color = Color.FromArgb(255, Color.FromArgb(ColorValue % 256, (ColorValue >> 8) % 256, (ColorValue >> 16) % 256)); // graph.FillRectangle(brush, rect); // // 画字符串 // brush.Color = Color.FromArgb(255, Color.Black); // graph.DrawString(str, this.Font, brush, rect.X, rect.Y); //} } protected void ShowMouseMoveInfo(int ix, int iy, ref Rectangle XrayArea, ref Graphics graph) { // 判断坐标是否在矩形框区域内, 如果不在, 则退出 if (ix < XrayArea.X || ix > XrayArea.X + XrayArea.Width || iy < XrayArea.Y || iy > XrayArea.Y + XrayArea.Height) { return; } float fpos = 0; PointF point = new PointF(); PointF next = new PointF(); Pen pen = new Pen(Color.FromArgb(150, Color.Black), 1); SolidBrush brush = new SolidBrush(Color.FromArgb(255, Color.FromArgb(255, 0, 0))); fpos = (ix - XrayArea.X) * m_iHscale / (float)XrayArea.Width; SizeF size = graph.MeasureString(fpos.ToString(), this.Font); // 画竖线 point.X = ix; point.Y = XrayArea.Y + XrayArea.Height; next.X = point.X; next.Y = XrayArea.Y + (int)size.Height; graph.DrawLine(pen, point, next); // 显示坐标位置 graph.DrawString(fpos.ToString(), this.Font, brush, ix - (int)(size.Width / 2), XrayArea.Y+20); // 获取当前位置的元素 // List liststr = CElement.GetAllElementsEnergy(fpos, 0.1f); List liststr = new List(); //CElementClr.GetAllElementsEnergyK(fpos, 0.1f, ref liststr); brush.Color = Color.FromArgb(255, Color.Blue); for (int i = 0; i < liststr.Count; i++) { size = graph.MeasureString(liststr[i], this.Font); point.X = ('-' == liststr[i][0]) ? (ix - (size.Width + 2)) : ix; point.Y = (XrayArea.Y + size.Height) + i * (size.Height + 2); graph.DrawString(liststr[i], this.Font, brush, point.X, point.Y); } } public void SetElementLines(bool bShowElementLines) { m_bShowElementLines = bShowElementLines; } protected override void OnMouseMove(MouseEventArgs e) { //// if (null == m_CurSelMineral && //// (null == m_ListCompMineral || //// 0 == m_ListCompMineral.Count())) //if (null == m_CurSelSTDMineralClr && // (null == m_ListCompMineralClr || // 0 == m_ListCompMineralClr.Count())) //{ // return; //} m_bMouseMove = true; m_curCurssorPos.X = e.X; m_curCurssorPos.Y = e.Y; this.Invalidate(); // this.OnPaint(new PaintEventArgs(this.CreateGraphics(), new Rectangle(new Point(0, 0), this.Size))); } // 返回值是刻度的精度, iRows表示行数 protected int GetYScale(ref int iMaxValue) { int iMaxXray = 0; int iMaxXray1 = 0; int iMaxXray2 = 0; int iBaseScale = 20; // 最小基础刻度20 int iScale = 20; // 待返回的刻度值 int iBaseMaxValue = 100; // 基础最大值100 int iTimes = 0; int iLeft = 0; iMaxXray1 = GetMaxXray(Dr); iMaxXray2 = 0;//GetMaxXrayClr(); iMaxXray = (iMaxXray1 > iMaxXray2) ? iMaxXray1 : iMaxXray2; // 设计需求: 0 <= iMaxXray < 500(iScale: 50, iMaxValue: 250或者500) // 设计需求: 500 <= iMaxXray < 1000(iScale: 100, iMaxValue: 750或者1000) // 设计需求: 1000 <= iMaxXray < 1500(iScale: 150, iMaxValue: 1250或者1500) // 设计需求: 1500 <= iMaxXray < 2000(iScale: 200, iMaxValue: 1750或者2000) // 以此类推 // iMaxXray = 9000;// 测试代码, 可以删除 iTimes = iMaxXray / iBaseMaxValue; iLeft = iMaxXray % iBaseMaxValue; iScale = iBaseScale + iBaseScale * (iTimes / 2); iMaxValue = iBaseMaxValue + iBaseMaxValue * iTimes; // 因为iScale * (iMaxValue / iScale) <= iMaxValue, 所以如果 iMaxXray > iScale * (iMaxValue / iScale) 刻度就会不够,导致bug if (iScale * (iMaxValue / iScale) < iMaxXray) { iMaxValue = iMaxValue + iBaseMaxValue; } return iScale; } protected int GetMaxXray(DataRow dr) { if (null == dr) { return 0; } int iMaxXray = 0; int iXrayLen = 0; int[] SPEC = bytesToInt((byte[])dr["SPEC"], 0); iXrayLen = SPEC.Length; for (int i = 0; i < iXrayLen; i++) { if (SPEC[i] > iMaxXray) { iMaxXray = SPEC[i]; } } return iMaxXray; } protected int GetMaxXrayClr() { if (null == Dr) { return 0; } int iMaxXray = 0; int iXray = 0; for (int i = 0; i < Dt.Rows.Count; i++) { DataRow dr = Dt.Rows[i]; iXray = GetMaxXray(dr); if (iXray > iMaxXray) { iMaxXray = iXray; } } return iMaxXray; } private void setTag(Control cons) { foreach (Control con in cons.Controls) { con.Tag = con.Width + ":" + con.Height + ":" + con.Left + ":" + con.Top + ":" + con.Font.Size; if (con.Controls.Count > 0) setTag(con); } } private void setControls(float newx, float newy, Control cons) { foreach (Control con in cons.Controls) { if (con.Name == "Form_ZeroElementRules") { continue; } if (false) { } else { string[] mytag = con.Tag.ToString().Split(':'); float a = Convert.ToSingle(mytag[0]) * newx; con.Width = (int)a; a = Convert.ToSingle(mytag[1]) * newy; con.Height = (int)(a); a = Convert.ToSingle(mytag[2]) * newx; con.Left = (int)(a); a = Convert.ToSingle(mytag[3]) * newy; con.Top = (int)(a); Single currentSize; if (con.GetType().ToString() == "System.Windows.Forms.Label") { currentSize = Convert.ToSingle(mytag[4]) * ((newx + newy) / 2); //currentSize = 6f; } else { if (Math.Max(newx, newy) < 1) { currentSize = Convert.ToSingle(mytag[4]) * 1; } else { currentSize = Convert.ToSingle(mytag[4]) * Math.Max(newx, newy); } } con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit); if (con.Controls.Count > 0) { setControls(newx, newy, con); } } } } } }