diff --git a/BackupTest.cs b/BackupTest.cs deleted file mode 100644 index f544421..0000000 --- a/BackupTest.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using System.IO; -using System.Windows; - -namespace DrillTools -{ - /// - /// 备份功能测试类 - /// - public static class BackupTest - { - /// - /// 测试备份功能 - /// - public static void TestBackupFunctionality() - { - Console.WriteLine("=== 备份功能测试 ==="); - - // 创建测试文件 - string testFilePath = "test_file.drl"; - string testContent = "M48\nT01C1.000\n%\nT01\nX1000Y1000\nM30"; - - try - { - // 1. 创建原始测试文件 - File.WriteAllText(testFilePath, testContent); - Console.WriteLine("✓ 创建测试文件成功"); - - // 2. 第一次备份(应该直接创建.bak文件) - string backupPath1 = testFilePath + ".bak"; - if (File.Exists(backupPath1)) - File.Delete(backupPath1); - - File.Copy(testFilePath, backupPath1); - Console.WriteLine("✓ 第一次备份成功"); - - // 3. 模拟第二次备份(检测到.bak文件已存在) - if (File.Exists(backupPath1)) - { - Console.WriteLine("✓ 检测到备份文件已存在"); - - // 模拟用户选择创建时间戳备份 - string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); - string timestampBackupPath = $"{testFilePath}.{timestamp}.bak"; - File.Copy(testFilePath, timestampBackupPath); - Console.WriteLine($"✓ 创建时间戳备份成功: {Path.GetFileName(timestampBackupPath)}"); - } - - // 4. 验证备份文件内容 - if (File.Exists(backupPath1) && File.ReadAllText(backupPath1) == testContent) - { - Console.WriteLine("✓ 备份文件内容验证成功"); - } - - // 5. 清理测试文件 - File.Delete(testFilePath); - if (File.Exists(backupPath1)) - File.Delete(backupPath1); - - // 删除时间戳备份文件 - var timestampFiles = Directory.GetFiles(".", "*.bak"); - foreach (var file in timestampFiles) - { - if (file.Contains("test_file.") && file.Contains(".bak")) - { - File.Delete(file); - Console.WriteLine($"✓ 清理测试文件: {Path.GetFileName(file)}"); - } - } - - Console.WriteLine("=== 备份功能测试完成 ==="); - } - catch (Exception ex) - { - Console.WriteLine($"✗ 测试失败: {ex.Message}"); - } - } - } -} \ No newline at end of file diff --git a/DebugTest.cs b/DebugTest.cs deleted file mode 100644 index 2528285..0000000 --- a/DebugTest.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using DrillTools.Integration; - -namespace DrillTools.Tests -{ - /// - /// 调试测试程序,用于验证孔数计算问题 - /// - public class DebugTest - { - public static void RunTest() - { - Console.WriteLine("=== 调试测试:孔数计算问题 ==="); - - // 使用用户提供的钻带数据 - string drillTapeContent = @"M48 -;厚铜板参数-镀膜-EA-250618 -T01C1.049H05000Z+0.000S060.00F105.0U0700.0 -T02C1.550H01500Z+0.150S070.00F008.0U0800.0 -T03C1.156H03000Z-0.200S040.00F030.0U0900.0 -T04C1.451H04000Z-0.200S040.00F030.0U0900.0 -T05C1.153H05000Z-0.200S040.00F030.0U0900.0 -T06C0.499 -% -T01 -X-167525Y013500 -X-167525Y018500 -X-167525Y023500 -X167525Y013500 -X167525Y018500 -X167525Y023500 -X099366Y502000 -T02 -X-065975Y115250 -X-085825Y122450 -X-085825Y124550 -X-097425Y115250 -X103093Y502000 -T03 -X-069659Y016450G85X-094159Y016450 -X-181341Y195550G85X-156841Y195550 -X-069659Y210450G85X-094159Y210450 -X-181341Y389550G85X-156841Y389550 -X-069659Y404450G85X-094159Y404450 -X-181341Y583550G85X-156841Y583550 -X162939Y596000 -T04 -X-069659Y016450G85X-094159Y016450 -X-181341Y195550G85X-156841Y195550 -X-069659Y210450G85X-094159Y210450 -X-181341Y389550G85X-156841Y389550 -X-069659Y404450G85X-094159Y404450 -X-181341Y583550G85X-156841Y583550 -T05 -X-069659Y016450G85X-094159Y016450 -X-181341Y195550G85X-156841Y195550 -X-069659Y210450G85X-094159Y210450 -X-181341Y389550G85X-156841Y389550 -X-069659Y404450G85X-094159Y404450 -X-181341Y583550G85X-156841Y583550 -T06 -M97,A*,$S $N -X-194000Y002000 -M30"; - - // 处理钻带 - var result = DrillTapeProcessor.ProcessDrillTape(drillTapeContent); - - // 输出结果 - Console.WriteLine($"处理状态: {(result.Success ? "成功" : "失败")}"); - if (!result.Success) - { - Console.WriteLine($"错误信息: {result.Message}"); - return; - } - - Console.WriteLine("\n刀具统计:"); - Console.WriteLine("刀具\t孔径(mm)\t类型\t\t普通孔数\t槽孔数\t总孔数"); - Console.WriteLine("========================================================"); - - foreach (var tool in result.ToolResults) - { - string toolTypeDisplay = tool.ToolType switch - { - ToolType.Regular => "圆孔", - ToolType.Slot => "槽孔", - ToolType.MachineCode => "机台码", - _ => "未知" - }; - - Console.WriteLine($"T{tool.ToolNumber:D2}\t{tool.Diameter:F3}\t\t{toolTypeDisplay}\t{tool.RegularHoles}\t\t{tool.SlotHoles}\t{tool.TotalHoles}"); - } - - Console.WriteLine($"\n总孔数: {result.TotalHoles}"); - - // 验证结果 - Console.WriteLine("\n=== 验证结果 ==="); - VerifyResults(result); - } - - private static void VerifyResults(DrillTapeResult result) - { - // CAM350的预期结果 - var expectedResults = new[] - { - new { ToolNumber = 1, Diameter = 1.049, ExpectedHoles = 7 }, - new { ToolNumber = 2, Diameter = 1.550, ExpectedHoles = 5 }, - new { ToolNumber = 3, Diameter = 1.156, ExpectedHoles = 619 }, - new { ToolNumber = 4, Diameter = 1.451, ExpectedHoles = 5 }, - new { ToolNumber = 5, Diameter = 1.153, ExpectedHoles = 5 }, - new { ToolNumber = 6, Diameter = 0.499, ExpectedHoles = 57 } - }; - - bool allMatch = true; - - foreach (var expected in expectedResults) - { - var actual = result.ToolResults.Find(t => t.ToolNumber == expected.ToolNumber); - if (actual != null) - { - bool match = Math.Abs(actual.Diameter - expected.Diameter) < 0.001 && - actual.TotalHoles == expected.ExpectedHoles; - - Console.WriteLine($"T{expected.ToolNumber:D2} ({expected.Diameter:F3}mm): " + - $"预期={expected.ExpectedHoles}, 实际={actual.TotalHoles}, " + - $"{(match ? "✓" : "✗")}"); - - if (!match) - allMatch = false; - } - else - { - Console.WriteLine($"T{expected.ToolNumber:D2}: 未找到结果 ✗"); - allMatch = false; - } - } - - Console.WriteLine($"\n总体结果: {(allMatch ? "✓ 所有结果与CAM350一致" : "✗ 存在不一致的结果")}"); - } - } -} \ No newline at end of file diff --git a/DrillTools.csproj b/DrillTools.csproj index da170b8..1139bfd 100644 --- a/DrillTools.csproj +++ b/DrillTools.csproj @@ -8,6 +8,11 @@ true true x86 + favicon.ico + + + + diff --git a/MainWindow.xaml.cs b/MainWindow.xaml.cs index e62876e..8240b24 100644 --- a/MainWindow.xaml.cs +++ b/MainWindow.xaml.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Text; using System.Windows; using System.Windows.Controls; @@ -182,6 +183,16 @@ namespace DrillTools // 保存原始文件路径 ViewModel.OriginalFilePath = files[0]; + Encoding ansiEncoding; + try + { + ansiEncoding = Encoding.GetEncoding(936); // 936是GB2312的代码页 + } + catch + { + ansiEncoding = Encoding.Default; // 如果获取失败,使用系统默认编码 + } + var process = new Process { StartInfo = new ProcessStartInfo @@ -190,7 +201,8 @@ namespace DrillTools Arguments = $"/c type \"{files[0]}\"", RedirectStandardOutput = true, UseShellExecute = false, - CreateNoWindow = true + CreateNoWindow = true, + StandardOutputEncoding = ansiEncoding } }; diff --git a/MainWindowViewModel.cs b/MainWindowViewModel.cs index 8f2db47..dad54eb 100644 --- a/MainWindowViewModel.cs +++ b/MainWindowViewModel.cs @@ -5,6 +5,7 @@ using System.ComponentModel; using System.IO; using System.Linq; using System.Runtime.CompilerServices; +using System.Text; using System.Text.RegularExpressions; using System.Windows; using DrillTools.Integration; @@ -115,12 +116,12 @@ namespace DrillTools DrillTapeContent = drillTapeContent; Tools.Clear(); OriginalTools.Clear(); // 清空原始刀具顺序 - + try { // 使用现有的 DrillTapeProcessor 处理钻带数据 var result = DrillTapeProcessor.ProcessDrillTape(drillTapeContent); - + if (result.Success) { foreach (var toolResult in result.ToolResults) @@ -138,16 +139,16 @@ namespace DrillTools ToolCategory = toolResult.ToolCategory, HoleLocations = toolResult.Locations ?? new List() }; - + // 如果是机台码,使用DrillTapeProcessor已经解析出的机台码信息 if (toolResult.ToolType == ToolType.MachineCode) { toolItem.MachineCodeCommand = toolResult.MachineCodeCommand; toolItem.MachineCodeType = toolResult.MachineCodeType; - + // 添加日志验证机台码信息传递 System.Diagnostics.Debug.WriteLine($"[机台码传递] T{toolResult.ToolNumber:D2}: 命令={toolItem.MachineCodeCommand}, 类型={toolItem.MachineCodeType}"); - + // 如果 toolResult.Locations 已经包含坐标数据,则使用它 // 否则从原始钻带内容中提取坐标行 if (toolItem.HoleLocations == null || toolItem.HoleLocations.Count == 0) @@ -155,28 +156,28 @@ namespace DrillTools // 从钻带内容中提取机台码坐标行 var toolPattern = $@"%.+?T{toolResult.ToolNumber:D2}(.*?)(?=T\d{{2}}|M30)"; var match = System.Text.RegularExpressions.Regex.Match(DrillTapeContent, toolPattern, System.Text.RegularExpressions.RegexOptions.Singleline); - + if (match.Success) { string holeSection = match.Groups[1].Value; - + // 查找机台码坐标行 var coordinatePattern = @"X([+-]?\d+\.?\d*)Y([+-]?\d+\.?\d*)"; var coordinateMatches = System.Text.RegularExpressions.Regex.Matches(holeSection, coordinatePattern); - + toolItem.HoleLocations = new List(); foreach (Match coordMatch in coordinateMatches) { toolItem.HoleLocations.Add(coordMatch.Value); } - + System.Diagnostics.Debug.WriteLine($"[机台码坐标] T{toolResult.ToolNumber:D2}: 找到{toolItem.HoleLocations.Count}个坐标"); } } } - + Tools.Add(toolItem); - + // 同时添加到原始刀具顺序集合中 var originalToolItem = new ToolItem { @@ -191,9 +192,15 @@ namespace DrillTools }; OriginalTools.Add(originalToolItem); } - + // 更新按钮状态 UpdateMoveButtonsState(); + + // 检查并应用-sort.txt文件中的刀具排序 + if (!string.IsNullOrEmpty(OriginalFilePath)) + { + CheckAndApplySortFile(OriginalFilePath, Tools); + } } else { @@ -418,13 +425,31 @@ namespace DrillTools } } - // 3. 将重新排序后的钻带内容写入原始文件 - File.WriteAllText(OriginalFilePath, reorderedDrillTape); + // 3. 将重新排序后的钻带内容写入原始文件,使用ANSI编码 + Encoding ansiEncoding; + try + { + ansiEncoding = Encoding.GetEncoding(936); // 936是GB2312的代码页 + } + catch + { + ansiEncoding = Encoding.Default; // 如果获取失败,使用系统默认编码 + } + + // 使用StreamWriter写入文件,确保编码正确应用 + using (var writer = new StreamWriter(OriginalFilePath, false, ansiEncoding)) + { + writer.Write(reorderedDrillTape); + writer.Flush(); // 确保所有数据都被写入 + } // 4. 更新当前钻带内容 DrillTapeContent = reorderedDrillTape; - // 5. 打开文件资源管理器并选中文件 + // 5. 生成刀具直径列表文件 + GenerateToolDiameterListFile(OriginalFilePath, Tools); + + // 6. 打开文件资源管理器并选中文件 OpenFileExplorerAndSelectFile(OriginalFilePath); return reorderedDrillTape; @@ -481,6 +506,11 @@ namespace DrillTools MachineCodeType = t.MachineCodeType }).ToList(); + //重新排一下 reorderedTools 的刀序Txx + int number = 1; + foreach (var item in reorderedTools) + item.ToolNumber = number++; + //检查是否所有刀序没有变化 int checkindex = 1; for (int i = 0; i < originalTools.Count; i++) @@ -1071,5 +1101,197 @@ M30"; System.Windows.MessageBox.Show($"打开文件资源管理器失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } + + /// + /// 生成刀具直径列表文件 + /// + /// 原始文件路径 + /// 刀具列表 + private void GenerateToolDiameterListFile(string originalFilePath, ObservableCollection tools) + { + try + { + // 获取原文件的目录和文件名(不含扩展名) + string directory = Path.GetDirectoryName(originalFilePath) ?? ""; + string fileNameWithoutExt = Path.GetFileNameWithoutExtension(originalFilePath); + string outputFilePath = Path.Combine(directory, $"{fileNameWithoutExt}-sort.txt"); + + // 按刀具编号排序获取最终顺序 + var sortedTools = tools.OrderBy(t => t.ToolNumber).ToList(); + + // 生成刀具直径列表内容 + var diameterList = new StringBuilder(); + foreach (var tool in sortedTools) + { + diameterList.AppendLine($"{tool.Diameter:F3}"); + } + + // 使用ANSI编码写入文件 + Encoding ansiEncoding; + try + { + ansiEncoding = Encoding.GetEncoding(936); // 936是GB2312的代码页 + } + catch + { + ansiEncoding = Encoding.Default; // 如果获取失败,使用系统默认编码 + } + + File.WriteAllText(outputFilePath, diameterList.ToString(), ansiEncoding); + + // 记录日志 + System.Diagnostics.Debug.WriteLine($"刀具直径列表文件已生成: {outputFilePath}"); + } + catch (Exception ex) + { + // 记录错误但不影响主要功能 + System.Diagnostics.Debug.WriteLine($"生成刀具直径列表文件失败: {ex.Message}"); + } + } + + /// + /// 检查并应用-sort.txt文件中的刀具排序 + /// + /// 原始文件路径 + /// 当前刀具列表 + private void CheckAndApplySortFile(string originalFilePath, ObservableCollection tools) + { + try + { + // 获取-sort.txt文件路径 + string directory = Path.GetDirectoryName(originalFilePath) ?? ""; + string fileNameWithoutExt = Path.GetFileNameWithoutExtension(originalFilePath); + string sortFilePath = Path.Combine(directory, $"{fileNameWithoutExt}-sort.txt"); + + // 检查-sort.txt文件是否存在 + if (!File.Exists(sortFilePath)) + return; + + // 读取-sort.txt文件内容 + List sortDiameters = ReadSortFile(sortFilePath); + if (sortDiameters.Count == 0) + return; + + // 检查直径数量是否一致 + if (sortDiameters.Count != tools.Count) + return; + + // 提示用户是否应用排序 + var result = System.Windows.MessageBox.Show( + $"检测到之前刀序重排后的记录文件:{Path.GetFileName(sortFilePath)}\n\n" + + $"是否直接按该记录文件进行排序?\n\n" + + "是(Y):按记录文件排序\n" + + "否(N):保持当前顺序", + "刀具排序提示", + MessageBoxButton.YesNo, + MessageBoxImage.Question); + + if (result == MessageBoxResult.Yes) + { + // 按照-sort.txt文件中的直径顺序重新排列刀具 + SortToolsByDiameterList(tools, sortDiameters); + + // 执行完整的重排刀序流程,包括重新编号和更新钻带内容 + try + { + string reorderedDrillTape = ReorderAndRenumberTools(); + System.Diagnostics.Debug.WriteLine($"已按-sort.txt文件重新排序刀具并更新钻带内容"); + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"重排刀序失败: {ex.Message}"); + // 即使重排失败,也保持列表的排序 + OnPropertyChanged(nameof(Tools)); + } + } + } + catch (Exception ex) + { + // 记录错误但不影响主要功能 + System.Diagnostics.Debug.WriteLine($"检查-sort.txt文件失败: {ex.Message}"); + } + } + + /// + /// 读取-sort.txt文件内容并解析直径列表 + /// + /// -sort.txt文件路径 + /// 直径列表 + private List ReadSortFile(string sortFilePath) + { + var diameters = new List(); + + try + { + // 使用ANSI编码读取文件 + Encoding ansiEncoding; + try + { + ansiEncoding = Encoding.GetEncoding(936); // 936是GB2312的代码页 + } + catch + { + ansiEncoding = Encoding.Default; // 如果获取失败,使用系统默认编码 + } + + string[] lines = File.ReadAllLines(sortFilePath, ansiEncoding); + + foreach (string line in lines) + { + string trimmedLine = line.Trim(); + if (!string.IsNullOrEmpty(trimmedLine)) + { + if (double.TryParse(trimmedLine, out double diameter)) + { + diameters.Add(diameter); + } + } + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"读取-sort.txt文件失败: {ex.Message}"); + } + + return diameters; + } + + /// + /// 根据直径列表排序刀具 + /// + /// 刀具列表 + /// 直径列表(目标顺序) + private void SortToolsByDiameterList(ObservableCollection tools, List diameterList) + { + // 创建直径到刀具的映射 + var diameterToTools = new Dictionary>(); + foreach (var tool in tools) + { + double roundedDiameter = Math.Round(tool.Diameter, 3); + if (!diameterToTools.ContainsKey(roundedDiameter)) + { + diameterToTools[roundedDiameter] = new List(); + } + diameterToTools[roundedDiameter].Add(tool); + } + + // 按照直径列表的顺序重新排列刀具 + var sortedTools = new List(); + foreach (double diameter in diameterList) + { + double roundedDiameter = Math.Round(diameter, 3); + if (diameterToTools.ContainsKey(roundedDiameter)) + { + sortedTools.AddRange(diameterToTools[roundedDiameter]); + } + } + + // 清空原列表并添加排序后的刀具 + tools.Clear(); + foreach (var tool in sortedTools) + { + tools.Add(tool); + } + } } } \ No newline at end of file diff --git a/ToolReorderConfirmationWindow.xaml b/ToolReorderConfirmationWindow.xaml index 2b7891d..01fa003 100644 --- a/ToolReorderConfirmationWindow.xaml +++ b/ToolReorderConfirmationWindow.xaml @@ -46,7 +46,7 @@ - + @@ -65,7 +65,7 @@ - + diff --git a/ToolReorderConfirmationWindow.xaml.cs b/ToolReorderConfirmationWindow.xaml.cs index 3a507f8..63e64fe 100644 --- a/ToolReorderConfirmationWindow.xaml.cs +++ b/ToolReorderConfirmationWindow.xaml.cs @@ -15,6 +15,11 @@ namespace DrillTools /// public bool IsConfirmed { get; private set; } + /// + /// 标记是否正在处理选中项同步,防止递归调用 + /// + private bool _isSynchronizingSelection = false; + /// /// 构造函数 /// @@ -97,6 +102,104 @@ namespace DrillTools } } + /// + /// 原始刀序列表选中项变化事件处理 + /// + private void OriginalToolsListView_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (_isSynchronizingSelection) + return; + + try + { + _isSynchronizingSelection = true; + + if (OriginalToolsListView.SelectedItem is ToolOrderItem selectedOriginalItem) + { + // 在重排后列表中查找对应的刀具 + var matchingItem = FindMatchingToolItem(ReorderedToolsListView, selectedOriginalItem); + if (matchingItem != null) + { + ReorderedToolsListView.SelectedItem = matchingItem; + // 确保选中的项可见 + ReorderedToolsListView.ScrollIntoView(matchingItem); + } + } + else + { + // 如果原始列表没有选中项,清空重排后列表的选中项 + ReorderedToolsListView.SelectedItem = null; + } + } + finally + { + _isSynchronizingSelection = false; + } + } + + /// + /// 重排后刀序列表选中项变化事件处理 + /// + private void ReorderedToolsListView_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (_isSynchronizingSelection) + return; + + try + { + _isSynchronizingSelection = true; + + if (ReorderedToolsListView.SelectedItem is ToolOrderItem selectedReorderedItem) + { + // 在原始列表中查找对应的刀具 + var matchingItem = FindMatchingToolItem(OriginalToolsListView, selectedReorderedItem); + if (matchingItem != null) + { + OriginalToolsListView.SelectedItem = matchingItem; + // 确保选中的项可见 + OriginalToolsListView.ScrollIntoView(matchingItem); + } + } + else + { + // 如果重排后列表没有选中项,清空原始列表的选中项 + OriginalToolsListView.SelectedItem = null; + } + } + finally + { + _isSynchronizingSelection = false; + } + } + + /// + /// 在ListView中查找匹配的刀具项 + /// + /// 要搜索的ListView + /// 目标刀具项 + /// 匹配的刀具项,如果未找到则返回null + private ToolOrderItem FindMatchingToolItem(System.Windows.Controls.ListView listView, ToolOrderItem targetItem) + { + if (listView?.ItemsSource == null || targetItem == null) + return null; + + foreach (var item in listView.Items) + { + if (item is ToolOrderItem toolItem) + { + // 使用与ViewModel中相同的匹配逻辑:基于孔径和刀具类型 + // 注意:这里使用ToolTypeDisplay进行比较,因为ToolOrderItem中没有ToolType属性 + if (Math.Abs(toolItem.Diameter - targetItem.Diameter) < 0.001 && + toolItem.ToolTypeDisplay == targetItem.ToolTypeDisplay) + { + return toolItem; + } + } + } + + return null; + } + /// /// 获取ListView中的ScrollViewer控件 /// diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..b16b9cd Binary files /dev/null and b/favicon.ico differ