using OTSCommon.DBOperate; using OTSCommon.DBOperate.Model; using OTSIncAReportApp; using OTSIncAReportApp._1_UI.Control_Grids.ParticlesGridDevidePage; using OTSIncAReportApp._2_CommonFunction.CommonClass; using OTSIncAReportApp._3_ServiceCenter.DataOperation.DataAccess; using OTSIncAReportApp.DataOperation.DataAccess; using OTSIncAReportApp.OTSRstMgrFunction; using OTSIncAReportApp.SysMgrTools; using OTSIncAReportGraph.Class; using OTSIncAReportGraph.Controls; using OTSIncAReportGraph.OTSIncAReportGraphFuncation; using OTSIncAReportGrids.OTSIncAReportGridsFuncation; using OTSIncAReportMailInterface; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Data.SQLite; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; using System.Threading; using System.Windows.Forms; using static OTSDataType.otsdataconst; namespace OTSIncAReportGrids { public partial class ParticlesGridDevidePage : UserControl { #region 变量定义 private ParticlesGridDevidePageShowConfig m_particlesGridDevidePageShowConfig = null; //设置模拟数据表 public DataTable m_dt = new DataTable(); //底层操作类 private SEMAndEDSOperate m_OTSIncAReportGridsFun = null; //进度条窗体 public Frm_UserProgress m_frm_userprogress; //移动SEM到指定位置发生线程 private Thread m_mythread; //记录线程是否已经运行完成的状态 private bool m_mythread_state = false; //导出图像文件的路径 private string m_imagefilepath = ""; //显示元素列表 public List m_list_elementscolname = null; //单个数据源所拥有的列数,这里保存下来,供导出模块使用 public int m_oneresult_columncount = 0; private OTSImageDisHelp m_ReportFun = null; public OTSImageDisHelp ReportFun { get => m_ReportFun; set => m_ReportFun = value; } /// /// 选择颗粒缓存表 /// private List Particleslist_selecttodisplay = new List(); //多个数据源,每个数据源拥有的列数,这里保存下来,供分组使用 public List m_list_oneresult_columncount; //国际化 private Language lan; public Hashtable table; //测量结果 public ResultFile result = null; private frmReportConditionChoose m_condition; private FieldData fieldData; private DataTable particlesAll; private DataTable particlesFilter; public ParticleData Particledata; public UserSTDDbAccess userSTDDb; public FieldImage fldImgAccess; private DataTable userSTDDbData; List elementTypeSort; private readonly NLog.Logger log = NLog.LogManager.GetCurrentClassLogger(); private enum SelItem { analyticalParticle = 0, otherParticles = 1, MergeParticles = 2, allParticles = 3 } #region 分页器相关 #region 分页字段和属性 private string condition = ""; public string FileName = null; private int pageIndex = 1; /// /// 当前页面 /// public virtual int PageIndex { get { return pageIndex; } set { pageIndex = value; } } private int pageSize = 20; /// /// 每页记录数 /// public virtual int PageSize { get { return pageSize; } set { pageSize = value; } } private int recordCount = 0; /// /// 总记录数 /// public virtual int RecordCount { get { return recordCount; } set { recordCount = value; } } private int pageCount = 0; /// /// 总页数 /// public int PageCount { get { pageCount = GetPageCount(); return pageCount; } } /// /// 计算总页数 /// /// private int GetPageCount() { if (PageSize <= 0) { return 0; } return (RecordCount + PageSize - 1) / PageSize; } #endregion private frmReportApp m_ReportApp; #endregion #endregion #region UI层方法 #region 初始化 public ParticlesGridDevidePage(frmReportApp ReportApp) { m_ReportApp = ReportApp; m_condition = ReportApp.m_conditionChoose; string sou = m_condition.m_CurrentConditions[OTSIncAReportApp.OTSSampleReportInfo.OTS_REPORT_PROP_GRID_ITEMS.DATA_SOURCE].itemDisplayVal.ToString(); if (sou.Contains("+")) { MessageBox.Show("This function does not support multiple samples!"); result = m_ReportApp.m_rstDataMgr.ResultFilesList[0]; } else { result = m_ReportApp.m_rstDataMgr.ResultFilesList[m_ReportApp.m_conditionChoose.m_conditionData.GetComboDownListIndexByItemName(OTSIncAReportApp.OTSSampleReportInfo.OTS_REPORT_PROP_GRID_ITEMS.DATA_SOURCE)]; } ReportFun = new OTSImageDisHelp(result); //设置窗体的双缓冲,以保证大数据时拖动不卡 this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true); this.UpdateStyles(); InitializeComponent(); //利用反射设置DataGridView的双缓冲 Type dgvType = this.dgV_ParticlesDevidePage.GetType(); PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); pi?.SetValue(this.dgV_ParticlesDevidePage, true, null); this.control_XRayTable1 = new Control_XRayTable(null); this.control_XRayTable1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(180)))), ((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(255))))); this.control_XRayTable1.Dock = System.Windows.Forms.DockStyle.Bottom; this.control_XRayTable1.GBInfoStr = ""; this.control_XRayTable1.GoodChineseName = ""; this.control_XRayTable1.MaterialName = ""; this.control_XRayTable1.Location = new System.Drawing.Point(0, 400); this.control_XRayTable1.Name = "control_XRayTable1"; this.control_XRayTable1.ShowAnalysisXray = true; this.control_XRayTable1.ShowSearchXray = false; this.control_XRayTable1.Size = new System.Drawing.Size(1004, 200); this.control_XRayTable1.STDName = ""; this.control_XRayTable1.Visible = false; this.control_XRayTable1.label_close.Visible = true; this.Controls.Add(this.control_XRayTable1); } private bool Init() { if (result == null) { return false; } try { lan = new Language(this); table = lan.GetNameTable(this.Name); m_mythread_state = false; m_mythread = new Thread(new ParameterizedThreadStart(ControlThread_GO)); fieldData = new FieldData(result.FilePath); Particledata = new ParticleData(result.FilePath); fldImgAccess = new FieldImage(result.FilePath); var systype = m_ReportApp.m_RptConfigFile.Systype; if (systype == OTS_SysType_ID.TCCleannessA || systype == OTS_SysType_ID.BatteryCleannessA) { string str_STDDbName = result.GetSTDName(); userSTDDb = new UserSTDDbAccess(str_STDDbName, result.FilePath + "\\"); userSTDDbData = userSTDDb.GetSqlHelper() != null ? userSTDDb.GetSubAttributeFromDatabase() : null; } //初始化底层操作类 m_OTSIncAReportGridsFun = new SEMAndEDSOperate(); return true; } catch (Exception ex) { log.Error(ex.ToString()); return false; } } private void ParticlesGridDevidePage_Load(object sender, EventArgs e) { if (!Init()) { return; } ProgressStart(); if (!UpdateDataGrid()) { return; } InitializePageSizeComboBox(); InitializeTypeTextBox(); dgV_ParticlesDevidePage.Focus(); } private Dictionary InitializeTable(ref string str_ElementsColName) { dgV_ParticlesDevidePage.Rows.Clear(); dgV_ParticlesDevidePage.Columns.Clear(); var startFun = m_ReportApp.m_RptConfigFile.Systype; string str_DefaultComputedColName = ""; str_ElementsColName = ""; DataSet ds = XMLoperate.GetXmlData(Application.StartupPath + RptConfigFile.m_ReportMgrParamFile, "XMLData"); DataTable dt = ds.Tables["Member"]; foreach (DataRow element in dt.Rows) { string regName = element["RegName"].ToString(); if (regName == "DefaultComputedColName") { str_DefaultComputedColName = element["strValue"].ToString(); } else if (regName == "ElementsColName") { str_ElementsColName = element["strValue"].ToString(); } } string[] strs = str_DefaultComputedColName.Split(','); var keyValues = new Dictionary { ["rowid"] = table["str4"].ToString(), ["TypeName"] = table["str6"].ToString(), ["ParticleImage"] = table["str5"].ToString(), ["FieldId"] = "FieldId", ["ParticleId"] = "ParticleId", ["SEMPosX"] = "SEMPosX", ["SEMPosY"] = "SEMPosY" }; foreach (string str in strs) { switch (str) { case "ParticleCoordinate": keyValues["AbPosX"] = "PosX"; keyValues["AbPosY"] = "PosY"; break; case "Area": keyValues["Area"] = table["str21"].ToString(); break; case "EquivalentCircleDiameter": keyValues["Equivalent"] = table["str22"].ToString(); break; case "MaxDiameter": keyValues["DMAX"] = table["str23"].ToString(); break; case "MinDiameter": keyValues["DMIN"] = table["str24"].ToString(); break; case "DiameterRatio": keyValues["DiameterRatio"] = table["str25"].ToString(); break; case "FerretDiameter": keyValues["DFERET"] = table["str26"].ToString(); break; case "PERP": keyValues["DPERP"] = table["str27"].ToString(); break; case "PERI": keyValues["PERIMETER"] = table["str28"].ToString(); break; case "INSCR": keyValues["DINSCR"] = table["str29"].ToString(); break; case "MEAN": keyValues["DMEAN"] = table["str30"].ToString(); break; case "ELONG": keyValues["DELONG"] = table["str31"].ToString(); break; case "ASPECT_ELONG": keyValues["ASPECT_ELONG"] = table["str32"].ToString(); break; case "Orientation": keyValues["ORIENTATION"] = table["str33"].ToString(); break; case "XRayDataCount": keyValues["XRayDataCount"] = "XRay计数"; break; } if (startFun == OTS_SysType_ID.TCCleannessA || startFun == OTS_SysType_ID.BatteryCleannessA) { switch (str) { case "Hardness": keyValues["Hardness"] = table["str34"].ToString(); break; case "Density": keyValues["Density"] = table["str35"].ToString(); break; case "Electrical_conductivity": keyValues["Electrical_conductivity"] = table["str36"].ToString(); break; } } } keyValues["Element"] = "Element"; return keyValues; } private void InitializePageSizeComboBox() { cbB_PageSize.Items.AddRange(new object[] { "20", "100", "500", "1000", "5000", "All" }); cbB_PageSize.SelectedIndex = 0; } private void InitializeTypeTextBox() { DataTable classificationTable = GetClassificationOfAllParticles(); if (classificationTable?.Rows.Count > 0) { tbx_Type.Text = string.Join("$", classificationTable.AsEnumerable() .Select(row => row["TypeName"].ToString())); } } // 新增:为 userSTDDbData 建立索引以加速查找 private Dictionary BuildUserStdLookup() { var dict = new Dictionary(); if (userSTDDbData == null) return dict; foreach (DataRow r in userSTDDbData.Rows) { var key = Convert.ToString(r["STDId"]); if (!dict.ContainsKey(key)) dict.Add(key, r); } return dict; } private void InitializeGridViewColumns(Dictionary keyValues) { dgV_ParticlesDevidePage.Rows.Clear(); dgV_ParticlesDevidePage.Columns.Clear(); foreach (var kvp in keyValues) { if (kvp.Key == "ParticleImage") { var iconColumn = new DataGridViewImageColumn { Name = kvp.Key, HeaderText = kvp.Value }; dgV_ParticlesDevidePage.Columns.Add(iconColumn); } else if (kvp.Key != "Element") { dgV_ParticlesDevidePage.Columns.Add(kvp.Key, kvp.Value); if (IsNumericColumn(kvp.Key)) { int id = dgV_ParticlesDevidePage.Columns.Count; dgV_ParticlesDevidePage.Columns[id - 1].Tag = "NumericType"; } } } } #endregion #region 数据加载 private DataTable GetParticleDataBySelection(int selection) { switch (selection) { case (int)SelItem.analyticalParticle: return Particledata.GetInfoForPartucleDevidePage_analyticalParticle(condition); case (int)SelItem.otherParticles: return Particledata.GetInfoForPartucleDevidePage_otherParticle(condition); case (int)SelItem.MergeParticles: return Particledata.GetInfoForPartucleDevidePage_mergeParticles(condition); case (int)SelItem.allParticles: return Particledata.GetInfoForPartucleDevidePage_allParticles(condition); default: return new DataTable(); } } private bool UpdateDataGrid() { int sel = m_ReportApp.m_conditionChoose.m_conditionData .GetComboDownListIndexByItemName(OTSIncAReportApp.OTSSampleReportInfo.OTS_REPORT_PROP_GRID_ITEMS.PARTICE_LIST); particlesAll = GetParticleDataBySelection(sel); if (particlesAll == null) { log.Error("There is an exception in the data of the database!"); CloseProgressIfNeeded(); return false; } // 添加必要列 particlesAll.Columns.Add("Hardness"); particlesAll.Columns.Add("Density"); particlesAll.Columns.Add("Electrical_conductivity"); // 使用字典索引 userSTDDbData,避免对每行使用 DataTable.Select(性能瓶颈) var userStdLookup = BuildUserStdLookup(); UpdateHardnessDensityData(userStdLookup); btn_Sel.Enabled = true; DataTable elementchemistry = Particledata.GetElementChemistry(); var elemIndex = BuildElementChemistryIndex(elementchemistry); UpdateElementData(elemIndex); particlesAll.Columns.Add("XRayDataCount"); DataTable XRayData = Particledata.GetXRayData(); var xrayIndex = BuildXRayDataIndex(XRayData); UpdateXRayDataCount(xrayIndex); return true; } private void UpdateHardnessDensityData(Dictionary userStdLookup) { string emptyValue = ""; for (int i = 0; i < particlesAll.Rows.Count; i++) { string key = Convert.ToString(particlesAll.Rows[i]["TypeId"]); if (userSTDDbData != null && userStdLookup.TryGetValue(key, out var dr)) { particlesAll.Rows[i]["Hardness"] = dr["Hardness"].ToString(); particlesAll.Rows[i]["Density"] = dr["Density"].ToString(); particlesAll.Rows[i]["Electrical_conductivity"] = dr["Electrical_conductivity"].ToString(); } else { particlesAll.Rows[i]["Hardness"] = emptyValue; particlesAll.Rows[i]["Density"] = emptyValue; particlesAll.Rows[i]["Electrical_conductivity"] = emptyValue; } } } private Dictionary> BuildElementChemistryIndex(DataTable elementchemistry) { var elemIndex = new Dictionary>(); foreach (DataRow er in elementchemistry.Rows) { string key = $"XRayId = {er["XRayId"]} and fieldid = {er["fieldid"]}"; if (!elemIndex.TryGetValue(key, out var list)) { list = new List(); elemIndex[key] = list; } list.Add(er); } return elemIndex; } private void UpdateElementData(Dictionary> elemIndex) { for (int i = 0; i < particlesAll.Rows.Count; i++) { string key = $"XRayId = {particlesAll.Rows[i]["particleId"]} and fieldid = {particlesAll.Rows[i]["fieldid"]}"; string concatenatedString = ""; if (elemIndex.TryGetValue(key, out var drList)) { concatenatedString = string.Join(";", drList.Select(dr => $"{dr["name"]}-{dr["Percentage"]}")); } particlesAll.Rows[i]["Element"] = concatenatedString; } } private Dictionary BuildXRayDataIndex(DataTable XRayData) { var xrayIndex = new Dictionary(); foreach (DataRow xr in XRayData.Rows) { if (xr.ItemArray.Length >= 3 && xr[2] is byte[] b) { string key = $" XrayIndex= {xr[0]} and fieldid = {xr[1]}"; if (!xrayIndex.ContainsKey(key)) { xrayIndex[key] = b; } } } return xrayIndex; } private void UpdateXRayDataCount(Dictionary xrayIndex) { for (int i = 0; i < particlesAll.Rows.Count; i++) { string subParticleString = Convert.ToString(particlesAll.Rows[i]["SubParticles"]); if (string.IsNullOrEmpty(subParticleString)) { particlesAll.Rows[i]["XRayDataCount"] = 0; string str = $" XrayIndex= {particlesAll.Rows[i]["particleId"]} and fieldid = {particlesAll.Rows[i]["fieldid"]}"; if (xrayIndex.TryGetValue(str, out var bytes)) { uint xraycount = 0; int len = bytes.Length / 4; for (int j = 0; j < len; j++) { xraycount += BitConverter.ToUInt32(bytes, j * 4); } particlesAll.Rows[i]["XRayDataCount"] = xraycount; } } else { particlesAll.Rows[i]["XRayDataCount"] = 0; DataRow dgvr = particlesAll.Rows[i]; uint[] Analysis_xray = new uint[2000]; Particledata.GetXrayByParticleTagIDAndFieldID_ForMergeParticle( Convert.ToInt32(dgvr["particleId"]), Convert.ToInt32(dgvr["fieldid"]), out Analysis_xray); uint xraycount = 0; for (int j = 0; j < Analysis_xray.Length; j++) { xraycount += Analysis_xray[j]; } particlesAll.Rows[i]["XRayDataCount"] = xraycount; } } } private void RefreshGridView() { dgV_ParticlesDevidePage.Visible = false; if (m_frm_userprogress == null || m_frm_userprogress.IsDisposed) { ProgressStart(); } string str_ElementsColName = null; Dictionary keyValues = InitializeTable(ref str_ElementsColName); // 减少 UI 重绘开销 dgV_ParticlesDevidePage.SuspendLayout(); try { InitializeGridViewColumns(keyValues); if (PageSize <= 0) { PageSize = particlesAll?.Rows.Count ?? 0; } if (particlesAll == null) { return; } UpdatePageData(); InitializeElementColumns(str_ElementsColName); LoadParticleData(keyValues); } finally { dgV_ParticlesDevidePage.ResumeLayout(); dgV_ParticlesDevidePage.Visible = true; CloseProgress(); } } private void UpdatePageData() { RecordCount = particlesAll.Rows.Count; particlesFilter = particlesAll.Clone(); int startRow = (PageIndex - 1) * pageSize; int endRow = Math.Min(startRow + pageSize, RecordCount); for (int fi = startRow; fi < endRow; fi++) { particlesFilter.ImportRow(particlesAll.Rows[fi]); } } private void InitializeElementColumns(string str_ElementsColName) { elementTypeSort = string.IsNullOrEmpty(str_ElementsColName) ? new List() : str_ElementsColName.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Distinct() .ToList(); foreach (string element in elementTypeSort) { dgV_ParticlesDevidePage.Columns.Add(element, element); int id = dgV_ParticlesDevidePage.Columns.Count; dgV_ParticlesDevidePage.Columns[id - 1].Tag = "NumericType"; } } private void LoadParticleData(Dictionary keyValues) { if (particlesFilter?.Rows.Count == 0) return; double progressStep = particlesFilter.Rows.Count > 0 ? 95.0 / particlesFilter.Rows.Count : 95.0; string filePath = Path.Combine(result.FilePath, "FIELD_FILES"); // 把 fieldpics 缓存提升到循环外,避免对同一 field 多次磁盘读取 var fieldPics = new Dictionary(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < particlesFilter.Rows.Count; i++) { if (i % 10 == 0 && m_frm_userprogress != null && !m_frm_userprogress.IsDisposed) m_frm_userprogress.SetProgressValueAndText((int)(progressStep * i), "loading.."); int add_rowindex = dgV_ParticlesDevidePage.Rows.Add(); dgV_ParticlesDevidePage.Rows[add_rowindex].Cells[0].Value = (pageSize * (PageIndex - 1) + add_rowindex + 1).ToString(); LoadParticleRowData(i, add_rowindex, keyValues, fieldPics); } } private void ProcessColumnData(int rowIndex, int gridRowIndex, int columnIndex, string columnName, Dictionary fieldPics) { switch (columnName) { case "ParticleImage": ProcessParticleImageColumn(rowIndex, gridRowIndex, columnIndex, fieldPics); break; case "DiameterRatio": ProcessDiameterRatioColumn(rowIndex, gridRowIndex, columnIndex); break; case "ASPECT_ELONG": ProcessAspectElongColumn(rowIndex, gridRowIndex, columnIndex); break; case "Element": ProcessElementColumn(rowIndex, gridRowIndex); break; case "TypeName": ProcessTypeNameColumn(rowIndex, gridRowIndex, columnIndex); break; case "Equivalent": ProcessEquivalentColumn(rowIndex, gridRowIndex, columnIndex); break; case "Hardness": ProcessHardnessColumn(rowIndex, gridRowIndex, columnIndex); break; case "AbPosX": ProcessAbPosColumn(rowIndex, gridRowIndex); break; default: break; } AdjustTheFormatOfTheUnitValues(rowIndex, gridRowIndex, columnIndex, columnName); } private void ProcessParticleImageColumn(int rowIndex, int gridRowIndex, int columnIndex, Dictionary fieldPics) { string subParticleString = Convert.ToString(particlesFilter.Rows[rowIndex]["SubParticles"]); dgV_ParticlesDevidePage.Rows[gridRowIndex].Height = 70; dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells[columnIndex].Style.BackColor = Color.Azure; Bitmap bmap = null; if (!string.IsNullOrEmpty(subParticleString) && subParticleString != "IsSubParticle") { bmap = CreateMergedParticleImage(subParticleString); } else if (subParticleString != "IsSubParticle") { bmap = CreateSingleParticleImage(rowIndex, fieldPics); } bmap.Tag = new List() { particlesFilter.Rows[rowIndex]["fieldid"].ToString(), particlesFilter.Rows[rowIndex]["ParticleId"].ToString() }; dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells[columnIndex].Value = bmap; } private void LoadParticleRowData(int rowIndex, int gridRowIndex, Dictionary keyValues, Dictionary fieldPics) { foreach (var kvp in keyValues) { int columnIndex = dgV_ParticlesDevidePage.Columns.IndexOf(dgV_ParticlesDevidePage.Columns[kvp.Key]); //if (columnIndex < 0) continue; ProcessColumnData(rowIndex, gridRowIndex, columnIndex, kvp.Key, fieldPics); } } private void ProcessElementColumn(int rowIndex, int gridRowIndex) { List elementtemp = new List(elementTypeSort); string[] strcbo = particlesFilter.Rows[rowIndex]["Element"].ToString().Split(';'); for (int j = 0; j < strcbo.Length; j++) { if (elementTypeSort.Count == 0) { break; } string[] str = strcbo[j].Split('-'); if (elementTypeSort.Contains(str[0])) { dgV_ParticlesDevidePage.Rows[rowIndex].Cells[str[0].ToString()].Value = Math.Round(double.Parse(str[1]), 2).ToString(); } elementtemp.Remove(str[0].ToString()); } foreach (var ele in elementtemp) { dgV_ParticlesDevidePage.Rows[rowIndex].Cells[ele].Value = "0"; } } private void ProcessTypeNameColumn(int rowIndex, int gridRowIndex, int columnIndex) { if (particlesFilter.Rows[rowIndex]["TypeId"].ToString() == "9") { dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells[columnIndex].Value = "Not Identified"; } } private void ProcessEquivalentColumn(int rowIndex, int gridRowIndex, int columnIndex) { double dSize = Convert.ToDouble(particlesFilter.Rows[rowIndex]["Area"]); double diameter = Math.Sqrt(dSize / Math.PI) * 2; dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells[columnIndex].Value = Math.Round(diameter, 2); } private void ProcessHardnessColumn(int rowIndex, int gridRowIndex, int columnIndex) { string hardnessColor = ChangeHardnessColor(Convert.ToString(particlesFilter.Rows[rowIndex]["Hardness"])); if (hardnessColor == "#FF0000") { dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells[columnIndex].Style.ForeColor = Color.Red; } } private void ProcessAbPosColumn(int rowIndex, int gridRowIndex) { Point semPos = new Point( Convert.ToInt32(particlesFilter.Rows[rowIndex]["SEMPosX"]), Convert.ToInt32(particlesFilter.Rows[rowIndex]["SEMPosY"])); Point particlePos = new Point( Convert.ToInt32(particlesFilter.Rows[rowIndex]["PosX"]), Convert.ToInt32(particlesFilter.Rows[rowIndex]["PosY"])); Point point = CalculateParticleCenterPosition(result, semPos, particlePos); dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells["AbPosX"].Value = point.X; dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells["AbPosY"].Value = point.Y; } private void ProcessDiameterRatioColumn(int rowIndex, int gridRowIndex, int columnIndex) { double dmax = Convert.ToDouble(particlesFilter.Rows[rowIndex]["DMAX"]); double dmin = Convert.ToDouble(particlesFilter.Rows[rowIndex]["DMIN"]); double ratio = dmin != 0 ? dmax / dmin : 0; dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells[columnIndex].Value = Math.Round(ratio, 2); } private void ProcessAspectElongColumn(int rowIndex, int gridRowIndex, int columnIndex) { double delong = Convert.ToDouble(particlesFilter.Rows[rowIndex]["DELONG"]); double dmean = Convert.ToDouble(particlesFilter.Rows[rowIndex]["DMEAN"]); double ratio = dmean != 0 ? delong / dmean : 0; dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells[columnIndex].Value = Math.Round(ratio, 2); } /// /// 页面控件呈现 /// private void DrawControl(bool callEvent) { RefreshGridView(); lblTotalCount.Text = RecordCount.ToString(); lblPageCount.Text = PageCount.ToString(); txtPageNum.Text = PageIndex.ToString(); SetFormCtrEnabled(); if (PageCount == 0 || PageCount == 1) //有且仅有一页 { lnkFirst.Enabled = false; lnkPrev.Enabled = false; lnkNext.Enabled = false; lnkLast.Enabled = false; btnGo.Enabled = false; } else if (PageIndex == 1) //第一页 { lnkFirst.Enabled = false; lnkPrev.Enabled = false; } else if (PageIndex == PageCount) //最后一页 { lnkNext.Enabled = false; lnkLast.Enabled = false; } } private void DisplayData() { if (cbB_PageSize.SelectedItem?.ToString() == "All"){pageSize = -1;} else if (int.TryParse(cbB_PageSize.SelectedItem?.ToString(), out int parsedSize)){pageSize = parsedSize;} lnkFirst_Click(null, null); SetDataGridViewStyle(); } #endregion #region 健壮性判断 private bool IsNumericColumn(string columnName) { string[] numericColumns = { "Area", "EquivalentCircleDiameter", "MaxDiameter", "MinDiameter", "DiameterRatio", "FerretDiameter", "PERP", "PERI", "INSCR", "MEAN", "ELONG", "ASPECT_ELONG", "Orientation" }; return numericColumns.Contains(columnName); } /// /// 判断条件输入 前<后 /// /// /// /// private bool CompareInput(string min, string max) { if (!double.TryParse(max, out double dmax)) { if (!int.TryParse(max, out int imax)) return false; dmax = imax; } if (!double.TryParse(min, out double dmin)) { if (!int.TryParse(min, out int imin)) return false; dmin = imin; } return dmin <= dmax; } private bool ValidateAndAddCondition(string value, string fieldName, string operatorSymbol) { if (string.IsNullOrWhiteSpace(value)) return true; if (double.TryParse(value, out double dnum) && dnum >= 0) { condition += $" and {fieldName} {operatorSymbol} {value}"; return true; } if (int.TryParse(value, out int inum) && inum >= 0) { condition += $" and {fieldName} {operatorSymbol} {value}"; return true; } ShowErrorMessage("str10"); return false; } private bool ValidateIntegerField(string value, string fieldName) { if (string.IsNullOrWhiteSpace(value)) return true; if (int.TryParse(value, out _)) { condition += $" and {fieldName} = {value}"; return true; } ShowErrorMessage("str10"); return false; } private bool ProcessECDConditions() { if (!string.IsNullOrWhiteSpace(tbx_ECDMin.Text)) { if (double.TryParse(tbx_ECDMin.Text, out double dnum) && dnum >= 0) { double area = Math.PI * dnum / 2 * dnum / 2; condition += $" and Area > {area}"; } else if (int.TryParse(tbx_ECDMin.Text, out int inum) && inum >= 0) { double area = Math.PI * inum / 2 * inum / 2; condition += $" and Area > {area}"; } else { ShowErrorMessage("str10"); return false; } } if (!string.IsNullOrWhiteSpace(tbx_ECDMax.Text)) { if (double.TryParse(tbx_ECDMax.Text, out double dnum) && dnum >= 0) { double area = Math.PI * dnum / 2 * dnum / 2; condition += $" and Area < {area}"; } else if (int.TryParse(tbx_ECDMax.Text, out int inum) && inum >= 0) { double area = Math.PI * inum / 2 * inum / 2; condition += $" and Area < {area}"; } else { ShowErrorMessage("str10"); return false; } } if (!string.IsNullOrWhiteSpace(tbx_ECDMin.Text) && !string.IsNullOrWhiteSpace(tbx_ECDMax.Text)) { if (!CompareInput(tbx_ECDMin.Text, tbx_ECDMax.Text)) { ShowErrorMessage("str11"); return false; } } return true; } private void ShowErrorMessage(string resourceKey) { MessageBox.Show(table?[resourceKey].ToString() ?? "输入错误"); } #endregion #region 数据处理 private Bitmap CreateMergedParticleImage(string subParticleString) { double pix = result.GetPixelSize(); int width = result.GetImageWidth(); int height = result.GetImageHeight(); string vs = "," + subParticleString.Replace(':', '-') + ","; DataTable dataTable = Particledata.GetParticleAllForBig(vs); var bmap1 = fldImgAccess.GetBitmapForMergedParticle(subParticleString, pix, height, width, dataTable); int cellWidth = dgV_ParticlesDevidePage.Columns["ParticleImage"].Width - 20; int cellHeight = dgV_ParticlesDevidePage.Rows[0].Height - 20; var ratioX = (double)cellWidth / bmap1.Width; var ratioY = (double)cellWidth / bmap1.Height; var ratio = Math.Min(ratioX, ratioY); var bmap = fldImgAccess.ScaleImageProportional(bmap1, ratio); return bmap; } private Bitmap CreateSingleParticleImage(int rowIndex, Dictionary fieldPics) { string fid = Convert.ToString(particlesFilter.Rows[rowIndex]["fieldid"]); if (!fieldPics.ContainsKey(fid)) { string imagePath = "Field" + fid + ".bmp"; fieldPics[fid] = fldImgAccess.ReadImageFile(imagePath); } Rectangle rectangle = new Rectangle() { X = Convert.ToInt32(particlesFilter.Rows[rowIndex]["RectLeft"]), Y = Convert.ToInt32(particlesFilter.Rows[rowIndex]["RectTop"]), Width = Convert.ToInt32(particlesFilter.Rows[rowIndex]["RectWidth"]), Height = Convert.ToInt32(particlesFilter.Rows[rowIndex]["RectHeight"]) }; var src = fieldPics[fid]; if (src != null) { var bmap1 = fldImgAccess.CapturePic(src, rectangle); int cellWidth = dgV_ParticlesDevidePage.Columns["ParticleImage"].Width - 20; int cellHeight = dgV_ParticlesDevidePage.Rows[0].Height - 20; var ratioX = (double)cellWidth / bmap1.Width; var ratioY = (double)cellWidth / bmap1.Height; var ratio = Math.Min(ratioX, ratioY); var bmap = fldImgAccess.ScaleImageProportional(bmap1, ratio); return bmap; } return null; } /// /// 计算颗粒中心的电镜坐标 /// /// /// /// /// public static Point CalculateParticleCenterPosition(ResultFile resultFile, Point SEMPos, Point ParticlePos) { Point point = new Point(); float scanFieldSizeX = resultFile.GetScanFieldSizeX(); string leftOrRight = resultFile.GetXAxisDir(); string downOrUp = resultFile.GetYAxisDir(); float scanFieldSizeY = resultFile.GetScanFieldSizeY(); float pixelSize = resultFile.GetPixelSize(); if (leftOrRight == "RIGHT_TOWARD") { point.X = (int)(SEMPos.X - scanFieldSizeX / 2 + ParticlePos.X * pixelSize); } else { point.X = (int)(SEMPos.X + scanFieldSizeX / 2 - ParticlePos.X * pixelSize); } if (downOrUp == "UP_TOWARD") { point.Y = (int)(SEMPos.Y + scanFieldSizeY / 2 - ParticlePos.Y * pixelSize); } else { point.Y = (int)(SEMPos.Y - scanFieldSizeY / 2 + ParticlePos.Y * pixelSize); } return point; } /// /// 复制选择区域 /// public void CopySelected() { //复制选择区域 object clipboardContent = dgV_ParticlesDevidePage.GetClipboardContent(); if (clipboardContent != null) Clipboard.SetDataObject(dgV_ParticlesDevidePage.GetClipboardContent()); } /// /// 复制所有 /// public void CopyAll() { dgV_ParticlesDevidePage.SelectAll(); Clipboard.SetDataObject(dgV_ParticlesDevidePage.GetClipboardContent()); } /// /// 以图像的方式将GridView进行截图 /// public void CopyImage() { int width = dgV_ParticlesDevidePage.Columns.GetColumnsWidth(DataGridViewElementStates.Visible) + 2; int height = this.Height; using (Bitmap image = new Bitmap(width, height)) { dgV_ParticlesDevidePage.DrawToBitmap(image, new Rectangle(0, 0, width, height)); Clipboard.SetImage(image); } } private void dgV_ParticlesDevidePage_SortCompare(object sender, DataGridViewSortCompareEventArgs e) { //排序中 if (e.Column.Tag?.ToString() == "NumericType") { if (double.TryParse(e.CellValue1?.ToString(), out double val1) && double.TryParse(e.CellValue2?.ToString(), out double val2)) { e.SortResult = val1.CompareTo(val2); e.Handled = true; } } } private string ChangeHardnessColor(string hardness) { if (string.IsNullOrEmpty(hardness)) return ""; string str = System.Text.RegularExpressions.Regex.Replace(hardness, @"[^\d.\d]", ""); return double.TryParse(str, out double hd) && hd >= 1000 ? "#FF0000" : ""; } private void SaveParticleslist_select() { ParticleData fielddata = new ParticleData(result.FilePath); List particles = fielddata.GetParticleAllList(); Particleslist_selecttodisplay.Clear(); for (int l = 0; l < dgV_ParticlesDevidePage.SelectedRows.Count; l++) { //从事先加载的Bitmap对象的Tag中取出List DataGridViewRow dgvr = dgV_ParticlesDevidePage.SelectedRows[l]; string str = " particleId= " + dgvr.Cells["particleId"].Value.ToString() + " and fieldid = " + dgvr.Cells["fieldid"].Value.ToString(); DataRow[] drs = particlesFilter.Select(str); DataRow row = drs[0]; string subParticleString = row["SubParticles"].ToString(); int i_ls_fieldid = -1; int i_ls_particleid = -1; if (subParticleString != "" && subParticleString != null) { string[] SubParticlesstrG = subParticleString.Split(','); if (SubParticlesstrG.Length > 1) { string fieldid1 = SubParticlesstrG[0].Split(':')[0]; string pid1 = SubParticlesstrG[0].Split(':')[1]; i_ls_fieldid = Convert.ToInt32(fieldid1); i_ls_particleid = Convert.ToInt32(pid1); } } else { Bitmap ls_bp = (Bitmap)dgvr.Cells[2].Value; List list_str = (List)ls_bp.Tag; if (list_str != null) { i_ls_fieldid = Convert.ToInt32(list_str[0]); i_ls_particleid = Convert.ToInt32(list_str[1]); } } foreach (Particle item in particles) { if (i_ls_fieldid == item.FieldId && i_ls_particleid == item.ParticleId) { Particleslist_selecttodisplay.Add(item); break; } } } } public List GetParticleslist_select() { return Particleslist_selecttodisplay; } /// /// 获取所有颗粒的分类信息 /// /// public DataTable GetClassificationOfAllParticles() { string str = ""; int sel = m_ReportApp.m_conditionChoose.m_conditionData.GetComboDownListIndexByItemName(OTSIncAReportApp.OTSSampleReportInfo.OTS_REPORT_PROP_GRID_ITEMS.PARTICE_LIST); if (sel == (int)SelItem.analyticalParticle) { str = "where xrayid > -1 and typeid !=9 and typeid !=-1 and typeid !=4 and SubParticles is not 'IsSubParticle' "; } else if (sel == (int)SelItem.otherParticles) { str = "where SubParticles is not 'IsSubParticle'and(typeid =9 or typeid =-1 or typeid =4)"; } else { } DataTable table = Particledata.GetClassificationOfAllParticles(str); return table; } #endregion #region 格式处理 private void AdjustTheFormatOfTheUnitValues(int rowIndex, int gridRowIndex, int columnIndex, string columnName) { if (!particlesFilter.Columns.Contains(columnName)) return; if (columnName== "Element") return; var cellValue = particlesFilter.Rows[rowIndex][columnName]; if (cellValue == null) return; if (double.TryParse(cellValue.ToString(), out double num)) { dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells[columnIndex].Value = Math.Round(num, 2); } else { dgV_ParticlesDevidePage.Rows[gridRowIndex].Cells[columnIndex].Value = cellValue.ToString(); } } private void SetFormCtrEnabled() { lnkFirst.Enabled = true; lnkPrev.Enabled = true; lnkNext.Enabled = true; lnkLast.Enabled = true; btnGo.Enabled = true; } /// /// 设置DataGridView样式 /// private void SetDataGridViewStyle() { //用户不能调整标题的高度 dgV_ParticlesDevidePage.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing; //用户不能调整 行高 dgV_ParticlesDevidePage.AllowUserToResizeRows = false; //点击选择整行 dgV_ParticlesDevidePage.SelectionMode = DataGridViewSelectionMode.FullRowSelect; //居中显示 DataGridViewCellStyle dataGridViewCellStyle1 = new DataGridViewCellStyle { Alignment = DataGridViewContentAlignment.MiddleCenter }; dgV_ParticlesDevidePage.DefaultCellStyle = dataGridViewCellStyle1; dgV_ParticlesDevidePage.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; //再次重覆禁用拖动表头高度,居然有效果了 dgV_ParticlesDevidePage.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing; //设置grid可以复制 dgV_ParticlesDevidePage.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText; //设置每列的宽度 if (dgV_ParticlesDevidePage.Columns.Count > 0) { dgV_ParticlesDevidePage.Columns[0].Width = 40; //第一列序号的宽度设置一下吧,要不太丑 if (dgV_ParticlesDevidePage.Columns.Count > 1) dgV_ParticlesDevidePage.Columns[1].Width = 150; } //设置序号列不排序 if (dgV_ParticlesDevidePage.Columns.Count > 0) { dgV_ParticlesDevidePage.Columns[0].SortMode = DataGridViewColumnSortMode.NotSortable; if (dgV_ParticlesDevidePage.Columns.Count > 1) dgV_ParticlesDevidePage.Columns[1].SortMode = DataGridViewColumnSortMode.NotSortable; } //设置序号列不可以设置宽度 if (dgV_ParticlesDevidePage.Columns.Count > 0) dgV_ParticlesDevidePage.Columns[0].Resizable = DataGridViewTriState.False; dgV_ParticlesDevidePage.RowsDefaultCellStyle.BackColor = Color.Azure; } #endregion #region 进度条 private void CloseProgress() { //加载完成设置鼠标为默认 this.Cursor = Cursors.Default; string str8 = table?["str8"].ToString() ?? "完成"; if (m_frm_userprogress != null && !m_frm_userprogress.IsDisposed) { m_frm_userprogress.SetProgressValueAndText(100, str8); m_frm_userprogress.Close(); } } private void CloseProgressIfNeeded() { this.Cursor = Cursors.Default; if (m_frm_userprogress != null && !m_frm_userprogress.IsDisposed) m_frm_userprogress.Close(); } private void ProgressStart() { #region 加载显示进度条部份 this.Cursor = Cursors.WaitCursor; m_frm_userprogress = new Frm_UserProgress(); Form ls_main_form = this.ParentForm?.ParentForm;//取出父窗体 if (ls_main_form == null) { m_frm_userprogress.Visible = false; } else { m_frm_userprogress.Width = (int)(MyPrimaryScreen.DESKTOP.Width / MyPrimaryScreen.ScaleX * 0.9); m_frm_userprogress.Location = new Point( ls_main_form.Location.X + 80, ls_main_form.Location.Y + (int)(MyPrimaryScreen.DESKTOP.Height / MyPrimaryScreen.ScaleX) / 2); m_frm_userprogress.Show(); m_frm_userprogress.SetProgressValueAndText(0, "Loading data of particles..."); } #endregion } #endregion #region UI事件 private void ToolStripMenuItem1_Click(object sender, EventArgs e) { //复制整个表 CopyAll(); } private void ToolStripMenuItem2_Click(object sender, EventArgs e) { //复制选择区域 CopySelected(); } private void toolStripMenuItem4_Click(object sender, EventArgs e) { //对gridview进行截图 CopyImage(); } private void ToolStripMenuItem5_Click(object sender, EventArgs e) { /*注意:多数据源情况下,只获取第一个数据源的选择了多行的情况下,只获取最后一个选择行的,没有办法,这是为了符合李阳博士提出的要求*/ //先获取鼠标所选择的行里的颗粒的FieldID和ParticleID if (dgV_ParticlesDevidePage.SelectedRows.Count == 0) return; string i_ls_fieldid = ""; string i_ls_particleid = ""; int cou = dgV_ParticlesDevidePage.SelectedRows.Count; DataGridViewRow dgvr = dgV_ParticlesDevidePage.SelectedRows[cou - 1]; if (dgvr.Cells[2].Value is Bitmap ls_bp && ls_bp.Tag is List list_str) { i_ls_fieldid = list_str[0]; i_ls_particleid = list_str[1]; } ParticleData particleData = new ParticleData(result.FilePath); Particle particle = particleData.GetParticleByFidAndPid(i_ls_fieldid, i_ls_particleid); //取得Field的Position,然后执行线程移动SEM到当前Field的位置 if (m_mythread == null) return; if (m_mythread.ThreadState == ThreadState.Running || m_mythread.ThreadState == ThreadState.WaitSleepJoin) { return; } if (m_mythread.ThreadState == ThreadState.Stopped) { m_mythread = new Thread(new ParameterizedThreadStart(ControlThread_GO)); } Point point = CalculateParticleCenterPosition(result, new Point(particle.SEMPosX, particle.SEMPosY), new Point(particle.PosX, particle.PosY)); //改为线程调用,先判断线程状态 m_mythread.Start(point); } private void ToolStripMenuItem_exportimagefile_Click(object sender, EventArgs e) { using (FolderBrowserDialog fbd = new FolderBrowserDialog()) { if (fbd.ShowDialog() != DialogResult.OK) return; m_imagefilepath = fbd.SelectedPath; for (int i = 0; i < dgV_ParticlesDevidePage.Rows.Count; i++) { if (dgV_ParticlesDevidePage.Rows[i].Cells[2].Value is Bitmap ls_bp) { string filePath = Path.Combine(m_imagefilepath, $"{(i + 1)}.jpg"); ls_bp.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg); } } string str9 = table?["str9"].ToString() ?? "导出完成,共导出 "; MessageBox.Show(str9 + dgV_ParticlesDevidePage.Rows.Count.ToString()); } } private void testToolStripMenuItem_Click(object sender, EventArgs e) { // Empty method placeholder } private void btn_Sel_Click(object sender, EventArgs e) { condition = ""; if (!ValidateAndAddCondition(tBx_AreaMin.Text, "Area", ">")) return; if (!ValidateAndAddCondition(Tbx_AreaMax.Text, "Area", "<")) return; if (!string.IsNullOrWhiteSpace(tBx_AreaMin.Text) && !string.IsNullOrWhiteSpace(Tbx_AreaMax.Text)) { if (!CompareInput(tBx_AreaMin.Text, Tbx_AreaMax.Text)) { ShowErrorMessage("str11"); return; } } if (!ValidateAndAddCondition(tbx_DmaxMin.Text, "DMAX", ">")) return; if (!ValidateAndAddCondition(tbx_DmaxMax.Text, "DMAX", "<")) return; if (!string.IsNullOrWhiteSpace(tbx_DmaxMin.Text) && !string.IsNullOrWhiteSpace(tbx_DmaxMax.Text)) { if (!CompareInput(tbx_DmaxMin.Text, tbx_DmaxMax.Text)) { ShowErrorMessage("str11"); return; } } if (!ValidateIntegerField(tB_FieldId.Text, "FieldId")) return; if (!ValidateIntegerField(tB_ParticleId.Text, "ParticleId")) return; if (!ValidateAndAddCondition(tbx_DferretMin.Text, "DFERET", ">")) return; if (!ValidateAndAddCondition(tbx_DferretMax.Text, "DFERET", "<")) return; if (!string.IsNullOrWhiteSpace(tbx_DferretMin.Text) && !string.IsNullOrWhiteSpace(tbx_DferretMax.Text)) { if (!CompareInput(tbx_DferretMin.Text, tbx_DferretMax.Text)) { ShowErrorMessage("str11"); return; } } if (!ProcessECDConditions()) return; if (!string.IsNullOrWhiteSpace(tbx_Type.Text)) { string[] types = tbx_Type.Text.Split('$'); condition += " and ("; for (int i = 0; i < types.Length; i++) { if (i == 0) { condition += $" TypeName = '{types[i]}'"; } else { condition += $" or TypeName = '{types[i]}'"; } } condition += ")"; } if (m_frm_userprogress?.IsDisposed != false) { ProgressStart(); } UpdateDataGrid(); lnkFirst_Click(null, null); SetDataGridViewStyle(); } /// /// 分页属性改变了。 /// private void txtPageSize_TextChanged(object sender, EventArgs e) { if (!int.TryParse(txtPageNum.Text.Trim(), out int num) || num <= 0) { txtPageNum.Text = "1"; } } private void lnkFirst_Click(object sender, EventArgs e) { PageIndex = 1; DrawControl(true); } private void lnkPrev_Click(object sender, EventArgs e) { PageIndex = Math.Max(1, PageIndex - 1); DrawControl(true); } private void lnkNext_Click(object sender, EventArgs e) { PageIndex = Math.Min(PageCount, PageIndex + 1); DrawControl(true); } private void lnkLast_Click(object sender, EventArgs e) { PageIndex = PageCount; DrawControl(true); } /// /// 跳转 /// /// /// private void btnGo_Click(object sender, EventArgs e) { if (int.TryParse(txtPageNum.Text.Trim(), out int num) && num > 0) { if (num > PageCount) { num = PageCount; txtPageNum.Text = PageCount.ToString(); } PageIndex = num; DrawControl(true); } } private void cbB_PageSize_SelectedIndexChanged(object sender, EventArgs e) { DisplayData(); } private void EXCELToolStripMenuItem_Click(object sender, EventArgs e) { using (var sfd = new OTSIncAReportApp._1_UI.Control_Grids.SpectrumExportConfirmation()) { if (sfd.ShowDialog() != DialogResult.OK) return; if (m_frm_userprogress?.IsDisposed != false) { ProgressStart(); } try { ExcelExport excelExport=new ExcelExport(dgV_ParticlesDevidePage,particlesFilter,Particledata, m_frm_userprogress); excelExport.ExportToExcel(sfd); } finally { //加载完成,关闭进度条 if (m_frm_userprogress != null && !m_frm_userprogress.IsDisposed) { m_frm_userprogress.SetProgressValueAndText(100, "导出完成"); m_frm_userprogress.Close(); } Cursor = Cursors.Default; //导出完成后,打开Excel文件 if (File.Exists(sfd.FileName)) { System.Diagnostics.Process.Start(sfd.FileName); } } } } private void ToolStripMenuItem3_Click(object sender, EventArgs e) { //如果没有选中颗粒退出 if (dgV_ParticlesDevidePage.SelectedRows.Count == 0) { return; } string categoryName = GetSelectedCategoryName(); var classificationData = GetClassificationData(); using (var modifyCategoryForm = new ModifyCategoryForm(classificationData, categoryName)) { if (modifyCategoryForm.ShowDialog() != DialogResult.OK || !modifyCategoryForm.DoYouWantToModifyIt) { return; } var updateParams = GetUpdateParameters(modifyCategoryForm); HandleCategoryUpdate(updateParams); } } private void ToolStripMenuItem_Delete_Particle_Click(object sender, EventArgs e) { string path = result.FilePath; var fieldData = new ParticleData(result.FilePath); List particles = fieldData.GetParticleAllList(); DialogResult dr = MessageBox.Show("Remove all these particles permanently?", "Tips", MessageBoxButtons.OKCancel, MessageBoxIcon.Question); if (dr == DialogResult.OK) { DeleteSelectedParticles(particles); } } private void btn_particletypesel_Click(object sender, EventArgs e) { ParticleClassificationSelect particleClassificationSelect = new ParticleClassificationSelect(this, tbx_Type.Text); DialogResult result = particleClassificationSelect.ShowDialog(); if (result == DialogResult.OK) { condition = ""; tbx_Type.Text = ""; if (particleClassificationSelect.ParticleClassificationSelected != "") { tbx_Type.Text = particleClassificationSelect.ParticleClassificationSelected; btn_Sel_Click(null, null); } } } private void btn_showconfig_Click(object sender, EventArgs e) { var p = particlesFilter; List ele = new List(); string elementsstr = ""; foreach (DataRow row in particlesFilter.Rows) { string[] strcbo = row["Element"].ToString().Split(';'); for (int j = 0; j < strcbo.Length; j++) { string[] str = strcbo[j].Split('-'); if (!ele.Contains(str[0]) && str[0] != "") { if (str[1] != "" && double.Parse(str[1]) != 0) //咨询demo后,元素含量返回值为零时一般去除此元素 { ele.Add(str[0]); } } } } foreach (var el in ele) { elementsstr += el.ToString() + ','; } if (elementsstr != "") { elementsstr = elementsstr.Remove(elementsstr.Length - 1, 1); } m_particlesGridDevidePageShowConfig = new ParticlesGridDevidePageShowConfig(m_ReportApp.m_RptConfigFile.Systype, elementsstr); m_particlesGridDevidePageShowConfig.ShowDialog(); if (m_particlesGridDevidePageShowConfig.DialogResult == DialogResult.OK) { dgV_ParticlesDevidePage.Rows.Clear(); dgV_ParticlesDevidePage.Columns.Clear(); RefreshGridView(); SetDataGridViewStyle(); } } private void tbx_Type_Click(object sender, EventArgs e) { ParticleClassificationSelect particleClassificationSelect = new ParticleClassificationSelect(this, tbx_Type.Text); DialogResult result = particleClassificationSelect.ShowDialog(); if (result == DialogResult.OK) { condition = ""; tbx_Type.Text = particleClassificationSelect.ParticleClassificationSelected; string[] tr = tbx_Type.Text.Split(','); condition += " and ("; for (int i = 0; i < tr.Length; i++) { if (i == 0) { condition += " TypeName = '" + tr[i] + "'"; } else { condition += " or TypeName = '" + tr[i] + "'"; } } condition += ")"; if (m_frm_userprogress.IsDisposed) { ProgressStart(); } UpdateDataGrid(); lnkFirst_Click(null, null); SetDataGridViewStyle(); } } private void 根据相似度批量修改ToolStripMenuItem_Click(object sender, EventArgs e) { //如果没有选中颗粒退出 if (dgV_ParticlesDevidePage.SelectedRows.Count != 1) { MessageBox.Show("Please select one row!"); return; } var SelectRows = dgV_ParticlesDevidePage.SelectedRows; DataGridViewRow dgvr = SelectRows[0]; Bitmap ls_bp = (Bitmap)dgvr.Cells[2].Value; List list_str = (List)ls_bp.Tag; uint[] Analysis_xray = new uint[2000]; int i_xray_id = 0; List list_celementchemistryclr = new List(); string str = " particleId= " + dgvr.Cells["particleId"].Value.ToString() + " and fieldid = " + dgvr.Cells["fieldid"].Value.ToString(); DataRow[] drs = particlesFilter.Select(str); DataRow row = drs[0]; string subParticleString = row["SubParticles"].ToString(); if (subParticleString != "" && subParticleString != null) { Particledata.GetXrayByParticleTagIDAndFieldID_ForMergeParticle(Convert.ToInt32(dgvr.Cells["particleId"].Value), Convert.ToInt32(dgvr.Cells["fieldid"].Value), out Analysis_xray); } else { ReportFun.GetXrayByParticleTagIDAndFieldID_ForDrawDistrbutionImageAndBSE(Convert.ToInt32(dgvr.Cells["particleId"].Value), Convert.ToInt32(dgvr.Cells["fieldid"].Value), out Analysis_xray, out i_xray_id, out list_celementchemistryclr); } ListOfSimilarParticles Form_listOfSimilarParticles = new ListOfSimilarParticles(this, Analysis_xray, m_ReportApp); DialogResult result3 = Form_listOfSimilarParticles.ShowDialog(); if (result3 == DialogResult.OK) { UpdateDataGrid(); lnkFirst_Click(null, null); SetDataGridViewStyle(); DataTable table = GetClassificationOfAllParticles(); if (table != null) { if (table.Rows.Count > 0) { foreach (DataRow rw in table.Rows) { tbx_Type.Text += rw["TypeName"].ToString() + '$'; } } if (tbx_Type.Text != "") { tbx_Type.Text = tbx_Type.Text.Remove(tbx_Type.Text.Length - 1); } } dgV_ParticlesDevidePage.Focus(); } else { } } private void dgV_ParticlesDevidePage_KeyDown(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Delete) { ToolStripMenuItem_Delete_Particle_Click(null, null); } } private void dgV_ParticlesDevidePage_KeyUp(object sender, KeyEventArgs e) { if (e.KeyData == Keys.Down) { dgV_ParticlesDevidePage_MouseUp(null, null); } if (e.KeyData == Keys.Up) { dgV_ParticlesDevidePage_MouseUp(null, null); } } private void dgV_ParticlesDevidePage_MouseUp(object sender, MouseEventArgs e) { ToolStripMenuItem_SimilarityReclassification.Enabled = false; var SelectRows = dgV_ParticlesDevidePage.SelectedRows; if (SelectRows.Count != 0) { if (SelectRows.Count == 1) { DataGridViewRow dgvr = SelectRows[0]; Bitmap ls_bp = (Bitmap)dgvr.Cells[2].Value; uint[] Analysis_xray = new uint[2000]; Particle particle = new Particle(); string str = " particleId= " + dgvr.Cells["particleId"].Value.ToString() + " and fieldid = " + dgvr.Cells["fieldid"].Value.ToString(); DataRow[] drs = particlesFilter.Select(str); DataRow row = drs[0]; string subParticleString = row["SubParticles"].ToString(); particle = Particledata.GetXrayByParticleIDAndFieldID(subParticleString, Convert.ToInt32(dgvr.Cells["particleId"].Value), Convert.ToInt32(dgvr.Cells["fieldid"].Value), out Analysis_xray); List list_showelementinfo = Particledata.GetShowElementInfos(particle.ElementList); string str_IncAName = ""; str_IncAName = Convert.ToString(dgvr.Cells[1].Value); if (particle == null) { return; } control_XRayTable1.SetParticleInfo("Area:" + Math.Round(particle.Area, 2) + " " + "DMAX:" + Math.Round(particle.DMAX, 2) + " " + "DELONG:" + Math.Round(particle.DELONG, 2) + " " + "DFERET:" + Math.Round(particle.DFERET, 2) + " " + "DINSCR:" + Math.Round(particle.DINSCR, 2) + "\n" + "DMEAN:" + Math.Round(particle.DMEAN, 2) + " " + "DMIN:" + Math.Round(particle.DMIN, 2) + " " + "DPERP:" + Math.Round(particle.DPERP, 2) + " " + "ORIENTATION:" + Math.Round(particle.ORIENTATION, 2) + " " + "PERIMETER:" + Math.Round(particle.PERIMETER, 2)); control_XRayTable1.Visible = true; control_XRayTable1.SetXRayShowLineValue(Analysis_xray, list_showelementinfo); control_XRayTable1.GBInfoStr = ""; control_XRayTable1.MaterialName = str_IncAName; control_XRayTable1.List_ShowElementInfo = list_showelementinfo; DataTable dataTable = new DataTable(); double pix = result.GetPixelSize(); int width = result.GetImageWidth(); int height = result.GetImageHeight(); Dictionary> segsData = new Dictionary>(); if (subParticleString == "" || subParticleString == null) { int fldid = Convert.ToInt32(dgvr.Cells["fieldid"].Value); int partid = Convert.ToInt32(dgvr.Cells["particleId"].Value); var listseg = Particledata.GetSegmentData(fldid, partid); string key = fldid.ToString() + "_" + partid.ToString(); segsData.Add(key, listseg); dataTable = particlesFilter.Clone(); dataTable.ImportRow(row); } else { string vs = "," + subParticleString.Replace(':', '-') + ","; dataTable = Particledata.GetParticleAllForBig(vs);//组成拼接颗粒的子颗粒 foreach (DataRow dow in dataTable.Rows) { int fldid = Convert.ToInt32(dow["fieldid"]); int partid = Convert.ToInt32(dow["particleId"]); var listseg = Particledata.GetSegmentData(fldid, partid); string key = dow["fieldid"].ToString() + "_" + dow["particleid"].ToString(); segsData.Add(key, listseg); } } Bitmap bmap = fldImgAccess.GetBitmapForParticleAll(subParticleString, dataTable, pix, height, width); Bitmap bmap1 = fldImgAccess.GetBitmapForParticleAllWithBlackAndWhite(subParticleString, dataTable, segsData, pix, height, width); control_XRayTable1.SetBitmapOfPictureBox(bmap, bmap1); Invalidate(); ToolStripMenuItem_SimilarityReclassification.Enabled = true; } SaveParticleslist_select(); } } private void dgV_ParticlesDevidePage_MouseDown(object sender, MouseEventArgs e) { ToolStripMenuItemDelete_Particle.Visible = true; } #endregion #endregion #region 连接电镜相关 /// /// 移动SEM到指定位置线程函数 /// private void ControlThread_GO(object in_obj) { if (m_mythread_state) return; m_mythread_state = true; try { Point sem_point = (Point)in_obj; //第一步,连接电镜 m_OTSIncAReportGridsFun?.Connection_ForParticlesGrid(); Thread.Sleep(500); //第二步,移动到指定位置,先读取再设置 if (m_OTSIncAReportGridsFun?.m_SEMConnectionState == true) { m_OTSIncAReportGridsFun.MoveSemToPointXY_ForParticlesGrid(sem_point.X, sem_point.Y); } Thread.Sleep(1500); } finally { m_mythread_state = false; } } #endregion #region 类别修改相关 /// /// 读取标准库的ClassifySTD表 /// /// /// private DataTable ReadClassification(string a_address, string STDName) { DataTable dt_STDGroups = new DataTable(); DataTable dt_ClassifySTD = new DataTable(); DataTable dt_IncAData = new DataTable(); var systype = m_ReportApp.m_RptConfigFile.Systype; if (systype == OTS_SysType_ID.IncA) { dt_ClassifySTD.Columns.Add("STDId"); dt_ClassifySTD.Columns.Add("StrName"); dt_ClassifySTD.Columns.Add("Color"); dt_ClassifySTD.Columns.Add("KeyElementList"); dt_ClassifySTD.Columns.Add("SubElementList"); dt_ClassifySTD.Columns.Add("UsingImgPropertyList"); dt_ClassifySTD.Columns.Add("UsingOtherPropertyList"); dt_ClassifySTD.Columns.Add("Expression"); dt_ClassifySTD.Columns.Add("Hardness"); dt_ClassifySTD.Columns.Add("Density"); dt_ClassifySTD.Columns.Add("Electrical_conductivity"); dt_ClassifySTD.Columns.Add("BSE"); dt_ClassifySTD.Columns.Add("Formula"); dt_ClassifySTD.Columns.Add("Element"); dt_ClassifySTD.Columns.Add("IfElementAnalysis"); dt_ClassifySTD.Columns.Add("ListNum"); dt_ClassifySTD.Columns.Add("GroupId"); dt_ClassifySTD.Columns.Add("GroupName"); dt_ClassifySTD.Columns.Add("GroupColor"); DataTable da = Particledata.GetParticleListForParticlSizeID("area", ""); for (int i = 0; i < da.Rows.Count; i++) { if (Convert.ToInt64(da.Rows[i]["TypeId"]) > 9) { DataRow newRow = dt_ClassifySTD.NewRow(); newRow["STDId"] = da.Rows[i]["TypeId"]; newRow["StrName"] = da.Rows[i]["TypeName"]; newRow["Color"] = da.Rows[i]["TypeColor"]; newRow["GroupId"] = da.Rows[i]["GroupId"]; newRow["GroupName"] = da.Rows[i]["GroupName"]; newRow["GroupColor"] = da.Rows[i]["GroupColor"]; dt_ClassifySTD.Rows.Add(newRow); } } } else { SqLiteHelper sh_STDGroups = new SqLiteHelper("data source='" + a_address + "\\" + STDName + ".db" + "'"); dt_STDGroups = sh_STDGroups.ExecuteQuery("select * from STDGroups"); SqLiteHelper sh_ClassifySTD = new SqLiteHelper("data source='" + a_address + "\\" + STDName + ".db" + "'"); dt_ClassifySTD = sh_ClassifySTD.ExecuteQuery("select * from ClassifySTD"); dt_ClassifySTD.Columns.Add("GroupName"); dt_ClassifySTD.Columns.Add("GroupColor"); for (int i = 0; i < dt_ClassifySTD.Rows.Count; i++) { for (int a = 0; a < dt_STDGroups.Rows.Count; a++) { if (dt_ClassifySTD.Rows[i]["GroupId"].ToString() == dt_STDGroups.Rows[a]["id"].ToString()) { dt_ClassifySTD.Rows[i]["GroupName"] = dt_STDGroups.Rows[a]["name"].ToString(); dt_ClassifySTD.Rows[i]["GroupColor"] = dt_STDGroups.Rows[a]["color"].ToString(); continue; } } } SqLiteHelper sh_Inclusion = new SqLiteHelper("data source='" + a_address + "\\FIELD_FILES\\Inclusion.db" + "'"); dt_IncAData = sh_Inclusion.ExecuteQuery("select * from IncAData"); for (int i = 0; i < dt_IncAData.Rows.Count; i++) { if (Convert.ToInt64(dt_IncAData.Rows[i]["TypeId"]) > 50000) { DataRow newRow = dt_ClassifySTD.NewRow(); newRow["STDId"] = dt_IncAData.Rows[i]["TypeId"]; newRow["StrName"] = dt_IncAData.Rows[i]["TypeName"]; newRow["Color"] = dt_IncAData.Rows[i]["TypeColor"]; newRow["GroupId"] = dt_IncAData.Rows[i]["GroupId"]; newRow["GroupName"] = dt_IncAData.Rows[i]["GroupName"]; newRow["GroupColor"] = dt_IncAData.Rows[i]["GroupColor"]; dt_ClassifySTD.Rows.Add(newRow); } } } DataRow newRowInvalid = dt_ClassifySTD.NewRow(); newRowInvalid["STDId"] = -1; newRowInvalid["StrName"] = "Invalid"; newRowInvalid["Color"] = "#000000"; newRowInvalid["GroupId"] = -1; newRowInvalid["GroupName"] = "Invalid"; newRowInvalid["GroupColor"] = "#000000"; dt_ClassifySTD.Rows.Add(newRowInvalid); return dt_ClassifySTD; } private string GetSelectedCategoryName() { if (dgV_ParticlesDevidePage.SelectedRows.Count > 0) { DataGridViewRow lastRow = dgV_ParticlesDevidePage.SelectedRows[ dgV_ParticlesDevidePage.SelectedRows.Count - 1]; return lastRow.Cells[1].Value?.ToString() ?? ""; } return ""; } private DataTable GetClassificationData() { string[] resultParts = result.GetSTDName().Split('.'); return ReadClassification(result.FilePath, resultParts[0]); } private List GetUpdateParameters(ModifyCategoryForm form) { return new List { form.OutTypeAndName[0], // TypeId form.OutTypeAndName[1], // TypeName form.OutTypeAndName[2], // TypeColor form.OutTypeAndName[3], // GroupName form.OutTypeAndName[4], // GroupID form.OutTypeAndName[5] // GroupColor }; } private void HandleCategoryUpdate(List updateParams) { if (dgV_ParticlesDevidePage.SelectedRows.Count == 1) { HandleSingleRowUpdate(updateParams); } else { HandleMultipleRowsUpdate(updateParams); } RefreshAfterUpdate(); } private void HandleSingleRowUpdate(List updateParams) { DialogResult result = MessageBox.Show("是否寻找相似颗粒并重命名?", "Tip", MessageBoxButtons.YesNo); if (result == DialogResult.Yes) { HandleSimilarParticleSearch(updateParams); } else { ExecuteBatchUpdate(updateParams); } } private void HandleSimilarParticleSearch(List updateParams) { int sel = m_ReportApp.m_conditionChoose.m_conditionData .GetComboDownListIndexByItemName( OTSIncAReportApp.OTSSampleReportInfo.OTS_REPORT_PROP_GRID_ITEMS.PARTICE_LIST); if (sel == (int)SelItem.MergeParticles) { ExecuteBatchUpdate(updateParams); return; } uint[] analysisXray = new uint[2000]; if (dgV_ParticlesDevidePage.SelectedRows.Count == 1) { DataGridViewRow row = dgV_ParticlesDevidePage.SelectedRows[0]; ReportFun.GetXrayByParticleTagIDAndFieldID_ForDrawDistrbutionImageAndBSE( Convert.ToInt32(row.Cells["particleId"].Value), Convert.ToInt32(row.Cells["fieldid"].Value), out analysisXray, out int _, // i_xray_id out List _); // list_celementchemistryclr } using (var form = new ListOfSimilarParticles(this, analysisXray, updateParams, m_ReportApp)) { if (form.ShowDialog() != DialogResult.OK) { ExecuteBatchUpdate(updateParams); } } } private void HandleMultipleRowsUpdate(List updateParams) { ExecuteBatchUpdate(updateParams); } private void ExecuteBatchUpdate(List updateParams) { var cmdList = new List>(); foreach (DataGridViewRow row in dgV_ParticlesDevidePage.SelectedRows) { UpdateGridRow(row, updateParams[1]); // TypeName if (row.Cells[2].Value is Bitmap bitmap && bitmap.Tag is List tagList) { var particleIds = new List { Convert.ToInt32(tagList[0]), // fieldId Convert.ToInt32(tagList[1]) // particleId }; var cmd = Particledata.GetUpdataAIncACmd(particleIds, updateParams); cmdList.Add(cmd); } row.Cells[1].Value = updateParams[1]; // Update TypeName in grid } Particledata.ExecuteNonQueryBatch(cmdList); } private void UpdateGridRow(DataGridViewRow row, string typeName) { row.Cells[1].Value = typeName; } private void RefreshAfterUpdate() { UpdateDataGrid(); lnkFirst_Click(null, null); SetDataGridViewStyle(); UpdateTypeTextBox(); dgV_ParticlesDevidePage.Focus(); } private void UpdateTypeTextBox() { tbx_Type.Text = ""; DataTable table = GetClassificationOfAllParticles(); if (table?.Rows.Count > 0) { tbx_Type.Text = string.Join("$", table.AsEnumerable() .Select(row => row["TypeName"].ToString())); } } #endregion #region 删除颗粒相关\备份 private void DeleteSelectedParticles(List particles) { var deletedParticles = new List(); foreach (DataGridViewRow row in dgV_ParticlesDevidePage.SelectedRows) { if (row.Cells[2].Value is Bitmap bitmap && bitmap.Tag is List tagList) { int fieldId = Convert.ToInt32(tagList[0]); int particleId = Convert.ToInt32(tagList[1]); Particle particleToDelete = particles.FirstOrDefault(p => p.FieldId == fieldId && p.ParticleId == particleId); if (particleToDelete != null && DeleteParticlesFromSTDDb(particleToDelete.ParticleId, particleToDelete.FieldId)) { RemoveParticleFromDataTable(particleToDelete); deletedParticles.Add(particleToDelete); } else { MessageBox.Show("Delete failed"); break; } } } UpdateUIAfterDeletion(deletedParticles.Count); //SynchronizeParticleDeletion(deletedParticles); } private void RemoveParticleFromDataTable(Particle particle) { for (int i = particlesAll.Rows.Count - 1; i >= 0; i--) { if (particlesAll.Rows[i]["Fieldid"].ToString() == particle.FieldId.ToString() && particlesAll.Rows[i]["Particleid"].ToString() == particle.ParticleId.ToString()) { particlesAll.Rows.RemoveAt(i); break; } } } private void UpdateUIAfterDeletion(int deletedCount) { RecordCount = recordCount - deletedCount; lblTotalCount.Text = RecordCount.ToString(); // Remove rows from grid (in reverse order to avoid index issues) var rowsToRemove = dgV_ParticlesDevidePage.SelectedRows.Cast().ToList(); foreach (var row in rowsToRemove) { dgV_ParticlesDevidePage.Rows.Remove(row); } if (dgV_ParticlesDevidePage.Rows.Count == 0) { DisplayData(); } else { // Update row numbers for (int j = 0; j < dgV_ParticlesDevidePage.Rows.Count; j++) { dgV_ParticlesDevidePage.Rows[j].Cells[0].Value = (pageSize * (PageIndex - 1) + j + 1).ToString(); } } } private void SynchronizeParticleDeletion(List deletedParticles) { if (m_ReportApp.im_Control_DrawDistrbutionImageAndBSE != null) { m_ReportApp.im_Control_DrawDistrbutionImageAndBSE.DeletesParticlesSynchronously(deletedParticles); } else { using (var control = new OTSIncAReportGraph.Controls.Control_DrawDistrbutionImageAndBSE(m_ReportApp)) { foreach (var particle in deletedParticles) { control.DeleteParticlesFromSTDDb(particle.ParticleId, particle.FieldId); } } } } private bool DeleteParticlesFromSTDDb(int particleId, int fieldId) { if (!CheckAndCreateBackup()) return false; //防止为空校验判断 if (result.GetList_OTSField() == null) return false; try { //Particle particle = result.GetList_OTSField() // .Find(x => x.FieldID == fieldId)? // .ParticleList.Find(x => x.ParticleId == particleId); //if (particle == null) // return false; var particleData = new ParticleData(result.FilePath); return particleData.DeleteFromData( Convert.ToString(fieldId), Convert.ToString(particleId)); } catch (Exception ex) { log.Error($"Error deleting particle: {ex.Message}"); return false; } } private bool CheckAndCreateBackup() { bool backupExists = Enumerable.Range(1, 200).Any(i => Directory.Exists(Path.Combine(result.FilePath, "FIELD_FILES", "Backups" + i))); if (!backupExists) { return BackupDatabase(); } return true; } private bool BackupDatabase() { try { //创建备份数据库文件夹 string sourcePath = Path.Combine(result.FilePath, "FIELD_FILES", "Inclusion.db"); string sourceName = "Inclusion.db"; string folderPath = Path.Combine(result.FilePath, "FIELD_FILES", "Backups"); string backupFolder = ""; for (int i = 1; i <= 200; i++) { string currentPath = Path.Combine(folderPath, i.ToString()); if (!Directory.Exists(currentPath)) { Directory.CreateDirectory(currentPath); backupFolder = currentPath; break; } } if (string.IsNullOrEmpty(backupFolder)) { return false; } //复制数据库文件 string targetPath = Path.Combine(backupFolder, sourceName); File.Copy(sourcePath, targetPath, true); return true; } catch (Exception ex) { log.Error($"Error backing up database: {ex.Message}"); return false; } } #endregion #region 报表输出 /// /// /// /// /// /// /// public void Out_MarkParticleRectangleOnFieldFile(string str_resultPath, DataTable dataTable, out List vs, out DataTable dt_FIeld) { Init(); var fieldIds = ExtractFieldIds(dataTable); string str_path_FIELD_FILES = Path.Combine(str_resultPath, "FIELD_FILES"); dt_FIeld = new DataTable(); vs = new List(); ResultFile resfile = m_ReportApp.m_rstDataMgr.ResultFilesList[ m_ReportApp.m_rstDataMgr.GetWorkingResultId()]; float pixelSize = resfile.GetPixelSize(); float scanFieldSizeX = resfile.GetScanFieldSizeX(); int gauge = RulerSelection(scanFieldSizeX); float rulerPixels = gauge / pixelSize; var fieldData = new FieldData(resfile.FilePath); DataTable dt_AllParticle = fieldData.GetAllParticle_DataTable(); var directoryInfo = new DirectoryInfo(str_path_FIELD_FILES); if (directoryInfo.Exists) { ProcessFieldFiles(directoryInfo, fieldIds, dataTable, dt_AllParticle, rulerPixels, gauge, ref dt_FIeld, vs); } } private List ExtractFieldIds(DataTable dataTable) { return dataTable.AsEnumerable() .Where(row => Convert.ToInt32(row["TypeId"]) > 9) .Take(10) .Select(row => row["Fieldid"].ToString()) .Distinct() .ToList(); } private void ProcessFieldFiles(DirectoryInfo directoryInfo, List fieldIds, DataTable dataTable, DataTable allParticles, float rulerPixels, int gauge, ref DataTable dt_FIeld, List vs) { var fieldFiles = directoryInfo.GetFiles("Field*.bmp") .ToDictionary(f => GetFieldIdFromFile(f.Name), f => f, StringComparer.OrdinalIgnoreCase); var resultTable = CreateFieldDataTable(); foreach (string fieldId in fieldIds.Where(id => fieldFiles.ContainsKey(id))) { var file = fieldFiles[fieldId]; int count = dataTable.AsEnumerable() .Count(row => row["fieldid"].ToString() == fieldId); DataRow dr = resultTable.NewRow(); dr["fieldid"] = $" fieldid = {fieldId}"; dr["cunt"] = count; dr["fieldName"] = file.Name; dr["fieldFullName"] = file.FullName; dr["id"] = fieldId; resultTable.Rows.Add(dr); } dt_FIeld = resultTable.Copy(); dt_FIeld.Columns.Add("Field_pic", typeof(Bitmap)); ProcessFieldImages(allParticles, rulerPixels, gauge, dt_FIeld, vs); } private string GetFieldIdFromFile(string fileName) { string nameWithoutExtension = Path.GetFileNameWithoutExtension(fileName); return nameWithoutExtension.Length > 5 ? nameWithoutExtension.Substring(5) : nameWithoutExtension; } private DataTable CreateFieldDataTable() { var dt = new DataTable(); dt.Columns.Add("fieldid"); dt.Columns.Add("id"); dt.Columns.Add("fieldName"); dt.Columns.Add("cunt", typeof(int)); dt.Columns.Add("fieldFullName"); return dt; } private void ProcessFieldImages(DataTable allParticles, float rulerPixels, int gauge, DataTable dt_FIeld, List vs) { var particleGroups = allParticles.AsEnumerable() .GroupBy(row => row["fieldid"].ToString()) .ToDictionary(g => g.Key, g => g.ToList()); foreach (DataRow row in dt_FIeld.Rows.Cast().ToList()) { string fieldId = row["id"].ToString(); if (!particleGroups.ContainsKey(fieldId) || particleGroups[fieldId].Count == 0) continue; vs.Add(fieldId); try { using (var img = Image.FromFile(row["fieldFullName"].ToString())) { using (var fieldBitmap = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { DrawBaseImage(img, fieldBitmap); MarkParticlesOnImage(particleGroups[fieldId], fieldBitmap, row, fieldId, rulerPixels, gauge); } } } catch (Exception ex) { log.Error($"Error processing field image: {ex.Message}"); } } } private void DrawBaseImage(Image sourceImage, Bitmap targetBitmap) { using (Graphics g = Graphics.FromImage(targetBitmap)) { g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.DrawImage(sourceImage, new Rectangle(0, 0, sourceImage.Width, sourceImage.Height)); } } private void MarkParticlesOnImage(List particles, Bitmap fieldBitmap, DataRow fieldRow, string fieldId, float rulerPixels, int gauge) { foreach (DataRow particleRow in particles) { string particleId = particleRow["particleid"].ToString(); var rectangle = new Rectangle( Convert.ToInt32(particleRow["RectLeft"]), Convert.ToInt32(particleRow["RectTop"]), Convert.ToInt32(particleRow["RectWidth"]), Convert.ToInt32(particleRow["RectHeight"]) ); MarkParticleOnImage(fieldBitmap, rectangle, fieldId, particleId); } using (var rulerBitmap = DrawRuler(fieldBitmap, (int)(rulerPixels / 2), 2, $"{gauge / 2}μm")) { fieldRow["Field_pic"] = new Bitmap(rulerBitmap); } } private void MarkParticleOnImage(Bitmap fieldBitmap, Rectangle rectangle, string fieldId, string particleId) { using (Graphics g = Graphics.FromImage(fieldBitmap)) using (var pen = new Pen(Color.Aquamarine)) { g.DrawRectangle(pen, rectangle); int textX = rectangle.X + rectangle.Width > fieldBitmap.Width - 10 ? rectangle.X - 10 : rectangle.X + rectangle.Width; using (var font = new Font("黑体", 8)) using (var brush = new SolidBrush(Color.Aqua)) { g.DrawString($"{fieldId} {particleId}", font, brush, new PointF(textX, rectangle.Y)); } } } /// /// 在图片上绘制标尺 /// /// 图片 /// 线长(像素) /// 线宽(像素) /// 显示文本 /// private Bitmap DrawRuler(Bitmap bitmap, int lineLength, int lineWidth, string text) { if (bitmap == null) throw new ArgumentNullException(nameof(bitmap)); var rgbBitmap = new Bitmap(bitmap.Width, bitmap.Height); using (Graphics graphics = Graphics.FromImage(rgbBitmap)) { graphics.DrawImage(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height)); Color color = Color.LimeGreen; using (var pen = new Pen(color, lineWidth)) using (var font = new Font("Arial", 20, GraphicsUnit.Pixel)) using (var brush = new SolidBrush(color)) { var stringFormat = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; int startX = 20; int startY = bitmap.Height - 30; graphics.DrawLine(pen, startX, startY, startX + lineLength, startY); graphics.DrawString(text, font, brush, new PointF(startX + lineLength / 2, startY - 20), stringFormat); } } return rgbBitmap; } private int RulerSelection(float scanFieldSizeX) { // 根据扫描场尺寸选择合适的标尺单位 if (scanFieldSizeX >= 1000) return 1000; if (scanFieldSizeX >= 500) return 500; if (scanFieldSizeX >= 200) return 200; if (scanFieldSizeX >= 100) return 100; if (scanFieldSizeX >= 50) return 50; if (scanFieldSizeX >= 20) return 20; if (scanFieldSizeX >= 10) return 10; if (scanFieldSizeX >= 5) return 5; if (scanFieldSizeX >= 2) return 2; return 1; } #endregion } }