UXrayControl.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Data;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using System.Collections;
  11. namespace OTSPartA_STDEditor
  12. {
  13. public partial class UXrayControl : UserControl
  14. {
  15. // 画能谱图的矩形区域
  16. protected Rectangle m_XrayArea;
  17. protected PointF[] m_xraypointf = null;
  18. protected bool m_bShowElementLines = true;
  19. // 水平刻度分成20等分
  20. protected const int m_iHscale = 20;
  21. protected bool m_bMouseMove = false;
  22. protected Point m_curCurssorPos;
  23. private DataTable dt = null;
  24. private DataRow dr = null;
  25. public DataRow Dr { get => dr; set => dr = value; }
  26. public DataTable Dt { get => dt; set => dt = value; }
  27. public UXrayControl()
  28. {
  29. InitializeComponent();
  30. // 设置双缓冲
  31. SetDoubleBufferByIsDraw();
  32. }
  33. public void SetDoubleBufferByIsDraw()
  34. {
  35. SetStyle(ControlStyles.UserPaint, true);//没什么效果,开与关
  36. SetStyle(ControlStyles.AllPaintingInWmPaint, true); // 禁止擦除背景,关了闪
  37. this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); // 双缓冲,关了闪
  38. //上面是必须有的
  39. SetStyle(ControlStyles.UserMouse, true);//执行自己的鼠标行为,这个打开后,在win7下鼠标操作明显改善
  40. }
  41. private void UXrayControl_Load(object sender, EventArgs e)
  42. {
  43. }
  44. private void UXrayControl_Resize(object sender, EventArgs e)
  45. {
  46. this.RefreshCtrl();
  47. }
  48. private void UXrayControl_Paint(object sender, PaintEventArgs e)
  49. {
  50. Graphics graphic = e.Graphics;
  51. DrawSpecture(ref graphic);
  52. if (m_bMouseMove)
  53. {
  54. ShowMouseMoveInfo(m_curCurssorPos.X, m_curCurssorPos.Y, ref m_XrayArea, ref graphic);
  55. }
  56. }
  57. public void RefreshCtrl()
  58. {
  59. this.Invalidate();
  60. Graphics graph = Graphics.FromHwnd(this.Handle);
  61. DrawSpecture(ref graph);
  62. m_bMouseMove = false;
  63. }
  64. public void DrawSpecture(ref Graphics graph)
  65. {
  66. // 设置设置能谱的区域大小
  67. // 首先预留出刻度的大小
  68. String strLabel = "9999";
  69. SizeF size = graph.MeasureString(strLabel, this.Font);
  70. // 上下左右四顶点预留2个像素空白, 扣除标签的宽高
  71. // Rectangle XrayArea = new Rectangle();
  72. m_XrayArea.X = 2 + (int)size.Width;
  73. m_XrayArea.Y = 2;
  74. m_XrayArea.Width = this.Width - 2 - m_XrayArea.X;
  75. m_XrayArea.Height = this.Height - 2 - m_XrayArea.Y - (int)size.Height;
  76. Pen pen = new Pen(Color.FromArgb(150, Color.Black), 1);
  77. // 画矩形框
  78. graph.DrawRectangle(pen, m_XrayArea);
  79. // 画横坐标刻度
  80. Point point = new Point();
  81. Point next = new Point();
  82. Point adapt = new Point(); // 微调参数
  83. SolidBrush brush = new SolidBrush(Color.FromArgb(255, Color.Black));
  84. pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
  85. for (int i = 0; i < m_iHscale; i++)
  86. {
  87. point.X = m_XrayArea.X + i * m_XrayArea.Width / m_iHscale;
  88. point.Y = m_XrayArea.Y + m_XrayArea.Height;
  89. // 画横坐标数字刻度
  90. adapt.X = (i > 9) ? 6 : 4;
  91. adapt.Y = 2;
  92. graph.DrawString(Convert.ToString(i), this.Font, brush, new Point(point.X - adapt.X, point.Y + adapt.Y));
  93. // 画垂直方向刻度
  94. next.X = point.X;
  95. next.Y = m_XrayArea.Y;
  96. pen.Color = Color.FromArgb(70, Color.Black);
  97. graph.DrawLine(pen, point, next);
  98. }
  99. // 画纵坐标的刻度
  100. int iRows = 0;
  101. int iMaxValue = 0;
  102. int iScale = GetYScale(ref iMaxValue);
  103. iRows = iMaxValue / iScale;
  104. for (int i = 1; i < iRows; i++)
  105. {
  106. point.Y = m_XrayArea.Y + m_XrayArea.Height - i * m_XrayArea.Height / iRows;
  107. point.X = m_XrayArea.X;
  108. // 画纵坐标数字刻度
  109. adapt.X = (i * iScale >= 100) ? 22 : 16;
  110. adapt.X = (i * iScale >= 1000) ? 28 : adapt.X;
  111. adapt.Y = 6;
  112. graph.DrawString(Convert.ToString(iScale * i), this.Font, brush, new Point(point.X - adapt.X, point.Y - adapt.Y));
  113. // 画水平方向刻度
  114. next.X = point.X + m_XrayArea.Width;
  115. next.Y = point.Y;
  116. graph.DrawLine(pen, point, next);
  117. }
  118. // 画能谱数据
  119. // ShowXray(ref m_XrayArea, iMaxValue, ref graph, m_bShowElementLines);
  120. ShowXrayClr(ref m_XrayArea, iMaxValue, ref graph, m_bShowElementLines);
  121. }
  122. protected void ShowXrayClr(ref Rectangle XrayArea, int iMaxValue, ref Graphics graph, bool bShowElementLines)
  123. {
  124. ShowXray( Dr, ref XrayArea, iMaxValue, ref graph);
  125. if (bShowElementLines)
  126. {
  127. // 元素线的高度为能谱图矩形高度一半
  128. ShowElementLines(Dr, XrayArea.Height / 2, ref XrayArea, ref graph);
  129. }
  130. if (null != Dr)
  131. {
  132. int iDelt = 0;
  133. SizeF size = graph.MeasureString("Test", this.Font);
  134. for (int i = 0; i < 1; i++)
  135. {
  136. //DataRow dr = Dt.Rows[i];
  137. ShowXray(Dr, ref XrayArea, iMaxValue, ref graph, true);
  138. if (bShowElementLines)
  139. {
  140. iDelt = (0 == i % 2) ? (-i - 1) * (int)size.Height : i * (int)size.Height;
  141. ShowElementLines(dr, iDelt + XrayArea.Height / 2, ref XrayArea, ref graph);
  142. }
  143. }
  144. }
  145. }
  146. protected int[] bytesToInt(byte[] src, int offset)
  147. {
  148. int[] values = new int[src.Length / 4];
  149. for (int i = 0; i < values.Length; i++)
  150. {
  151. values[i] = BitConverter.ToInt32(src, offset);
  152. offset += 4;
  153. }
  154. return values;
  155. }
  156. public void ShowXray(DataRow dr, ref Rectangle XrayArea, int iMaxValue, ref Graphics graph, bool bComp = false)
  157. {
  158. if (null != dr)
  159. {
  160. int[] SPEC= bytesToInt((byte[])dr["SPEC"], 0);
  161. int iXrayDataLen = SPEC.Length;
  162. if (null == m_xraypointf)
  163. {
  164. m_xraypointf = new PointF[iXrayDataLen];
  165. }
  166. for (int i = 0; i < iXrayDataLen; i++)
  167. {
  168. m_xraypointf[i].X = XrayArea.X + i * XrayArea.Width / iXrayDataLen;
  169. m_xraypointf[i].Y = XrayArea.Y + XrayArea.Height - SPEC[i] * XrayArea.Height / iMaxValue;
  170. }
  171. int ColorValue = 0;
  172. if (!dr["Color"].ToString().Equals(""))
  173. {
  174. ColorValue = Convert.ToInt32(dr["Color"]);
  175. }
  176. if (bComp)
  177. {
  178. Pen pen = new Pen(Color.FromArgb(150, Color.FromArgb(ColorValue % 256, (ColorValue >> 8) % 256, (ColorValue >> 16) % 256)), 1);
  179. graph.DrawPolygon(pen, m_xraypointf);
  180. }
  181. else
  182. {
  183. SolidBrush brush = new SolidBrush(Color.FromArgb(150, Color.FromArgb(ColorValue % 256, (ColorValue >> 8) % 256, (ColorValue >> 16) % 256)));
  184. graph.FillPolygon(brush, m_xraypointf);
  185. }
  186. }
  187. }
  188. protected void ShowElementLines(DataRow dr, int iLineHeight, ref Rectangle XrayArea, ref Graphics graph)
  189. {
  190. if (null == dr)
  191. {
  192. return;
  193. }
  194. //double dEnergy = 0;
  195. String str = "Test";
  196. SizeF size = graph.MeasureString(str, this.Font);
  197. // 判断元素线高度的合法性
  198. iLineHeight = (iLineHeight > size.Height) ? iLineHeight : (int)size.Height;
  199. iLineHeight = ((iLineHeight + (int)size.Height) > XrayArea.Height) ? (XrayArea.Height - (int)size.Height) : iLineHeight;
  200. //PointF point = new PointF();
  201. //PointF next = new PointF();
  202. //RectangleF rect = new RectangleF();
  203. Pen pen = new Pen(Color.FromArgb(255, 150, 100, 50), 1);
  204. int ColorValue = 0;
  205. if (!dr["Color"].ToString().Equals(""))
  206. {
  207. ColorValue = Convert.ToInt32(dr["Color"]);
  208. }
  209. SolidBrush brush = new SolidBrush(Color.FromArgb(255, Color.FromArgb(ColorValue % 256, (ColorValue >> 8) % 256, (ColorValue >> 16) % 256)));
  210. //for (int i = 0; i < 1; i++)
  211. //{
  212. // //CElementClr elementclr = stdmineralclr.GetElement(i);
  213. // str = "0";//elementclr.GetName();
  214. // size = graph.MeasureString(str, this.Font);
  215. // dEnergy = 2.3;//elementclr.GetEnergyValueK();
  216. // point.X = XrayArea.X + (float)dEnergy * XrayArea.Width / m_iHscale;
  217. // point.Y = XrayArea.Y + XrayArea.Height;
  218. // next.X = point.X;
  219. // next.Y = (0 == i % 2) ? (point.Y - iLineHeight) : (point.Y - iLineHeight + 2 + (int)size.Height);
  220. // // 画线
  221. // graph.DrawLine(pen, point, next);
  222. // // 画矩形框
  223. // rect.X = next.X - size.Width / 2;
  224. // rect.Y = next.Y - size.Height;
  225. // rect.Width = size.Width;
  226. // rect.Height = size.Height;
  227. // brush.Color = Color.FromArgb(255, Color.FromArgb(ColorValue % 256, (ColorValue >> 8) % 256, (ColorValue >> 16) % 256));
  228. // graph.FillRectangle(brush, rect);
  229. // // 画字符串
  230. // brush.Color = Color.FromArgb(255, Color.Black);
  231. // graph.DrawString(str, this.Font, brush, rect.X, rect.Y);
  232. //}
  233. }
  234. protected void ShowMouseMoveInfo(int ix, int iy, ref Rectangle XrayArea, ref Graphics graph)
  235. {
  236. // 判断坐标是否在矩形框区域内, 如果不在, 则退出
  237. if (ix < XrayArea.X ||
  238. ix > XrayArea.X + XrayArea.Width ||
  239. iy < XrayArea.Y ||
  240. iy > XrayArea.Y + XrayArea.Height)
  241. {
  242. return;
  243. }
  244. float fpos = 0;
  245. PointF point = new PointF();
  246. PointF next = new PointF();
  247. Pen pen = new Pen(Color.FromArgb(150, Color.Black), 1);
  248. SolidBrush brush = new SolidBrush(Color.FromArgb(255, Color.FromArgb(255, 0, 0)));
  249. fpos = (ix - XrayArea.X) * m_iHscale / (float)XrayArea.Width;
  250. SizeF size = graph.MeasureString(fpos.ToString(), this.Font);
  251. // 画竖线
  252. point.X = ix;
  253. point.Y = XrayArea.Y + XrayArea.Height;
  254. next.X = point.X;
  255. next.Y = XrayArea.Y + (int)size.Height;
  256. graph.DrawLine(pen, point, next);
  257. // 显示坐标位置
  258. graph.DrawString(fpos.ToString(), this.Font, brush, ix - (int)(size.Width / 2), XrayArea.Y+20);
  259. // 获取当前位置的元素
  260. // List<String> liststr = CElement.GetAllElementsEnergy(fpos, 0.1f);
  261. List<String> liststr = new List<string>();
  262. //CElementClr.GetAllElementsEnergyK(fpos, 0.1f, ref liststr);
  263. brush.Color = Color.FromArgb(255, Color.Blue);
  264. for (int i = 0; i < liststr.Count; i++)
  265. {
  266. size = graph.MeasureString(liststr[i], this.Font);
  267. point.X = ('-' == liststr[i][0]) ? (ix - (size.Width + 2)) : ix;
  268. point.Y = (XrayArea.Y + size.Height) + i * (size.Height + 2);
  269. graph.DrawString(liststr[i], this.Font, brush, point.X, point.Y);
  270. }
  271. }
  272. public void SetElementLines(bool bShowElementLines)
  273. {
  274. m_bShowElementLines = bShowElementLines;
  275. }
  276. protected override void OnMouseMove(MouseEventArgs e)
  277. {
  278. //// if (null == m_CurSelMineral &&
  279. //// (null == m_ListCompMineral ||
  280. //// 0 == m_ListCompMineral.Count()))
  281. //if (null == m_CurSelSTDMineralClr &&
  282. // (null == m_ListCompMineralClr ||
  283. // 0 == m_ListCompMineralClr.Count()))
  284. //{
  285. // return;
  286. //}
  287. m_bMouseMove = true;
  288. m_curCurssorPos.X = e.X;
  289. m_curCurssorPos.Y = e.Y;
  290. this.Invalidate();
  291. // this.OnPaint(new PaintEventArgs(this.CreateGraphics(), new Rectangle(new Point(0, 0), this.Size)));
  292. }
  293. // 返回值是刻度的精度, iRows表示行数
  294. protected int GetYScale(ref int iMaxValue)
  295. {
  296. int iMaxXray = 0;
  297. int iMaxXray1 = 0;
  298. int iMaxXray2 = 0;
  299. int iBaseScale = 20; // 最小基础刻度20
  300. int iScale = 20; // 待返回的刻度值
  301. int iBaseMaxValue = 100; // 基础最大值100
  302. int iTimes = 0;
  303. int iLeft = 0;
  304. iMaxXray1 = GetMaxXray(Dr);
  305. iMaxXray2 = 0;//GetMaxXrayClr();
  306. iMaxXray = (iMaxXray1 > iMaxXray2) ? iMaxXray1 : iMaxXray2;
  307. // 设计需求: 0 <= iMaxXray < 500(iScale: 50, iMaxValue: 250或者500)
  308. // 设计需求: 500 <= iMaxXray < 1000(iScale: 100, iMaxValue: 750或者1000)
  309. // 设计需求: 1000 <= iMaxXray < 1500(iScale: 150, iMaxValue: 1250或者1500)
  310. // 设计需求: 1500 <= iMaxXray < 2000(iScale: 200, iMaxValue: 1750或者2000)
  311. // 以此类推
  312. // iMaxXray = 9000;// 测试代码, 可以删除
  313. iTimes = iMaxXray / iBaseMaxValue;
  314. iLeft = iMaxXray % iBaseMaxValue;
  315. iScale = iBaseScale + iBaseScale * (iTimes / 2);
  316. iMaxValue = iBaseMaxValue + iBaseMaxValue * iTimes;
  317. // 因为iScale * (iMaxValue / iScale) <= iMaxValue, 所以如果 iMaxXray > iScale * (iMaxValue / iScale) 刻度就会不够,导致bug
  318. if (iScale * (iMaxValue / iScale) < iMaxXray)
  319. {
  320. iMaxValue = iMaxValue + iBaseMaxValue;
  321. }
  322. return iScale;
  323. }
  324. protected int GetMaxXray(DataRow dr)
  325. {
  326. if (null == dr)
  327. {
  328. return 0;
  329. }
  330. int iMaxXray = 0;
  331. int iXrayLen = 0;
  332. int[] SPEC = bytesToInt((byte[])dr["SPEC"], 0);
  333. iXrayLen = SPEC.Length;
  334. for (int i = 0; i < iXrayLen; i++)
  335. {
  336. if (SPEC[i] > iMaxXray)
  337. {
  338. iMaxXray = SPEC[i];
  339. }
  340. }
  341. return iMaxXray;
  342. }
  343. protected int GetMaxXrayClr()
  344. {
  345. if (null == Dr)
  346. {
  347. return 0;
  348. }
  349. int iMaxXray = 0;
  350. int iXray = 0;
  351. for (int i = 0; i < Dt.Rows.Count; i++)
  352. {
  353. DataRow dr = Dt.Rows[i];
  354. iXray = GetMaxXray(dr);
  355. if (iXray > iMaxXray)
  356. {
  357. iMaxXray = iXray;
  358. }
  359. }
  360. return iMaxXray;
  361. }
  362. }
  363. }