Design Express Res initial commit
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,83 @@
|
||||
# Design Express Res 部署脚本: 复制 DLL + 注册每用户 COM + 生成 .addin (无需管理员权限)
|
||||
# 架构: DesignExpress.Core.dll(独立核心) + DesignExpress.InventorLink.dll(Inventor 适配)
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$invVer = "2022"
|
||||
$addinDir = Join-Path $env:APPDATA "Autodesk\Inventor $invVer\Addins"
|
||||
$clsid = "{D422E0BF-02D0-4DAE-958A-7BBA80B718E9}"
|
||||
$progId = "DesignExpress.InventorLink.AddInServer"
|
||||
$asmName = "DesignExpress.InventorLink, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
|
||||
|
||||
$srcCore = Join-Path $PSScriptRoot "DesignExpress.Core.dll"
|
||||
$srcLink = Join-Path $PSScriptRoot "DesignExpress.InventorLink.dll"
|
||||
if (-not (Test-Path $srcCore)) { Write-Host "未找到 DesignExpress.Core.dll"; exit 1 }
|
||||
if (-not (Test-Path $srcLink)) { Write-Host "未找到 DesignExpress.InventorLink.dll"; exit 1 }
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $addinDir | Out-Null
|
||||
Copy-Item -LiteralPath $srcCore -Destination (Join-Path $addinDir "DesignExpress.Core.dll") -Force
|
||||
$dstLink = Join-Path $addinDir "DesignExpress.InventorLink.dll"
|
||||
Copy-Item -LiteralPath $srcLink -Destination $dstLink -Force
|
||||
Write-Host "DLL 已复制: $addinDir"
|
||||
|
||||
# 每用户 COM 注册 (HKCU\Software\Classes)
|
||||
$clsBase = "HKCU:\Software\Classes\CLSID\$clsid"
|
||||
Remove-Item -Path $clsBase -Recurse -Force -ErrorAction SilentlyContinue
|
||||
New-Item -Path $clsBase -Force | Out-Null
|
||||
Set-ItemProperty -Path $clsBase -Name "(default)" -Value $progId
|
||||
New-Item -Path "$clsBase\InprocServer32" -Force | Out-Null
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "(default)" -Value "mscoree.dll"
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "Class" -Value $progId
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "Assembly" -Value $asmName
|
||||
$codebase = "file:///" + ($dstLink.Replace('\', '/'))
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "CodeBase" -Value $codebase
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "ThreadingModel" -Value "Both"
|
||||
|
||||
$progBase = "HKCU:\Software\Classes\$progId"
|
||||
Remove-Item -Path $progBase -Recurse -Force -ErrorAction SilentlyContinue
|
||||
New-Item -Path "$progBase\CLSID" -Force | Out-Null
|
||||
Set-ItemProperty -Path "$progBase\CLSID" -Name "(default)" -Value $clsid
|
||||
Write-Host "COM 注册完成 (HKCU)"
|
||||
|
||||
# 生成 .addin
|
||||
$addinXml = @"
|
||||
<Addin Type="Standard">
|
||||
<ClassId>$clsid</ClassId>
|
||||
<ClientId>$clsid</ClientId>
|
||||
<DisplayName>Design Express Res</DisplayName>
|
||||
<Description>设计标注检查与设计数据查询工具(Core+Link 架构)</Description>
|
||||
<Assembly>$dstLink</Assembly>
|
||||
<LoadOnStartUp>1</LoadOnStartUp>
|
||||
<UserUnloadable>1</UserUnloadable>
|
||||
<Hidden>0</Hidden>
|
||||
<SupportedSoftwareVersionGreaterThan>25..</SupportedSoftwareVersionGreaterThan>
|
||||
<DataVersion>1</DataVersion>
|
||||
<UserInterfaceVersion>1</UserInterfaceVersion>
|
||||
</Addin>
|
||||
"@
|
||||
$addinFile = Join-Path $addinDir "DesignExpress.InventorLink.addin"
|
||||
[System.IO.File]::WriteAllText($addinFile, $addinXml, [System.Text.Encoding]::UTF8)
|
||||
Write-Host ".addin 已生成: $addinFile"
|
||||
|
||||
# 清理旧版本文件
|
||||
Remove-Item (Join-Path $addinDir "InventorDesignCheck.dll") -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item (Join-Path $addinDir "InventorDesignCheck.addin") -Force -ErrorAction SilentlyContinue
|
||||
|
||||
# 关键: 修复 AddInLoadRules(加载规则文件), 确保本加载项允许加载
|
||||
# 该文件为 UTF-16 二进制, 每条记录: "{GUID}" + DWORD(0=允许, 1=禁止)
|
||||
$rulesFile = Join-Path $addinDir "AddInLoadRules"
|
||||
if (Test-Path $rulesFile) {
|
||||
$b = [System.IO.File]::ReadAllBytes($rulesFile)
|
||||
$u = [System.Text.Encoding]::Unicode.GetString($b)
|
||||
$guid = "{D422E0BF-02D0-4DAE-958A-7BBA80B718E9}"
|
||||
$pos = $u.IndexOf($guid)
|
||||
if ($pos -ge 0) {
|
||||
$bytePos = $pos * 2 + $guid.Length * 2
|
||||
if ([BitConverter]::ToUInt32($b, $bytePos) -ne 0) {
|
||||
$b[$bytePos] = 0; $b[$bytePos + 1] = 0; $b[$bytePos + 2] = 0; $b[$bytePos + 3] = 0
|
||||
[System.IO.File]::WriteAllBytes($rulesFile, $b)
|
||||
Write-Host "已修复加载规则(允许加载)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "部署完成! 请重启 Inventor, 功能区将出现 [Design Express Res] 选项卡。"
|
||||
@@ -0,0 +1,59 @@
|
||||
# Design Express Res - SolidWorks Link 部署脚本 (无需管理员权限, 但 HKLM 注册需手动确认一次)
|
||||
# 说明: 首次部署后需正常退出并重启 SolidWorks 一次, 让选项卡定义持久化到注册表
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$swDir = Join-Path $env:APPDATA "DesignExpress\SolidWorks"
|
||||
$clsid = "{4A7E023E-EDD8-4642-B337-425E02394C81}"
|
||||
$progId = "DesignExpress.SolidWorksLink.SwAddin"
|
||||
$asmName = "DesignExpress.SolidWorksLink, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
|
||||
|
||||
$srcCore = Join-Path $PSScriptRoot "DesignExpress.Core.dll"
|
||||
$srcLink = Join-Path $PSScriptRoot "DesignExpress.SolidWorksLink.dll"
|
||||
if (-not (Test-Path $srcCore)) { Write-Host "未找到 DesignExpress.Core.dll"; exit 1 }
|
||||
if (-not (Test-Path $srcLink)) { Write-Host "未找到 DesignExpress.SolidWorksLink.dll"; exit 1 }
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $swDir | Out-Null
|
||||
Copy-Item -LiteralPath $srcCore -Destination (Join-Path $swDir "DesignExpress.Core.dll") -Force
|
||||
$dstLink = Join-Path $swDir "DesignExpress.SolidWorksLink.dll"
|
||||
Copy-Item -LiteralPath $srcLink -Destination $dstLink -Force
|
||||
Write-Host "DLL 已复制: $swDir"
|
||||
|
||||
# 每用户 COM 注册 (HKCU)
|
||||
$clsBase = "HKCU:\Software\Classes\CLSID\$clsid"
|
||||
Remove-Item -Path $clsBase -Recurse -Force -ErrorAction SilentlyContinue
|
||||
New-Item -Path $clsBase -Force | Out-Null
|
||||
Set-ItemProperty -Path $clsBase -Name "(default)" -Value $progId
|
||||
New-Item -Path "$clsBase\InprocServer32" -Force | Out-Null
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "(default)" -Value "mscoree.dll"
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "Class" -Value $progId
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "Assembly" -Value $asmName
|
||||
$codebase = "file:///" + ($dstLink.Replace('\', '/'))
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "CodeBase" -Value $codebase
|
||||
Set-ItemProperty -Path "$clsBase\InprocServer32" -Name "ThreadingModel" -Value "Both"
|
||||
|
||||
$progBase = "HKCU:\Software\Classes\$progId"
|
||||
Remove-Item -Path $progBase -Recurse -Force -ErrorAction SilentlyContinue
|
||||
New-Item -Path "$progBase\CLSID" -Force | Out-Null
|
||||
Set-ItemProperty -Path "$progBase\CLSID" -Name "(default)" -Value $clsid
|
||||
|
||||
# SolidWorks 加载项注册 (当前用户, 启动时加载)
|
||||
$swAddinKey = "HKCU:\Software\SolidWorks\AddIns\$clsid"
|
||||
Remove-Item -Path $swAddinKey -Recurse -Force -ErrorAction SilentlyContinue
|
||||
New-Item -Path $swAddinKey -Force | Out-Null
|
||||
Set-ItemProperty -Path $swAddinKey -Name "(default)" -Value 1 -Type DWord
|
||||
Set-ItemProperty -Path $swAddinKey -Name "Title" -Value "Design Express Res"
|
||||
Set-ItemProperty -Path $swAddinKey -Name "Description" -Value "设计标注检查与设计数据查询工具"
|
||||
|
||||
$swStartupKey = "HKCU:\Software\SolidWorks\AddInsStartup\$clsid"
|
||||
New-Item -Path $swStartupKey -Force | Out-Null
|
||||
Set-ItemProperty -Path $swStartupKey -Name "(default)" -Value 1 -Type DWord
|
||||
Write-Host "SolidWorks 加载项已注册(启动时自动加载)"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "=== 下一步(重要) ==="
|
||||
Write-Host "1. 若首次安装, 请以管理员身份导入注册表(加载项清单需要 HKLM):"
|
||||
Write-Host " reg add ""HKLM\SOFTWARE\SolidWorks\AddIns\$clsid"" /ve /t REG_SZ /d 1 /f"
|
||||
Write-Host " reg add ""HKLM\SOFTWARE\SolidWorks\AddIns\$clsid"" /v Title /t REG_SZ /d ""Design Express Res"" /f"
|
||||
Write-Host "2. 启动 SolidWorks, 在 工具→插件 中勾选 Design Express Res"
|
||||
Write-Host "3. 打开一个零件文档 -> 出现 Design Express Res 选项卡"
|
||||
Write-Host "4. 正常退出 SolidWorks 并重新打开(持久化选项卡定义)"
|
||||
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
public class CheckResult
|
||||
{
|
||||
public string Stage;
|
||||
public string Obj;
|
||||
public string CheckID;
|
||||
public string Name;
|
||||
public string Result;
|
||||
public string Note;
|
||||
public string Basis;
|
||||
}
|
||||
|
||||
public static class AppState
|
||||
{
|
||||
public static ICadHost Host;
|
||||
public static List<CheckResult> Results = new List<CheckResult>();
|
||||
|
||||
public static void Add(string stage, string obj, string id, string name,
|
||||
string result, string note, string basis = "")
|
||||
{
|
||||
Results.Add(new CheckResult
|
||||
{
|
||||
Stage = stage, Obj = obj, CheckID = id, Name = name,
|
||||
Result = result, Note = note, Basis = basis
|
||||
});
|
||||
try
|
||||
{
|
||||
if (Host != null) Host.SetStatusText("[" + stage + "] " + obj + " - " + name);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static void Count(out int pass, out int warn, out int fail, out int info)
|
||||
{
|
||||
pass = 0; warn = 0; fail = 0; info = 0;
|
||||
foreach (CheckResult r in Results)
|
||||
{
|
||||
switch (r.Result)
|
||||
{
|
||||
case "通过": pass++; break;
|
||||
case "警告": warn++; break;
|
||||
case "未通过": fail++; break;
|
||||
default: info++; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetProp(Dictionary<string, string> props, params string[] names)
|
||||
{
|
||||
if (props == null) return "";
|
||||
foreach (string n in names)
|
||||
{
|
||||
foreach (KeyValuePair<string, string> kv in props)
|
||||
{
|
||||
if (string.Equals(kv.Key, n, StringComparison.OrdinalIgnoreCase))
|
||||
return kv.Value ?? "";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public static bool IsDefaultMaterial(string s)
|
||||
{
|
||||
s = (s ?? "").Trim();
|
||||
return s == "" || s.Equals("默认", StringComparison.OrdinalIgnoreCase) ||
|
||||
s.Equals("Default", StringComparison.OrdinalIgnoreCase) ||
|
||||
s.Equals("Generic", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
// 在多个文档的属性中搜索关键词
|
||||
public static bool HitKeywords(IEnumerable<DocInfo> docs, string keys, out string hits)
|
||||
{
|
||||
hits = "";
|
||||
string[] kArr = keys.Split(',');
|
||||
foreach (DocInfo d in docs)
|
||||
{
|
||||
if (d == null) continue;
|
||||
string txt = GetProp(d.Props, "Comments", "备注", "注释", "Keywords", "关键词",
|
||||
"Description", "描述", "名称", "Title", "标题");
|
||||
foreach (string k in kArr)
|
||||
{
|
||||
if ((txt + d.Name).ToUpper().Contains(k.ToUpper()))
|
||||
{
|
||||
if (hits.Length < 300) hits += d.Name + "[" + k + "]; ";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,667 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
// 检查引擎: 只处理 DocSnapshot 纯数据, 不依赖任何 CAD 系统
|
||||
public static class CheckEngine
|
||||
{
|
||||
// ================= 零件阶段 =================
|
||||
|
||||
public static void RunPartChecks(DocSnapshot doc)
|
||||
{
|
||||
string objName = "零件";
|
||||
if (doc.Dirty)
|
||||
AppState.Add("零件", objName, "P01", "文档保存状态", "警告", "存在未保存的修改", "建议检查前保存");
|
||||
else
|
||||
AppState.Add("零件", objName, "P01", "文档保存状态", "通过", "已保存", "");
|
||||
|
||||
CheckPartProps(doc, objName);
|
||||
CheckModelAnnotations(doc, objName);
|
||||
CheckThreads(doc, objName);
|
||||
CheckMaterialContact(doc, objName);
|
||||
AppState.Add("零件", objName, "P15", "焊接标注检查", "信息",
|
||||
"模型焊接符号由工程图 D19 焊接技术要求关键词检查覆盖(双面焊/打磨/标准号)", "spec 文件");
|
||||
CheckSurfaceTreat(doc, objName);
|
||||
CheckStrength(doc, objName);
|
||||
FitCheckLoop(doc);
|
||||
}
|
||||
|
||||
private static void CheckPartProps(DocSnapshot doc, string objName)
|
||||
{
|
||||
string v;
|
||||
v = AppState.GetProp(doc.Props, "Part Number", "零件代号", "零件号", "图号");
|
||||
if (v == "") AppState.Add("零件", objName, "P02", "零件代号", "未通过", "未填写", "标题栏必填项");
|
||||
else AppState.Add("零件", objName, "P02", "零件代号", "通过", v, "");
|
||||
|
||||
v = AppState.GetProp(doc.Props, "Description", "描述", "名称", "部件名称");
|
||||
if (v == "") AppState.Add("零件", objName, "P03", "名称", "未通过", "未填写", "标题栏必填项");
|
||||
else AppState.Add("零件", objName, "P03", "名称", "通过", v, "");
|
||||
|
||||
string mat = doc.MaterialName;
|
||||
if (mat == "") mat = AppState.GetProp(doc.Props, "Material", "材料", "材质");
|
||||
if (AppState.IsDefaultMaterial(mat))
|
||||
AppState.Add("零件", objName, "P04", "材料", "未通过", "材料未指定或为默认", "配合面/接触面必须明确材料");
|
||||
else
|
||||
AppState.Add("零件", objName, "P04", "材料", "通过", mat, "");
|
||||
|
||||
v = AppState.GetProp(doc.Props, "Designer", "设计者", "设计");
|
||||
if (v == "") AppState.Add("零件", objName, "P05", "设计者", "未通过", "未填写", "");
|
||||
else AppState.Add("零件", objName, "P05", "设计者", "通过", v, "");
|
||||
|
||||
v = AppState.GetProp(doc.Props, "Checked By", "检查者", "审核者", "校核");
|
||||
if (v == "") AppState.Add("零件", objName, "P06", "审核者", "未通过", "未填写", "");
|
||||
else AppState.Add("零件", objName, "P06", "审核者", "通过", v, "");
|
||||
|
||||
v = AppState.GetProp(doc.Props, "Revision Number", "修订号", "版本号");
|
||||
if (v == "") AppState.Add("零件", objName, "P07", "修订号", "警告", "未填写修订号", "建议填写以追溯版本");
|
||||
else AppState.Add("零件", objName, "P07", "修订号", "通过", v, "");
|
||||
}
|
||||
|
||||
private static void CheckModelAnnotations(DocSnapshot doc, string objName)
|
||||
{
|
||||
ModelInfo m = doc.Model;
|
||||
if (m == null) m = new ModelInfo();
|
||||
int nDim = m.DimCount, nFcf = m.FcfCount, nTex = m.TexCount, nDat = m.DatumCount, nTn = m.ThreadNoteCount;
|
||||
|
||||
if (nDim < 0)
|
||||
AppState.Add("零件", objName, "P08", "模型标注统计", "信息", "无法读取模型标注", "");
|
||||
else if (nDim == 0)
|
||||
AppState.Add("零件", objName, "P08", "模型标注统计", "警告", "模型上没有任何尺寸标注, 建议使用三维技术标注(PMI)", "设计标注要求");
|
||||
else
|
||||
AppState.Add("零件", objName, "P08", "模型标注统计", "通过",
|
||||
"模型尺寸 " + nDim + " 个; 形位公差 " + (nFcf < 0 ? "?" : nFcf.ToString()) +
|
||||
" 个; 粗糙度 " + (nTex < 0 ? "?" : nTex.ToString()) +
|
||||
" 个; 基准 " + (nDat < 0 ? "?" : nDat.ToString()) +
|
||||
" 个; 螺纹孔标注 " + (nTn < 0 ? "?" : nTn.ToString()) + " 个", "");
|
||||
|
||||
if (nDim > 0)
|
||||
{
|
||||
if (!m.TolReadable)
|
||||
AppState.Add("零件", objName, "P08b", "尺寸公差覆盖", "信息", "部分尺寸公差信息无法读取", "");
|
||||
else if (m.TolCount == 0)
|
||||
AppState.Add("零件", objName, "P08b", "尺寸公差覆盖", "警告", nDim + " 个尺寸均未标注公差", "配合尺寸应标注公差");
|
||||
else
|
||||
AppState.Add("零件", objName, "P08b", "尺寸公差覆盖", "通过", m.TolCount + "/" + nDim + " 个尺寸带公差", "");
|
||||
}
|
||||
|
||||
if (nFcf < 0)
|
||||
AppState.Add("零件", objName, "P08c", "形位公差标注", "信息", "无法读取", "");
|
||||
else if (nFcf == 0)
|
||||
AppState.Add("零件", objName, "P08c", "形位公差标注", "警告", "模型未标注任何形位公差(如跳动/同轴度/垂直度/平面度)", "关键配合特征应标注形位公差");
|
||||
else
|
||||
AppState.Add("零件", objName, "P08c", "形位公差标注", "通过", "共 " + nFcf + " 个形位公差标注", "");
|
||||
|
||||
if (nTex < 0)
|
||||
AppState.Add("零件", objName, "P08d", "粗糙度标注", "信息", "无法读取", "");
|
||||
else if (nTex == 0)
|
||||
AppState.Add("零件", objName, "P08d", "粗糙度标注", "警告", "模型未标注表面粗糙度", "配合面/密封面应标注粗糙度");
|
||||
else
|
||||
AppState.Add("零件", objName, "P08d", "粗糙度标注", "通过", "共 " + nTex + " 个粗糙度标注(首个: " + m.FirstTexText + ")", "");
|
||||
}
|
||||
|
||||
private static void CheckThreads(DocSnapshot doc, string objName)
|
||||
{
|
||||
ModelInfo m = doc.Model;
|
||||
int n = m == null ? -1 : m.ThreadFeatureCount;
|
||||
if (n < 0)
|
||||
AppState.Add("零件", objName, "P13", "螺纹孔检查", "信息", "无法读取螺纹特征", "");
|
||||
else if (n == 0)
|
||||
AppState.Add("零件", objName, "P13", "螺纹孔检查", "通过", "无螺纹特征", "");
|
||||
else
|
||||
AppState.Add("零件", objName, "P13", "螺纹孔检查", "通过", "共 " + n + " 处螺纹特征(示例: " + m.ThreadDesignation + ")", "螺纹代号/深度/攻深需在工程图中完整标注");
|
||||
}
|
||||
|
||||
private static void CheckMaterialContact(DocSnapshot doc, string objName)
|
||||
{
|
||||
string v = AppState.GetProp(doc.Props, "物料接触", "接触类别", "接触", "ContactClass", "MaterialContact");
|
||||
bool direct = false;
|
||||
if (v != "")
|
||||
{
|
||||
if (v.Contains("直接")) direct = true;
|
||||
AppState.Add("零件", objName, "P14", "物料接触检查", "通过",
|
||||
direct ? "属性标注: 直接接触 (需满足 GMP 材料/粗糙度/无死角要求)" : "属性标注: " + v,
|
||||
direct ? "GMP" : "");
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleInput f = new SimpleInput("物料接触", "该零件是否与物料接触?\r\n1=直接接触\r\n2=间接接触(外表/非接触面)\r\n3=非接触\r\n0=跳过", "1");
|
||||
if (f.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
int ans = 0;
|
||||
int.TryParse(f.Value.Trim(), out ans);
|
||||
switch (ans)
|
||||
{
|
||||
case 1: direct = true;
|
||||
AppState.Add("零件", objName, "P14", "物料接触检查", "通过", "人工确认: 直接接触", "建议在 iProperties 自定义属性中标注'物料接触=直接接触'以固化");
|
||||
break;
|
||||
case 2: AppState.Add("零件", objName, "P14", "物料接触检查", "通过", "人工确认: 间接接触", ""); break;
|
||||
case 3: AppState.Add("零件", objName, "P14", "物料接触检查", "通过", "人工确认: 非接触", ""); break;
|
||||
default: AppState.Add("零件", objName, "P14", "物料接触检查", "警告", "未声明物料接触类别, 无法执行 GMP 专项检查", "建议标注接触类别"); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
AppState.Add("零件", objName, "P14", "物料接触检查", "警告", "未声明物料接触类别, 无法执行 GMP 专项检查", "建议标注接触类别");
|
||||
}
|
||||
|
||||
if (direct)
|
||||
{
|
||||
string mat = doc.MaterialName;
|
||||
if (mat == "") mat = AppState.GetProp(doc.Props, "Material", "材料", "材质");
|
||||
if (AppState.IsDefaultMaterial(mat))
|
||||
AppState.Add("零件", objName, "P14b", "GMP 接触材料", "未通过", "材料未指定或为默认", "直接接触物料必须用卫生级不锈钢(316L)");
|
||||
else
|
||||
{
|
||||
string rec, basis, vv;
|
||||
vv = KB.GmpMaterialJudge(mat, out rec, out basis);
|
||||
AppState.Add("零件", objName, "P14b", "GMP 接触材料", vv, "材料: " + mat + "; " + rec, basis);
|
||||
}
|
||||
|
||||
ModelInfo m = doc.Model;
|
||||
int nTex = m == null ? 0 : m.TexCount;
|
||||
if (nTex > 0)
|
||||
AppState.Add("零件", objName, "P14c", "GMP 接触面粗糙度", "通过", "已标注粗糙度(共 " + nTex + " 个)", "接触面 Ra<=0.8");
|
||||
else
|
||||
AppState.Add("零件", objName, "P14c", "GMP 接触面粗糙度", "未通过", "接触面未标注粗糙度", "接触面 Ra<=0.8");
|
||||
|
||||
if (m == null || !m.MinFilletReadable)
|
||||
AppState.Add("零件", objName, "P14d", "GMP 无死角检查", "信息", "无法读取圆角特征", "");
|
||||
else if (m.MinFilletRadiusMM > 0 && m.MinFilletRadiusMM < 10)
|
||||
AppState.Add("零件", objName, "P14d", "GMP 无死角检查", "警告",
|
||||
"存在小于 R10 的圆角(最小 R" + m.MinFilletRadiusMM.ToString("0.0") + " mm), 夹角处易积料",
|
||||
"GMP: 夹角处圆角>=R10, 内夹角>=135度");
|
||||
else
|
||||
AppState.Add("零件", objName, "P14d", "GMP 无死角检查", "通过",
|
||||
m.MinFilletRadiusMM > 0 ? "最小圆角 R" + m.MinFilletRadiusMM.ToString("0.0") + " mm >= R10" : "未发现圆角特征, 请人工确认",
|
||||
"GMP 无死角要求");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckSurfaceTreat(DocSnapshot doc, string objName)
|
||||
{
|
||||
string v = AppState.GetProp(doc.Props, "表面处理", "表面", "Surfacing", "镀层", "防锈", "SurfaceTreatment");
|
||||
if (v == "") v = AppState.GetProp(doc.Props, "Comments", "备注", "注释");
|
||||
if (v != "" && (v.Contains("镀") || v.Contains("氧化") || v.Contains("抛光") ||
|
||||
v.Contains("防锈") || v.Contains("发黑") || v.Contains("喷砂")))
|
||||
AppState.Add("零件", objName, "P16", "表面处理/防锈", "通过", v, "");
|
||||
else
|
||||
AppState.Add("零件", objName, "P16", "表面处理/防锈", "警告", "未标注表面处理/防锈要求(如镀镍是否需磨削/抛光、防锈包装)", "请确认是否适用");
|
||||
}
|
||||
|
||||
private static void CheckStrength(DocSnapshot doc, string objName)
|
||||
{
|
||||
string mat = doc.MaterialName;
|
||||
if (mat == "") mat = AppState.GetProp(doc.Props, "Material", "材料", "材质");
|
||||
if (AppState.IsDefaultMaterial(mat))
|
||||
AppState.Add("零件", objName, "P17", "结构强度/仿真", "未通过", "材料未指定, 无法进行强度分析", "需先指定材料");
|
||||
else
|
||||
AppState.Add("零件", objName, "P17", "结构强度/仿真", "信息",
|
||||
"材料: " + mat + "; 建议使用 CAD 内置应力分析或导出模型进行有限元/仿真校核", "AI/CAE 校核指引");
|
||||
}
|
||||
|
||||
private static void FitCheckLoop(DocSnapshot doc)
|
||||
{
|
||||
SimpleInput ask = new SimpleInput("公差配合检查", "是否进行公差配合检查?\r\n1=是\r\n0=否(跳过)", "1");
|
||||
if (ask.ShowDialog() != DialogResult.OK) return;
|
||||
int go = 0;
|
||||
int.TryParse(ask.Value.Trim(), out go);
|
||||
if (go != 1)
|
||||
{
|
||||
AppState.Add("零件", "零件", "P09", "公差配合检查", "信息", "用户跳过配合检查", "");
|
||||
return;
|
||||
}
|
||||
|
||||
ICadHost host = AppState.Host;
|
||||
while (true)
|
||||
{
|
||||
double diaMM = 0;
|
||||
string faceName = "手动输入";
|
||||
try
|
||||
{
|
||||
if (host != null) diaMM = host.PickCylinderDiameterMM(out faceName);
|
||||
}
|
||||
catch { diaMM = 0; }
|
||||
if (diaMM <= 0)
|
||||
{
|
||||
SimpleInput di = new SimpleInput("公差配合检查", "请输入配合直径 (mm):", "30");
|
||||
if (di.ShowDialog() != DialogResult.OK) return;
|
||||
double.TryParse(di.Value.Trim(), out diaMM);
|
||||
if (diaMM <= 0) return;
|
||||
}
|
||||
|
||||
FitForm form = new FitForm(diaMM, faceName);
|
||||
if (form.ShowDialog() != DialogResult.OK) break;
|
||||
|
||||
foreach (FitItem it in form.Items)
|
||||
{
|
||||
string verdict = it.Verdict;
|
||||
int seg = KB.SegIndex(it.DiaMM);
|
||||
string note = "配合面: " + faceName + "; 直径 " + it.DiaMM.ToString("0.0") + " mm" +
|
||||
(seg < 0 ? " (>500mm 超出表范围)" : " (尺寸段 " + KB.SegName(seg) + ")") +
|
||||
"; 实际代码 " + it.Code + "; 推荐 " + it.Recommend + "; " + verdict;
|
||||
AppState.Add("零件", "零件", "P09", "公差配合检查(" + it.Role + ")", verdict, note, it.Basis);
|
||||
FitAdjacentChecks(doc, it.Role, it.DiaMM, faceName);
|
||||
}
|
||||
|
||||
if (MessageBox.Show("配合检查结果已加入。是否继续检查其他配合面?", "公差配合检查",
|
||||
MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void FitAdjacentChecks(DocSnapshot doc, string role, double diaMM, string faceName)
|
||||
{
|
||||
string objName = "零件(" + faceName + ")";
|
||||
ModelInfo m = doc.Model;
|
||||
int nFcf = m == null ? 0 : m.FcfCount;
|
||||
int nTex = m == null ? 0 : m.TexCount;
|
||||
if (nFcf > 0)
|
||||
AppState.Add("零件", objName, "P10", "配合面形位公差", "通过", "模型已标注形位公差(共 " + nFcf + " 个)", "轴承位建议标注径向跳动/同轴度, 等级 IT5~IT6");
|
||||
else
|
||||
AppState.Add("零件", objName, "P10", "配合面形位公差", "未通过", "配合面未标注形位公差", "轴承轴颈建议标注径向跳动/同轴度(IT5~IT6); 座孔标注同轴度/垂直度");
|
||||
|
||||
if (nTex > 0)
|
||||
AppState.Add("零件", objName, "P11", "配合面粗糙度", "通过", "已标注粗糙度(共 " + nTex + " 个)", "推荐: " + KB.RaSuggest(role));
|
||||
else
|
||||
AppState.Add("零件", objName, "P11", "配合面粗糙度", "未通过", "配合面未标注表面粗糙度", "推荐: " + KB.RaSuggest(role));
|
||||
|
||||
if (role.StartsWith("轴承"))
|
||||
{
|
||||
int seg = KB.SegIndex(diaMM);
|
||||
string tolNote;
|
||||
if (seg > 0)
|
||||
tolNote = "尺寸段 " + KB.SegName(seg) + " 对应 IT6=" + KB.ItTol(6, seg) + "um, IT7=" + KB.ItTol(7, seg) + "um";
|
||||
else
|
||||
tolNote = "直径超过 500mm, 无内置数据";
|
||||
AppState.Add("零件", objName, "P12", "轴承位公差等级", "信息", tolNote, "轴承轴颈公差等级一般取 IT5~IT6, 座孔 IT7");
|
||||
}
|
||||
}
|
||||
|
||||
// ================= 装配阶段 =================
|
||||
|
||||
public static void RunAssemblyChecks(DocSnapshot doc)
|
||||
{
|
||||
string objName = "装配";
|
||||
if (doc.Dirty)
|
||||
AppState.Add("装配", objName, "A01", "文档保存状态", "警告", "存在未保存的修改", "");
|
||||
else
|
||||
AppState.Add("装配", objName, "A01", "文档保存状态", "通过", "已保存", "");
|
||||
|
||||
GmpMaterialCheck(doc, objName);
|
||||
SealCheck(doc, objName);
|
||||
CleanCheck(doc, objName);
|
||||
GmpRoughnessCheck(doc, objName);
|
||||
InterferenceCheck(doc, objName);
|
||||
StandardPartsCheck(doc, objName);
|
||||
ElectricsCheck(doc, objName);
|
||||
UtilityCheck(doc, objName);
|
||||
AppState.Add("装配", objName, "A12", "运动干涉(动态)", "信息",
|
||||
"建议使用 CAD 驱动约束/运动仿真验证运动干涉; 本工具提供静态干涉结果", "运动学检查需要仿真环境");
|
||||
}
|
||||
|
||||
private static void GmpMaterialCheck(DocSnapshot doc, string objName)
|
||||
{
|
||||
int nPart = 0, nOk = 0, nWarn = 0, nBad = 0;
|
||||
string badList = "";
|
||||
foreach (DocInfo d in doc.OpenDocs)
|
||||
{
|
||||
if (d == null) continue;
|
||||
nPart++;
|
||||
string rec, basis, v;
|
||||
v = KB.GmpMaterialJudge(d.Material, out rec, out basis);
|
||||
if (v == "合理") nOk++;
|
||||
else if (v == "可接受" || v == "警告") nWarn++;
|
||||
else nBad++;
|
||||
if (v != "合理" && badList.Length < 400)
|
||||
badList += d.Name + "(" + d.Material + "): " + rec + " | ";
|
||||
}
|
||||
if (nPart == 0)
|
||||
AppState.Add("装配", objName, "A02", "GMP 材料合规", "信息", "未发现已加载的零件文档(仅检查已打开文档)", "");
|
||||
else if (nBad == 0 && nWarn == 0)
|
||||
AppState.Add("装配", objName, "A02", "GMP 材料合规", "通过", "全部 " + nPart + " 个零件材料符合 GMP 要求", "GMP 设备设计规范");
|
||||
else if (nBad == 0)
|
||||
AppState.Add("装配", objName, "A02", "GMP 材料合规", "警告", nWarn + "/" + nPart + " 个零件材料需关注: " + badList, "GMP 设备设计规范");
|
||||
else
|
||||
AppState.Add("装配", objName, "A02", "GMP 材料合规", "未通过", nBad + " 个零件材料不合格, " + nWarn + " 个需关注: " + badList, "GMP 设备设计规范");
|
||||
}
|
||||
|
||||
private static void SealCheck(DocSnapshot doc, string objName)
|
||||
{
|
||||
string names = "";
|
||||
int n = 0;
|
||||
AssemblyInfo asm = doc.Asm;
|
||||
if (asm != null)
|
||||
{
|
||||
foreach (string nm in asm.OccurrenceNames)
|
||||
{
|
||||
if (KB.IsSealPartName(nm))
|
||||
{
|
||||
n++;
|
||||
if (names.Length < 300) names += nm + "; ";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (n > 0)
|
||||
{
|
||||
AppState.Add("装配", objName, "A03", "密封件存在性", "通过", "发现 " + n + " 个密封元件: " + names, "GMP 密封要求");
|
||||
AppState.Add("装配", objName, "A04", "密封设计提示", "信息",
|
||||
"请核对: 密封槽尺寸是否符合 GB/T 3452.3(O型圈槽); 密封材料需符合 FDA 要求; 动密封面 Ra<=0.8", "GB/T 3452.3");
|
||||
}
|
||||
else
|
||||
{
|
||||
DialogResult ans = MessageBox.Show("未在装配中发现密封元件(名称不含 密封圈/O型圈/垫片 等关键词)。\r\n该设备是否需要密封设计?",
|
||||
"密封检查", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
||||
if (ans == DialogResult.Yes)
|
||||
AppState.Add("装配", objName, "A03", "密封件存在性", "未通过", "未发现密封元件, 需补充密封设计或确认命名规范", "GMP 密封要求");
|
||||
else
|
||||
AppState.Add("装配", objName, "A03", "密封件存在性", "通过", "无密封要求(用户确认)", "");
|
||||
}
|
||||
}
|
||||
|
||||
private static void CleanCheck(DocSnapshot doc, string objName)
|
||||
{
|
||||
string hits;
|
||||
List<DocInfo> docs = new List<DocInfo>();
|
||||
docs.Add(new DocInfo { Name = doc.DisplayName, Props = doc.Props, Material = doc.MaterialName });
|
||||
docs.AddRange(doc.OpenDocs);
|
||||
if (AppState.HitKeywords(docs, "清洁,清洗,CIP,SIP,死角,排空,卫生,可清洗", out hits))
|
||||
AppState.Add("装配", objName, "A05", "清洁性设计要求", "通过", "已体现清洁性设计说明: " + hits, "GMP 清洁性要求");
|
||||
else
|
||||
AppState.Add("装配", objName, "A05", "清洁性设计要求", "警告", "未在文档属性中发现清洁/清洗/CIP/死角等设计要求说明", "GMP 要求: 设备应可清洁、无死角、易排空");
|
||||
}
|
||||
|
||||
private static void GmpRoughnessCheck(DocSnapshot doc, string objName)
|
||||
{
|
||||
string noTex = "";
|
||||
int nPart = 0, nWith = 0;
|
||||
foreach (DocInfo d in doc.OpenDocs)
|
||||
{
|
||||
if (d == null) continue;
|
||||
nPart++;
|
||||
if (d.TexCount > 0) nWith++;
|
||||
else if (noTex.Length < 300) noTex += d.Name + "; ";
|
||||
}
|
||||
if (nPart == 0)
|
||||
AppState.Add("装配", objName, "A06", "GMP 粗糙度标注", "信息", "未发现已加载的零件文档", "");
|
||||
else if (nWith == nPart)
|
||||
AppState.Add("装配", objName, "A06", "GMP 粗糙度标注", "通过", "所有 " + nPart + " 个零件均标注了粗糙度", "GMP 接触面 Ra<=0.8");
|
||||
else
|
||||
AppState.Add("装配", objName, "A06", "GMP 粗糙度标注", "警告", (nPart - nWith) + "/" + nPart + " 个零件未标注粗糙度: " + noTex, "GMP 接触面 Ra<=0.8; 建议物料接触面电解抛光");
|
||||
}
|
||||
|
||||
private static void InterferenceCheck(DocSnapshot doc, string objName)
|
||||
{
|
||||
AssemblyInfo asm = doc.Asm;
|
||||
if (asm == null)
|
||||
{
|
||||
AppState.Add("装配", objName, "A07", "静态干涉", "信息", "无法读取装配信息", "");
|
||||
return;
|
||||
}
|
||||
if (asm.InterferenceState == 2)
|
||||
{
|
||||
AppState.Add("装配", objName, "A07", "静态干涉", "信息", "干涉分析执行失败(" + asm.InterferenceError + "), 请使用 CAD 自带干涉检查验证", "");
|
||||
return;
|
||||
}
|
||||
if (asm.InterferenceState == 0)
|
||||
AppState.Add("装配", objName, "A07", "静态干涉", "通过", "未发现静态干涉(共检查 " + asm.TopLevelCount + " 个顶层零部件)", "干涉检查");
|
||||
else
|
||||
{
|
||||
string detail = "";
|
||||
for (int j = 0; j < asm.Interferences.Count && detail.Length < 300; j++)
|
||||
{
|
||||
InterferencePair p = asm.Interferences[j];
|
||||
detail += p.Name1 + " 与 " + p.Name2 + " 体积 " + p.VolumeCM3.ToString("0.00") + "cm3; ";
|
||||
}
|
||||
AppState.Add("装配", objName, "A07", "静态干涉", "未通过", "发现 " + asm.Interferences.Count + " 处静态干涉: " + detail, "干涉检查");
|
||||
}
|
||||
}
|
||||
|
||||
private static void StandardPartsCheck(DocSnapshot doc, string objName)
|
||||
{
|
||||
AssemblyInfo asm = doc.Asm;
|
||||
string stdNames = "";
|
||||
int stdN = 0, totalN = 0;
|
||||
if (asm != null)
|
||||
{
|
||||
totalN = asm.OccurrenceNames.Count;
|
||||
foreach (string nm in asm.OccurrenceNames)
|
||||
{
|
||||
if (KB.IsStdPartName(nm))
|
||||
{
|
||||
stdN++;
|
||||
if (stdNames.Length < 200) stdNames += nm + "; ";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (totalN == 0)
|
||||
AppState.Add("装配", objName, "A09", "外购件优先", "信息", "未统计到零部件", "");
|
||||
else
|
||||
{
|
||||
double ratio = (double)stdN / (double)totalN;
|
||||
AppState.Add("装配", objName, "A09", "外购件优先", "通过",
|
||||
"标准/外购件 " + stdN + "/" + totalN + " (" + ratio.ToString("0%") + "): " + stdNames, "优先选用标准外购件");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ElectricsCheck(DocSnapshot doc, string objName)
|
||||
{
|
||||
string hits;
|
||||
List<DocInfo> docs = new List<DocInfo>();
|
||||
docs.Add(new DocInfo { Name = doc.DisplayName, Props = doc.Props, Material = doc.MaterialName });
|
||||
docs.AddRange(doc.OpenDocs);
|
||||
if (AppState.HitKeywords(docs, "西门子,SIEMENS,联网,以太网,PROFINET,PLC,IP65,防爆,电气,变频器,伺服", out hits))
|
||||
AppState.Add("装配", objName, "A10", "电气选型/西门子联网", "通过", hits, "电气元件选型技术要求");
|
||||
else
|
||||
AppState.Add("装配", objName, "A10", "电气选型/西门子联网", "警告", "未发现电气选型/西门子联网相关说明", "如涉及电气元件, 需注明选型及联网(如西门子 PROFINET)要求");
|
||||
}
|
||||
|
||||
private static void UtilityCheck(DocSnapshot doc, string objName)
|
||||
{
|
||||
string hits;
|
||||
List<DocInfo> docs = new List<DocInfo>();
|
||||
docs.Add(new DocInfo { Name = doc.DisplayName, Props = doc.Props, Material = doc.MaterialName });
|
||||
docs.AddRange(doc.OpenDocs);
|
||||
if (AppState.HitKeywords(docs, "施工,动力,公用工程,压缩空气,纯化水,蒸汽,排风,水电气,安装要求,配孔,吊顶", out hits))
|
||||
AppState.Add("装配", objName, "A11", "施工/公共动力系统", "通过", hits, "施工及公用动力安装技术要求");
|
||||
else
|
||||
AppState.Add("装配", objName, "A11", "施工/公共动力系统", "警告", "未发现施工/公共动力系统相关说明(压缩空气/纯化水/蒸汽/排风/配孔/吊顶等)", "如涉及需补充技术要求");
|
||||
}
|
||||
|
||||
// ================= 工程图阶段 =================
|
||||
|
||||
private class SpecGroup
|
||||
{
|
||||
public string ID;
|
||||
public string Name;
|
||||
public string Keys;
|
||||
}
|
||||
|
||||
private static readonly SpecGroup[] Specs = new SpecGroup[]
|
||||
{
|
||||
new SpecGroup { ID = "D18", Name = "物料接触类别声明", Keys = "接触,物料接触,直接接触,间接接触,接触类别" },
|
||||
new SpecGroup { ID = "D19", Name = "焊接技术要求", Keys = "焊接,双面焊,单面焊,打磨,焊缝,焊接标准" },
|
||||
new SpecGroup { ID = "D20", Name = "死角/夹角要求", Keys = "死角,无死角,夹角,圆角,清洁,排空,R10,135" },
|
||||
new SpecGroup { ID = "D21", Name = "公差要求完整性", Keys = "公差,配合,精度,未注公差" },
|
||||
new SpecGroup { ID = "D22", Name = "轴承位公差标注", Keys = "轴承,跳动,同轴,旋转精度" },
|
||||
new SpecGroup { ID = "D23", Name = "螺纹孔标注", Keys = "螺纹,螺孔,攻丝,丝锥,M6,M8,M10,M12,M16" },
|
||||
new SpecGroup { ID = "D24", Name = "表面处理/镀镍", Keys = "镀镍,镀铬,镀锌,电镀,抛光,表面处理,磨床,磨削,防锈,发黑,阳极氧化" },
|
||||
new SpecGroup { ID = "D25", Name = "平面度/平行度", Keys = "平面度,平行度,垂直度" },
|
||||
new SpecGroup { ID = "D26", Name = "特殊角度管加工", Keys = "角度管,弯管,折弯,倾斜,特殊角度" },
|
||||
new SpecGroup { ID = "D27", Name = "装配治具与检验", Keys = "治具,检具,检验,检测,夹具" },
|
||||
new SpecGroup { ID = "D28", Name = "加工辅助件要求", Keys = "辅助件,工艺,毛坯,余量,加工基准" },
|
||||
new SpecGroup { ID = "D29", Name = "外购件优先", Keys = "外购,标准件,优先采购" },
|
||||
new SpecGroup { ID = "D30", Name = "测试要求", Keys = "测试,试验,试压,气密,检漏,出厂测试" },
|
||||
new SpecGroup { ID = "D31", Name = "装配要求", Keys = "装配,安装,扭矩,紧固,间隙" },
|
||||
new SpecGroup { ID = "D32", Name = "防锈要求", Keys = "防锈,防锈油,防锈剂,包装,海运,真空包装" },
|
||||
new SpecGroup { ID = "D33", Name = "施工/公共动力系统", Keys = "施工,动力,公用工程,水电气,压缩空气,蒸汽,纯化水,排风" },
|
||||
new SpecGroup { ID = "D34", Name = "配孔技术要求", Keys = "配孔,配钻,现场配,扩孔" },
|
||||
new SpecGroup { ID = "D35", Name = "吊顶配件要求", Keys = "吊顶,吊架,吊装,悬挂" },
|
||||
new SpecGroup { ID = "D36", Name = "电气元件选型", Keys = "电气,元件,选型,防爆,防护等级,IP65" },
|
||||
new SpecGroup { ID = "D37", Name = "西门子联网器件", Keys = "西门子,SIEMENS,联网,以太网,PROFINET,总线" },
|
||||
new SpecGroup { ID = "D38", Name = "结构强度/仿真", Keys = "强度,仿真,有限元,FEA,应力" },
|
||||
new SpecGroup { ID = "D39", Name = "夹角R10/135度确认", Keys = "夹角,135,R10,圆角" }
|
||||
};
|
||||
|
||||
public static void RunDrawingChecks(DocSnapshot doc)
|
||||
{
|
||||
string objName = "工程图";
|
||||
if (doc.Dirty)
|
||||
AppState.Add("工程图", objName, "D00", "文档保存状态", "警告", "存在未保存的修改", "");
|
||||
else
|
||||
AppState.Add("工程图", objName, "D00", "文档保存状态", "通过", "已保存", "");
|
||||
|
||||
int idx = 0;
|
||||
foreach (SheetInfo sh in doc.Sheets)
|
||||
{
|
||||
idx++;
|
||||
CheckSheet(doc, sh, idx);
|
||||
}
|
||||
RunSpecChecks(doc);
|
||||
}
|
||||
|
||||
private static void CheckSheet(DocSnapshot doc, SheetInfo sh, int idx)
|
||||
{
|
||||
string objName = "图纸" + idx + "(" + sh.Name + ")";
|
||||
|
||||
if (!sh.HasBorder && !sh.HasTitleBlock)
|
||||
AppState.Add("工程图", objName, "D01", "图框", "未通过", "图纸没有图框/标题栏", "");
|
||||
else if (!sh.HasTitleBlock)
|
||||
AppState.Add("工程图", objName, "D01", "图框", "警告", "有图框但无标题栏", "");
|
||||
else
|
||||
AppState.Add("工程图", objName, "D01", "图框", "通过", "标题栏: " + sh.TitleBlockName, "");
|
||||
|
||||
CheckTitleBlockProps(doc, objName);
|
||||
|
||||
int nViews = sh.ViewCount;
|
||||
int nAnn = sh.DimCount + sh.FcfCount + sh.TexCount + sh.CenterlineCount + sh.BalloonCount + sh.NotesTexts.Count;
|
||||
if (nViews == 0 && nAnn == 0)
|
||||
AppState.Add("工程图", objName, "D03", "空白图纸", "未通过", "图纸无视图且无任何标注", "");
|
||||
else
|
||||
AppState.Add("工程图", objName, "D03", "空白图纸", "通过", "视图 " + nViews + " 个, 标注 " + nAnn + " 个", "");
|
||||
|
||||
if (sh.UpdateError > 0)
|
||||
AppState.Add("工程图", objName, "D04", "视图更新状态", "未通过", sh.UpdateError + " 个视图更新出错", "");
|
||||
else if (sh.UpdateNeeded > 0)
|
||||
AppState.Add("工程图", objName, "D04", "视图更新状态", "未通过", sh.UpdateNeeded + " 个视图需要更新", "出图前必须更新视图");
|
||||
else
|
||||
AppState.Add("工程图", objName, "D04", "视图更新状态", "通过", "所有视图已更新", "");
|
||||
|
||||
AppState.Add("工程图", objName, "D05", "剖视图统计", "通过", "共 " + sh.SectionCount + " 个剖视图", "剖视图需带剖面线及剖切位置标注");
|
||||
|
||||
if (sh.BorderRect != null)
|
||||
{
|
||||
int nOut = 0;
|
||||
foreach (RectD r in sh.ViewRects)
|
||||
{
|
||||
if (RectOut(r, sh.BorderRect, 0.5)) nOut++;
|
||||
}
|
||||
if (nOut > 0)
|
||||
AppState.Add("工程图", objName, "D06", "视图越界", "未通过", nOut + " 个视图超出图框", "");
|
||||
else
|
||||
AppState.Add("工程图", objName, "D06", "视图越界", "通过", "视图均在图框内", "");
|
||||
}
|
||||
else
|
||||
AppState.Add("工程图", objName, "D06", "视图越界", "信息", "无图框可参考, 跳过", "");
|
||||
|
||||
AppState.Add("工程图", objName, "D07", "尺寸数量", "通过", "共 " + sh.DimCount + " 个尺寸", "");
|
||||
if (sh.DimCount == 0)
|
||||
AppState.Add("工程图", objName, "D08", "尺寸公差", "信息", "无尺寸可统计", "");
|
||||
else if (sh.DimTolCount == 0 && sh.DimCount >= 5)
|
||||
AppState.Add("工程图", objName, "D08", "尺寸公差", "警告", "共 " + sh.DimCount + " 个尺寸均未标注公差", "配合/关键尺寸必须标注公差");
|
||||
else
|
||||
AppState.Add("工程图", objName, "D08", "尺寸公差", "通过", sh.DimTolCount + "/" + sh.DimCount + " 个尺寸带公差", "");
|
||||
if (sh.DimQuestionCount > 0)
|
||||
AppState.Add("工程图", objName, "D09", "尺寸文本异常", "未通过", sh.DimQuestionCount + " 个尺寸文本含\"?\"(测量失败或未更新)", "");
|
||||
else
|
||||
AppState.Add("工程图", objName, "D09", "尺寸文本异常", "通过", "尺寸文本正常", "");
|
||||
|
||||
AppState.Add("工程图", objName, "D10", "形位公差", "通过", "共 " + sh.FcfCount + " 个", "");
|
||||
AppState.Add("工程图", objName, "D11", "基准符号", "信息", "CAD API 不支持自动读取基准符号, 请人工核对", "");
|
||||
AppState.Add("工程图", objName, "D12", "表面粗糙度", "通过", "共 " + sh.TexCount + " 个", "");
|
||||
AppState.Add("工程图", objName, "D13", "焊接符号", "信息", "CAD API 不支持自动读取焊接符号, 由 D19 焊接技术要求关键词检查覆盖", "spec 文件");
|
||||
AppState.Add("工程图", objName, "D14", "孔标注", "信息", "CAD API 不支持自动读取孔标注, 由 D23 螺纹孔关键词检查覆盖", "spec 文件");
|
||||
AppState.Add("工程图", objName, "D15", "中心线/件号", "通过", "中心线 " + sh.CenterlineCount + " 个, 件号 " + sh.BalloonCount + " 个", "");
|
||||
|
||||
if (sh.BorderRect != null)
|
||||
{
|
||||
int nOut = 0;
|
||||
string firstNote = "";
|
||||
foreach (RectD r in sh.FcfRects)
|
||||
{
|
||||
if (RectOut(r, sh.BorderRect, 0.2)) { nOut++; if (firstNote == "") firstNote = "形位公差"; }
|
||||
}
|
||||
foreach (RectD r in sh.TexRects)
|
||||
{
|
||||
if (RectOut(r, sh.BorderRect, 0.2)) { nOut++; if (firstNote == "") firstNote = "粗糙度"; }
|
||||
}
|
||||
if (nOut > 0)
|
||||
AppState.Add("工程图", objName, "D16", "标注越界", "未通过", nOut + " 个标注超出图框, 如: " + firstNote, "");
|
||||
else
|
||||
AppState.Add("工程图", objName, "D16", "标注越界", "通过", "标注均在图框内", "");
|
||||
}
|
||||
else
|
||||
AppState.Add("工程图", objName, "D16", "标注越界", "信息", "无图框可参考, 跳过", "");
|
||||
|
||||
AppState.Add("工程图", objName, "D17", "图幅", "信息", sh.SheetWidth + " x " + sh.SheetHeight + " (cm)", "");
|
||||
}
|
||||
|
||||
private static bool RectOut(RectD r, RectD b, double margin)
|
||||
{
|
||||
if (r == null || b == null) return false;
|
||||
return (r.L < b.L - margin) || (r.T < b.T - margin) || (r.R > b.R + margin) || (r.B > b.B + margin);
|
||||
}
|
||||
|
||||
private static void CheckTitleBlockProps(DocSnapshot doc, string objName)
|
||||
{
|
||||
string missing = "";
|
||||
string v = AppState.GetProp(doc.Props, "Part Number", "零件代号", "零件号", "图号");
|
||||
if (v == "") missing += "零件代号/图号 ";
|
||||
v = AppState.GetProp(doc.Props, "Description", "描述", "名称", "部件名称");
|
||||
if (v == "") missing += "名称 ";
|
||||
v = AppState.GetProp(doc.Props, "Material", "材料", "材质");
|
||||
if (v == "") missing += "材料 ";
|
||||
v = AppState.GetProp(doc.Props, "Designer", "设计者", "设计");
|
||||
if (v == "") missing += "设计者 ";
|
||||
v = AppState.GetProp(doc.Props, "Checked By", "检查者", "审核者", "校核");
|
||||
if (v == "") missing += "审核者 ";
|
||||
v = AppState.GetProp(doc.Props, "Revision Number", "修订号", "版本号");
|
||||
if (v == "") missing += "修订号 ";
|
||||
if (missing == "")
|
||||
AppState.Add("工程图", objName, "D02", "标题栏属性", "通过", "图号/名称/材料/设计者/审核者/修订号 均已填写", "");
|
||||
else
|
||||
AppState.Add("工程图", objName, "D02", "标题栏属性", "未通过", "未填写: " + missing, "标题栏信息完整性");
|
||||
}
|
||||
|
||||
private static void RunSpecChecks(DocSnapshot doc)
|
||||
{
|
||||
string notes = "";
|
||||
foreach (SheetInfo sh in doc.Sheets)
|
||||
{
|
||||
foreach (string t in sh.NotesTexts)
|
||||
notes += " " + t;
|
||||
}
|
||||
notes += " " + AppState.GetProp(doc.Props, "Comments", "备注", "注释", "Keywords", "关键词", "Description", "描述");
|
||||
|
||||
foreach (SpecGroup g in Specs)
|
||||
{
|
||||
string[] keys = g.Keys.Split(',');
|
||||
bool found = false;
|
||||
string hitKey = "";
|
||||
foreach (string k in keys)
|
||||
{
|
||||
if (notes.ToUpper().Contains(k.ToUpper()))
|
||||
{
|
||||
found = true;
|
||||
hitKey = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
AppState.Add("工程图", "工程图", g.ID, g.Name, "通过", "图纸中已标注相关要求(关键词: " + hitKey + ")", "spec 文件");
|
||||
else
|
||||
AppState.Add("工程图", "工程图", g.ID, g.Name, "警告", "图纸技术要求中未发现[" + g.Name + "]相关要求, 如适用请补充标注或人工确认", "spec 文件");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
// Core 统一入口: 供各 CAD Link 调用(Inventor/Creo/SolidWorks)
|
||||
public static class Checks
|
||||
{
|
||||
private static MainForm mForm;
|
||||
|
||||
private static void EnsureForm()
|
||||
{
|
||||
if (mForm == null || mForm.IsDisposed)
|
||||
mForm = new MainForm();
|
||||
}
|
||||
|
||||
private static bool Prepare(out DocSnapshot snap, params string[] allowKinds)
|
||||
{
|
||||
snap = null;
|
||||
ICadHost host = AppState.Host;
|
||||
if (host == null) return false;
|
||||
object doc = host.GetActiveDocument();
|
||||
if (doc == null)
|
||||
{
|
||||
MessageBox.Show("请先打开文档", "Design Express Res", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
||||
return false;
|
||||
}
|
||||
string kind = host.GetDocType(doc);
|
||||
bool ok = false;
|
||||
foreach (string k in allowKinds)
|
||||
{
|
||||
if (kind == k) ok = true;
|
||||
}
|
||||
if (!ok)
|
||||
{
|
||||
MessageBox.Show("当前文档类型不支持该检查", "Design Express Res", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
||||
return false;
|
||||
}
|
||||
try { snap = host.Capture(doc); }
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("读取文档失败: " + ex.Message, "Design Express Res", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return false;
|
||||
}
|
||||
return snap != null;
|
||||
}
|
||||
|
||||
public static void PartCheck()
|
||||
{
|
||||
DocSnapshot snap;
|
||||
if (!Prepare(out snap, "Part", "Assembly")) return;
|
||||
EnsureForm();
|
||||
mForm.Show();
|
||||
mForm.Activate();
|
||||
mForm.RunAndLoad("零件", delegate { CheckEngine.RunPartChecks(snap); });
|
||||
}
|
||||
|
||||
public static void AssemblyCheck()
|
||||
{
|
||||
DocSnapshot snap;
|
||||
if (!Prepare(out snap, "Assembly")) return;
|
||||
EnsureForm();
|
||||
mForm.Show();
|
||||
mForm.Activate();
|
||||
mForm.RunAndLoad("装配", delegate { CheckEngine.RunAssemblyChecks(snap); });
|
||||
}
|
||||
|
||||
public static void DrawingCheck()
|
||||
{
|
||||
DocSnapshot snap;
|
||||
if (!Prepare(out snap, "Drawing")) return;
|
||||
EnsureForm();
|
||||
mForm.Show();
|
||||
mForm.Activate();
|
||||
mForm.RunAndLoad("工程图", delegate { CheckEngine.RunDrawingChecks(snap); });
|
||||
}
|
||||
|
||||
public static void ExportReport()
|
||||
{
|
||||
if (AppState.Results.Count == 0)
|
||||
{
|
||||
MessageBox.Show("暂无检查结果, 请先执行检查", "Design Express Res", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return;
|
||||
}
|
||||
SaveFileDialog dlg = new SaveFileDialog();
|
||||
dlg.Title = "保存检查报告";
|
||||
dlg.Filter = "Excel 报告 (*.xlsx)|*.xlsx|CSV 报告 (*.csv)|*.csv";
|
||||
dlg.FileName = "检查报告_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx";
|
||||
if (dlg.ShowDialog() == DialogResult.OK)
|
||||
{
|
||||
string file = dlg.FileName.ToLower().EndsWith(".csv") ? Report.WriteCsv(dlg.FileName) : Report.WriteExcel(dlg.FileName);
|
||||
MessageBox.Show("报告已生成: " + file, "Design Express Res", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Help()
|
||||
{
|
||||
MessageBox.Show(
|
||||
"Design Express Res v" + Report.ToolVersion + "\r\n\r\n" +
|
||||
"零件检查: 标注统计、公差配合(GB/T 275)、形位公差、粗糙度、螺纹孔、物料接触 GMP、表面处理、强度指引\r\n" +
|
||||
"装配检查: GMP 材料、密封件、清洁性、粗糙度、静态干涉、外购件、电气/西门子、动力系统\r\n" +
|
||||
"工程图检查: 图框/标题栏、视图更新、尺寸公差、标注统计、22 项 spec 技术要求关键词检查\r\n\r\n" +
|
||||
"架构: Core 独立核心库 + 各 CAD Link 适配层(Inventor/Creo/SolidWorks), 类似 COMSOL LiveLink。\r\n" +
|
||||
"报告输出为 Excel(汇总/明细/检查项清单), Excel 不可用时输出 CSV。",
|
||||
"使用说明", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
// ============ 设计数据查询工具入口(独立系统) ============
|
||||
|
||||
public static void CirclipQuery() { QueryForm.ShowQuery(0); }
|
||||
public static void KeywayQuery() { QueryForm.ShowQuery(1); }
|
||||
public static void OringQuery() { QueryForm.ShowQuery(2); }
|
||||
public static void BearingRingQuery() { QueryForm.ShowQuery(3); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
public class QueryRow
|
||||
{
|
||||
public string Item;
|
||||
public string Value;
|
||||
public string Std;
|
||||
public string Remark;
|
||||
}
|
||||
|
||||
public enum QueryKind
|
||||
{
|
||||
Circlip = 0, // 卡簧槽 GB/T 894.1
|
||||
Keyway = 1, // 键槽 GB/T 1095
|
||||
Oring = 2, // O 型密封圈 GB/T 3452.1 (规划中)
|
||||
BearingRing = 3 // 轴承挡圈 (规划中)
|
||||
}
|
||||
|
||||
// 设计尺寸查询数据引擎: 纯数据表查询, 与 CAD 无关
|
||||
// 注: 数据为常用参考值, 正式设计请核对最新版标准
|
||||
public static class DesignQuery
|
||||
{
|
||||
private const string DISCLAIMER = "参考值, 以最新标准为准";
|
||||
|
||||
// ================= 键槽 (GB/T 1095) =================
|
||||
|
||||
private class KeywayRow
|
||||
{
|
||||
public double Dmin, Dmax;
|
||||
public string KeySize; // b×h
|
||||
public double T1, T2; // 轴槽深, 轮毂槽深
|
||||
public string LRange; // 键长范围
|
||||
}
|
||||
|
||||
private static readonly KeywayRow[] Keyways = new KeywayRow[]
|
||||
{
|
||||
new KeywayRow { Dmin=6, Dmax=8, KeySize="2×2", T1=1.2, T2=1.0, LRange="6~20" },
|
||||
new KeywayRow { Dmin=8, Dmax=10, KeySize="3×3", T1=1.8, T2=1.4, LRange="6~36" },
|
||||
new KeywayRow { Dmin=10, Dmax=12, KeySize="4×4", T1=2.5, T2=1.8, LRange="8~45" },
|
||||
new KeywayRow { Dmin=12, Dmax=17, KeySize="5×5", T1=3.0, T2=2.3, LRange="10~56" },
|
||||
new KeywayRow { Dmin=17, Dmax=22, KeySize="6×6", T1=3.5, T2=2.8, LRange="14~70" },
|
||||
new KeywayRow { Dmin=22, Dmax=30, KeySize="8×7", T1=4.0, T2=3.3, LRange="18~90" },
|
||||
new KeywayRow { Dmin=30, Dmax=38, KeySize="10×8", T1=5.0, T2=3.3, LRange="22~110" },
|
||||
new KeywayRow { Dmin=38, Dmax=44, KeySize="12×8", T1=5.0, T2=3.3, LRange="28~140" },
|
||||
new KeywayRow { Dmin=44, Dmax=50, KeySize="14×9", T1=5.5, T2=3.8, LRange="36~160" },
|
||||
new KeywayRow { Dmin=50, Dmax=58, KeySize="16×10", T1=6.0, T2=4.3, LRange="45~180" },
|
||||
new KeywayRow { Dmin=58, Dmax=65, KeySize="18×11", T1=7.0, T2=4.4, LRange="50~200" },
|
||||
new KeywayRow { Dmin=65, Dmax=75, KeySize="20×12", T1=7.5, T2=4.9, LRange="56~220" },
|
||||
new KeywayRow { Dmin=75, Dmax=85, KeySize="22×14", T1=9.0, T2=5.4, LRange="63~250" },
|
||||
new KeywayRow { Dmin=85, Dmax=95, KeySize="25×14", T1=9.0, T2=5.4, LRange="70~280" },
|
||||
new KeywayRow { Dmin=95, Dmax=110, KeySize="28×16", T1=10.0, T2=6.4, LRange="80~320" },
|
||||
new KeywayRow { Dmin=110, Dmax=130, KeySize="32×18", T1=11.0, T2=7.4, LRange="90~360" },
|
||||
new KeywayRow { Dmin=130, Dmax=150, KeySize="36×20", T1=12.0, T2=8.4, LRange="100~400" },
|
||||
new KeywayRow { Dmin=150, Dmax=170, KeySize="40×22", T1=13.0, T2=9.4, LRange="100~400" },
|
||||
new KeywayRow { Dmin=170, Dmax=200, KeySize="45×25", T1=15.0, T2=10.4, LRange="110~450" },
|
||||
new KeywayRow { Dmin=200, Dmax=230, KeySize="50×28", T1=17.0, T2=11.4, LRange="125~500" },
|
||||
new KeywayRow { Dmin=230, Dmax=260, KeySize="56×32", T1=20.0, T2=12.4, LRange="140~500" },
|
||||
new KeywayRow { Dmin=260, Dmax=290, KeySize="63×32", T1=20.0, T2=12.4, LRange="160~500" },
|
||||
new KeywayRow { Dmin=290, Dmax=330, KeySize="70×36", T1=22.0, T2=14.4, LRange="180~500" },
|
||||
new KeywayRow { Dmin=330, Dmax=380, KeySize="80×40", T1=25.0, T2=15.4, LRange="200~500" },
|
||||
new KeywayRow { Dmin=380, Dmax=440, KeySize="90×45", T1=28.0, T2=17.4, LRange="220~500" },
|
||||
new KeywayRow { Dmin=440, Dmax=500, KeySize="100×50", T1=31.0, T2=19.5, LRange="250~500" }
|
||||
};
|
||||
|
||||
private static readonly double[] KeyLenSeries =
|
||||
{ 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 28, 32, 36, 40, 45, 50, 56, 63, 70, 80, 90, 100,
|
||||
110, 125, 140, 160, 180, 200, 220, 250, 280, 320, 360, 400, 450, 500 };
|
||||
|
||||
private static List<QueryRow> QueryKeyway(double d)
|
||||
{
|
||||
List<QueryRow> rows = new List<QueryRow>();
|
||||
KeywayRow hit = null;
|
||||
foreach (KeywayRow k in Keyways)
|
||||
{
|
||||
if (d > k.Dmin && d <= k.Dmax) { hit = k; break; }
|
||||
}
|
||||
if (hit == null)
|
||||
{
|
||||
rows.Add(new QueryRow { Item = "查询结果", Value = "超出数据范围", Std = "GB/T 1095", Remark = "支持轴径 6~500mm" });
|
||||
return rows;
|
||||
}
|
||||
rows.Add(new QueryRow { Item = "适用轴径 d", Value = ">" + hit.Dmin + "~" + hit.Dmax, Std = "GB/T 1095", Remark = "" });
|
||||
rows.Add(new QueryRow { Item = "键公称尺寸 b×h", Value = hit.KeySize, Std = "GB/T 1095", Remark = "" });
|
||||
rows.Add(new QueryRow { Item = "轴槽深 t1", Value = hit.T1.ToString("0.0"), Std = "GB/T 1095", Remark = "轴直径 - t1 = 槽底直径" });
|
||||
rows.Add(new QueryRow { Item = "轮毂槽深 t2", Value = hit.T2.ToString("0.0"), Std = "GB/T 1095", Remark = "孔直径 + t2 = 槽底直径" });
|
||||
rows.Add(new QueryRow { Item = "键长范围 L", Value = hit.LRange, Std = "GB/T 1095", Remark = "从标准长度系列选取" });
|
||||
|
||||
// 长度系列中落在范围内的
|
||||
double lo = 0, hi = 0;
|
||||
string[] parts = hit.LRange.Split('~');
|
||||
double.TryParse(parts[0], out lo);
|
||||
double.TryParse(parts[1], out hi);
|
||||
List<string> sel = new List<string>();
|
||||
foreach (double len in KeyLenSeries)
|
||||
{
|
||||
if (len >= lo && len <= hi) sel.Add(len.ToString("0"));
|
||||
}
|
||||
rows.Add(new QueryRow { Item = "可用键长", Value = string.Join(", ", sel.ToArray()), Std = "GB/T 1095", Remark = DISCLAIMER });
|
||||
return rows;
|
||||
}
|
||||
|
||||
// ================= 卡簧槽 - 轴用弹性挡圈 (GB/T 894.1 A型) =================
|
||||
|
||||
private class CirclipRow
|
||||
{
|
||||
public double D; // 轴径
|
||||
public double OD; // 挡圈外径
|
||||
public double Depth; // 槽深
|
||||
public double SlotW; // 槽宽
|
||||
}
|
||||
|
||||
private static readonly CirclipRow[] Circlips = new CirclipRow[]
|
||||
{
|
||||
new CirclipRow { D=3, OD=8.2, Depth=0.4, SlotW=0.6 },
|
||||
new CirclipRow { D=4, OD=9.6, Depth=0.4, SlotW=0.6 },
|
||||
new CirclipRow { D=5, OD=11.0, Depth=0.5, SlotW=0.7 },
|
||||
new CirclipRow { D=6, OD=13.0, Depth=0.7, SlotW=0.9 },
|
||||
new CirclipRow { D=7, OD=14.5, Depth=0.7, SlotW=0.9 },
|
||||
new CirclipRow { D=8, OD=16.0, Depth=0.7, SlotW=0.9 },
|
||||
new CirclipRow { D=9, OD=17.5, Depth=0.8, SlotW=1.0 },
|
||||
new CirclipRow { D=10, OD=19.0, Depth=0.8, SlotW=1.0 },
|
||||
new CirclipRow { D=11, OD=21.0, Depth=0.8, SlotW=1.0 },
|
||||
new CirclipRow { D=12, OD=22.5, Depth=0.9, SlotW=1.2 },
|
||||
new CirclipRow { D=13, OD=24.0, Depth=0.9, SlotW=1.2 },
|
||||
new CirclipRow { D=14, OD=25.5, Depth=0.9, SlotW=1.2 },
|
||||
new CirclipRow { D=15, OD=27.0, Depth=0.9, SlotW=1.2 },
|
||||
new CirclipRow { D=16, OD=28.5, Depth=1.0, SlotW=1.2 },
|
||||
new CirclipRow { D=17, OD=30.0, Depth=1.0, SlotW=1.2 },
|
||||
new CirclipRow { D=18, OD=32.0, Depth=1.1, SlotW=1.5 },
|
||||
new CirclipRow { D=19, OD=33.5, Depth=1.1, SlotW=1.5 },
|
||||
new CirclipRow { D=20, OD=35.0, Depth=1.1, SlotW=1.5 },
|
||||
new CirclipRow { D=21, OD=36.5, Depth=1.1, SlotW=1.5 },
|
||||
new CirclipRow { D=22, OD=38.0, Depth=1.1, SlotW=1.5 },
|
||||
new CirclipRow { D=24, OD=41.0, Depth=1.2, SlotW=1.5 },
|
||||
new CirclipRow { D=25, OD=42.5, Depth=1.2, SlotW=1.5 },
|
||||
new CirclipRow { D=26, OD=44.0, Depth=1.2, SlotW=1.5 },
|
||||
new CirclipRow { D=28, OD=47.0, Depth=1.3, SlotW=1.8 },
|
||||
new CirclipRow { D=30, OD=50.0, Depth=1.3, SlotW=1.8 },
|
||||
new CirclipRow { D=32, OD=53.0, Depth=1.4, SlotW=1.8 },
|
||||
new CirclipRow { D=34, OD=56.0, Depth=1.4, SlotW=1.8 },
|
||||
new CirclipRow { D=35, OD=57.5, Depth=1.4, SlotW=1.8 },
|
||||
new CirclipRow { D=36, OD=59.0, Depth=1.5, SlotW=2.0 },
|
||||
new CirclipRow { D=38, OD=62.0, Depth=1.5, SlotW=2.0 },
|
||||
new CirclipRow { D=40, OD=65.0, Depth=1.5, SlotW=2.0 },
|
||||
new CirclipRow { D=42, OD=68.0, Depth=1.6, SlotW=2.0 },
|
||||
new CirclipRow { D=45, OD=72.0, Depth=1.6, SlotW=2.0 },
|
||||
new CirclipRow { D=48, OD=76.0, Depth=1.6, SlotW=2.0 },
|
||||
new CirclipRow { D=50, OD=79.0, Depth=1.7, SlotW=2.5 }
|
||||
};
|
||||
|
||||
private static List<QueryRow> QueryCirclip(double d)
|
||||
{
|
||||
List<QueryRow> rows = new List<QueryRow>();
|
||||
CirclipRow hit = null;
|
||||
foreach (CirclipRow c in Circlips)
|
||||
{
|
||||
if (Math.Abs(c.D - d) < 0.001) { hit = c; break; }
|
||||
}
|
||||
if (hit == null)
|
||||
{
|
||||
// 未精确匹配: 取最接近的相邻挡圈
|
||||
CirclipRow lower = null, upper = null;
|
||||
foreach (CirclipRow c in Circlips)
|
||||
{
|
||||
if (c.D < d && (lower == null || c.D > lower.D)) lower = c;
|
||||
if (c.D > d && (upper == null || c.D < upper.D)) upper = c;
|
||||
}
|
||||
if (lower == null && upper == null)
|
||||
{
|
||||
rows.Add(new QueryRow { Item = "查询结果", Value = "超出数据范围", Std = "GB/T 894.1", Remark = "支持轴径 3~50mm" });
|
||||
return rows;
|
||||
}
|
||||
rows.Add(new QueryRow { Item = "查询结果", Value = "非标准轴径, 请就近选用", Std = "GB/T 894.1", Remark = DISCLAIMER });
|
||||
if (lower != null)
|
||||
rows.Add(new QueryRow { Item = "小于轴径的挡圈", Value = "d=" + lower.D + " 外径D=" + lower.OD + " 槽深t=" + lower.Depth + " 槽宽m=" + lower.SlotW, Std = "GB/T 894.1", Remark = "" });
|
||||
if (upper != null)
|
||||
rows.Add(new QueryRow { Item = "大于轴径的挡圈", Value = "d=" + upper.D + " 外径D=" + upper.OD + " 槽深t=" + upper.Depth + " 槽宽m=" + upper.SlotW, Std = "GB/T 894.1", Remark = "" });
|
||||
return rows;
|
||||
}
|
||||
rows.Add(new QueryRow { Item = "轴径 d", Value = hit.D.ToString("0"), Std = "GB/T 894.1", Remark = "A 型轴用弹性挡圈" });
|
||||
rows.Add(new QueryRow { Item = "挡圈外径 D", Value = hit.OD.ToString("0.0"), Std = "GB/T 894.1", Remark = "" });
|
||||
rows.Add(new QueryRow { Item = "沟槽直径 d1", Value = (hit.D - 2 * hit.Depth).ToString("0.0"), Std = "GB/T 894.1", Remark = "槽底直径 = d - 2t" });
|
||||
rows.Add(new QueryRow { Item = "沟槽深度 t", Value = hit.Depth.ToString("0.0"), Std = "GB/T 894.1", Remark = "" });
|
||||
rows.Add(new QueryRow { Item = "沟槽宽度 m", Value = hit.SlotW.ToString("0.0"), Std = "GB/T 894.1", Remark = "" });
|
||||
rows.Add(new QueryRow { Item = "安装说明", Value = "挡圈装入沟槽后应贴合槽底", Std = "GB/T 894.1", Remark = DISCLAIMER });
|
||||
return rows;
|
||||
}
|
||||
|
||||
// ================= 统一入口 =================
|
||||
|
||||
public static List<QueryRow> Query(QueryKind kind, double d)
|
||||
{
|
||||
switch (kind)
|
||||
{
|
||||
case QueryKind.Keyway: return QueryKeyway(d);
|
||||
case QueryKind.Circlip: return QueryCirclip(d);
|
||||
default:
|
||||
return new List<QueryRow>
|
||||
{
|
||||
new QueryRow { Item = "查询结果", Value = "模块开发中", Std = "GB/T 3452.1", Remark = "" }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
public class FitItem
|
||||
{
|
||||
public string Role;
|
||||
public string Code;
|
||||
public double DiaMM;
|
||||
public int Load;
|
||||
public int Purpose;
|
||||
public string Verdict;
|
||||
public string Recommend;
|
||||
public string Basis;
|
||||
}
|
||||
|
||||
// 公差配合检查对话框
|
||||
public class FitForm : Form
|
||||
{
|
||||
public List<FitItem> Items = new List<FitItem>();
|
||||
|
||||
private ComboBox cboRole, cboLoad, cboPurpose;
|
||||
private TextBox txtDia, txtCode;
|
||||
private Label lblResult;
|
||||
private ListBox lst;
|
||||
private Button btnCheck, btnDone;
|
||||
private double _diaMM;
|
||||
private string _faceName;
|
||||
|
||||
public FitForm(double diaMM, string faceName)
|
||||
{
|
||||
_diaMM = diaMM;
|
||||
_faceName = faceName;
|
||||
BuildUI();
|
||||
}
|
||||
|
||||
private void BuildUI()
|
||||
{
|
||||
Text = "公差配合检查 - 设计标注检查工具";
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false;
|
||||
MinimizeBox = false;
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
ClientSize = new Size(640, 480);
|
||||
|
||||
int y = 12;
|
||||
Label lblFace = new Label();
|
||||
lblFace.Text = "配合面: " + _faceName + " 直径: " + _diaMM.ToString("0.0") + " mm";
|
||||
lblFace.Location = new Point(12, y); lblFace.AutoSize = true; lblFace.Font = new Font(lblFace.Font, FontStyle.Bold);
|
||||
Controls.Add(lblFace);
|
||||
y += 28;
|
||||
|
||||
Label lblRole = new Label(); lblRole.Text = "角色:"; lblRole.Location = new Point(12, y + 3); lblRole.AutoSize = true;
|
||||
Controls.Add(lblRole);
|
||||
cboRole = new ComboBox();
|
||||
cboRole.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||
cboRole.Items.AddRange(new object[] { "轴承-轴颈(旋转)", "轴承-轴颈(固定)", "轴承-座孔(外圈固定)", "轴承-座孔(外圈旋转)", "一般孔轴配合" });
|
||||
cboRole.SelectedIndex = 0;
|
||||
cboRole.Location = new Point(90, y); cboRole.Width = 220;
|
||||
Controls.Add(cboRole);
|
||||
cboRole.SelectedIndexChanged += delegate { RoleChanged(); };
|
||||
y += 30;
|
||||
|
||||
Label lblLoad = new Label(); lblLoad.Text = "载荷:"; lblLoad.Location = new Point(12, y + 3); lblLoad.AutoSize = true;
|
||||
Controls.Add(lblLoad);
|
||||
cboLoad = new ComboBox();
|
||||
cboLoad.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||
cboLoad.Items.AddRange(new object[] { "轻载 (P<=0.07C)", "中载 (0.07C<P<=0.15C)", "重载 (P>0.15C)", "特重/冲击载荷" });
|
||||
cboLoad.SelectedIndex = 1;
|
||||
cboLoad.Location = new Point(90, y); cboLoad.Width = 220;
|
||||
Controls.Add(cboLoad);
|
||||
y += 30;
|
||||
|
||||
Label lblPurpose = new Label(); lblPurpose.Text = "用途:"; lblPurpose.Location = new Point(12, y + 3); lblPurpose.AutoSize = true;
|
||||
Controls.Add(lblPurpose);
|
||||
cboPurpose = new ComboBox();
|
||||
cboPurpose.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||
cboPurpose.Items.AddRange(new object[] { "滑动(有相对运动)", "定位(固定位置, 可拆)", "传动(传递扭矩)", "过盈连接(不拆卸)" });
|
||||
cboPurpose.SelectedIndex = 1;
|
||||
cboPurpose.Location = new Point(90, y); cboPurpose.Width = 220;
|
||||
Controls.Add(cboPurpose);
|
||||
y += 30;
|
||||
|
||||
Label lblDia = new Label(); lblDia.Text = "直径(mm):"; lblDia.Location = new Point(12, y + 3); lblDia.AutoSize = true;
|
||||
Controls.Add(lblDia);
|
||||
txtDia = new TextBox(); txtDia.Text = _diaMM.ToString("0.0"); txtDia.Location = new Point(90, y); txtDia.Width = 100;
|
||||
Controls.Add(txtDia);
|
||||
y += 30;
|
||||
|
||||
Label lblCode = new Label(); lblCode.Text = "配合代码:"; lblCode.Location = new Point(12, y + 3); lblCode.AutoSize = true;
|
||||
Controls.Add(lblCode);
|
||||
txtCode = new TextBox(); txtCode.Text = "k6"; txtCode.Location = new Point(90, y); txtCode.Width = 140;
|
||||
Controls.Add(txtCode);
|
||||
Label lblCodeHint = new Label();
|
||||
lblCodeHint.Text = "轴承轴颈: 如 k6/js6/m6; 座孔: 如 H7/J7/K7; 一般配合: 如 H7/k6";
|
||||
lblCodeHint.Location = new Point(240, y + 3); lblCodeHint.AutoSize = true;
|
||||
Controls.Add(lblCodeHint);
|
||||
y += 34;
|
||||
|
||||
btnCheck = new Button(); btnCheck.Text = "检查并加入列表"; btnCheck.Location = new Point(12, y); btnCheck.Width = 130;
|
||||
btnCheck.Click += delegate { DoCheck(); };
|
||||
Controls.Add(btnCheck);
|
||||
btnDone = new Button(); btnDone.Text = "完成 (生成报告)"; btnDone.Location = new Point(150, y); btnDone.Width = 130;
|
||||
btnDone.Click += delegate { DialogResult = DialogResult.OK; Close(); };
|
||||
Controls.Add(btnDone);
|
||||
y += 36;
|
||||
|
||||
lblResult = new Label();
|
||||
lblResult.Text = "";
|
||||
lblResult.Location = new Point(12, y); lblResult.AutoSize = true; lblResult.MaximumSize = new Size(610, 0);
|
||||
Controls.Add(lblResult);
|
||||
y += 60;
|
||||
|
||||
lst = new ListBox();
|
||||
lst.Location = new Point(12, y); lst.Width = 616; lst.Height = 140;
|
||||
Controls.Add(lst);
|
||||
|
||||
RoleChanged();
|
||||
}
|
||||
|
||||
private void RoleChanged()
|
||||
{
|
||||
bool bearing = cboRole.SelectedIndex >= 0 && cboRole.SelectedIndex <= 3;
|
||||
cboLoad.Enabled = bearing;
|
||||
cboPurpose.Enabled = !bearing;
|
||||
txtCode.Text = bearing ? "k6" : "H7/k6";
|
||||
}
|
||||
|
||||
private void DoCheck()
|
||||
{
|
||||
double dia;
|
||||
double.TryParse(txtDia.Text, out dia);
|
||||
if (dia <= 0) { MessageBox.Show("请输入有效直径"); return; }
|
||||
string code = txtCode.Text.Trim();
|
||||
if (code == "") { MessageBox.Show("请输入配合代码"); return; }
|
||||
|
||||
string verdict, recommend, basis;
|
||||
int load = cboLoad.SelectedIndex + 1;
|
||||
int purpose = cboPurpose.SelectedIndex + 1;
|
||||
|
||||
if (cboRole.SelectedIndex == 4)
|
||||
verdict = KB.GeneralFitJudge(code, purpose, out recommend, out basis);
|
||||
else
|
||||
verdict = KB.FitJudge(code, (string)cboRole.SelectedItem, load, out recommend, out basis);
|
||||
|
||||
FitItem it = new FitItem();
|
||||
it.Role = (string)cboRole.SelectedItem;
|
||||
it.Code = code;
|
||||
it.DiaMM = dia;
|
||||
it.Load = load;
|
||||
it.Purpose = purpose;
|
||||
it.Verdict = verdict;
|
||||
it.Recommend = recommend;
|
||||
it.Basis = basis;
|
||||
Items.Add(it);
|
||||
|
||||
lblResult.Text = "判定: " + verdict + " 推荐: " + recommend + "\r\n" + basis;
|
||||
lblResult.ForeColor = verdict == "合理" ? Color.Green : (verdict == "可接受" ? Color.DarkOrange : Color.Red);
|
||||
lst.Items.Add(dia.ToString("0.0") + "mm " + it.Role + " 代码 " + code + " -> " + verdict + " (推荐 " + recommend + ")");
|
||||
txtCode.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 通用单行输入对话框
|
||||
public class SimpleInput : Form
|
||||
{
|
||||
private TextBox txt;
|
||||
public string Value { get { return txt.Text; } }
|
||||
|
||||
public SimpleInput(string title, string prompt, string def)
|
||||
{
|
||||
Text = title;
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
MaximizeBox = false; MinimizeBox = false;
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
ClientSize = new Size(420, 110);
|
||||
|
||||
Label lbl = new Label();
|
||||
lbl.Text = prompt;
|
||||
lbl.Location = new Point(12, 12); lbl.AutoSize = true; lbl.MaximumSize = new Size(390, 40);
|
||||
Controls.Add(lbl);
|
||||
|
||||
txt = new TextBox();
|
||||
txt.Text = def;
|
||||
txt.Location = new Point(12, 50); txt.Width = 396;
|
||||
Controls.Add(txt);
|
||||
|
||||
Button ok = new Button(); ok.Text = "确定"; ok.DialogResult = DialogResult.OK;
|
||||
ok.Location = new Point(220, 78); ok.Width = 90;
|
||||
Controls.Add(ok);
|
||||
Button cancel = new Button(); cancel.Text = "取消"; cancel.DialogResult = DialogResult.Cancel;
|
||||
cancel.Location = new Point(318, 78); cancel.Width = 90;
|
||||
Controls.Add(cancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
// CAD 宿主抽象接口: Core 不依赖任何具体 CAD 系统,
|
||||
// 由各 CAD 的 Link 适配器(Inventor/Creo/SolidWorks)实现,
|
||||
// 架构类似 COMSOL LiveLink
|
||||
public interface ICadHost
|
||||
{
|
||||
string AppName { get; }
|
||||
object GetActiveDocument();
|
||||
string GetDocType(object doc);
|
||||
DocSnapshot Capture(object doc);
|
||||
double PickCylinderDiameterMM(out string faceName);
|
||||
void SetStatusText(string text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
using System;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
// 知识库: 机械设计手册常用数据(简化参考版)
|
||||
// 正式生产请以最新版《机械设计手册》及 GB/T 275, GB/T 1800, GB/T 1801 等标准为准
|
||||
public static class KB
|
||||
{
|
||||
public static int SegIndex(double dMM)
|
||||
{
|
||||
if (dMM <= 18) return 1;
|
||||
if (dMM <= 30) return 2;
|
||||
if (dMM <= 50) return 3;
|
||||
if (dMM <= 80) return 4;
|
||||
if (dMM <= 120) return 5;
|
||||
if (dMM <= 180) return 6;
|
||||
if (dMM <= 250) return 7;
|
||||
if (dMM <= 315) return 8;
|
||||
if (dMM <= 400) return 9;
|
||||
if (dMM <= 500) return 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static string SegName(int seg)
|
||||
{
|
||||
switch (seg)
|
||||
{
|
||||
case 1: return "<=18";
|
||||
case 2: return "18~30";
|
||||
case 3: return "30~50";
|
||||
case 4: return "50~80";
|
||||
case 5: return "80~120";
|
||||
case 6: return "120~180";
|
||||
case 7: return "180~250";
|
||||
case 8: return "250~315";
|
||||
case 9: return "315~400";
|
||||
case 10: return "400~500";
|
||||
default: return "?";
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly double[,] IT = new double[11, 10]
|
||||
{
|
||||
{ 0.8, 1, 1.2, 1.5, 2, 2.5, 3.5, 4, 4.5, 5 },
|
||||
{ 1.2, 1.5, 2, 2.5, 3, 4, 4.5, 5, 6, 7 },
|
||||
{ 2, 2.5, 3, 4, 5, 6, 7, 8, 9, 10 },
|
||||
{ 3, 4, 5, 6, 8, 10, 12, 13, 15, 16 },
|
||||
{ 4, 5, 7, 8, 10, 12, 14, 16, 18, 20 },
|
||||
{ 6, 8, 10, 12, 15, 18, 20, 23, 25, 27 },
|
||||
{ 10, 12, 16, 19, 22, 25, 28, 32, 36, 40 },
|
||||
{ 14, 18, 22, 26, 30, 35, 40, 46, 52, 57 },
|
||||
{ 25, 30, 36, 43, 52, 62, 72, 81, 89, 97 },
|
||||
{ 40, 48, 58, 70, 84, 100, 115, 130, 140, 155 },
|
||||
{ 60, 75, 90, 105, 130, 150, 175, 195, 210, 230 }
|
||||
};
|
||||
|
||||
public static double ItTol(int itNo, int seg)
|
||||
{
|
||||
if (itNo >= 1 && itNo <= 11 && seg >= 1 && seg <= 10) return IT[itNo - 1, seg - 1];
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static string LoadName(int load)
|
||||
{
|
||||
switch (load)
|
||||
{
|
||||
case 1: return "轻载(P<=0.07C)";
|
||||
case 2: return "中载(0.07C<P<=0.15C)";
|
||||
case 3: return "重载(P>0.15C)";
|
||||
default: return "特重/冲击载荷";
|
||||
}
|
||||
}
|
||||
|
||||
public static void ParseFit(string code, out string hole, out string shaft)
|
||||
{
|
||||
hole = ""; shaft = "";
|
||||
string c = (code ?? "").Trim().ToUpper();
|
||||
int p = c.IndexOf('/');
|
||||
if (p > 0)
|
||||
{
|
||||
hole = c.Substring(0, p).Trim();
|
||||
shaft = c.Substring(p + 1).Trim();
|
||||
}
|
||||
else hole = c;
|
||||
}
|
||||
|
||||
public static string FitJudge(string code, string role, int load, out string recommend, out string basis)
|
||||
{
|
||||
recommend = "";
|
||||
string c = (code ?? "").Trim().ToUpper();
|
||||
string rec = "", acc = "";
|
||||
basis = "机械设计手册 第2卷 / GB/T 275-2015 滚动轴承配合";
|
||||
switch (role)
|
||||
{
|
||||
case "轴承-轴颈(旋转)":
|
||||
switch (load)
|
||||
{
|
||||
case 1: rec = "js6"; acc = "k6"; break;
|
||||
case 2: rec = "k6"; acc = "m6"; break;
|
||||
case 3: rec = "m6"; acc = "n6"; break;
|
||||
default: rec = "n6"; acc = "p6,r6"; break;
|
||||
}
|
||||
basis += ": 内圈与旋转轴, " + LoadName(load) + ", 推荐 " + rec + " (可选 " + acc + ")";
|
||||
break;
|
||||
case "轴承-轴颈(固定)":
|
||||
rec = "h6"; acc = "g6,j6";
|
||||
basis += ": 内圈与不旋转轴, 推荐 " + rec + " (可选 " + acc + ")";
|
||||
break;
|
||||
case "轴承-座孔(外圈固定)":
|
||||
rec = "H7"; acc = "J7,H8";
|
||||
basis += ": 外圈与壳体孔(固定载荷), 推荐 " + rec + " (可选 " + acc + ")";
|
||||
break;
|
||||
case "轴承-座孔(外圈旋转)":
|
||||
rec = "K7"; acc = "M7,N7";
|
||||
basis += ": 外圈与壳体孔(旋转载荷), 推荐 " + rec + " (可选 " + acc + ")";
|
||||
break;
|
||||
default:
|
||||
basis = "未知角色";
|
||||
return "信息";
|
||||
}
|
||||
recommend = rec;
|
||||
if (c == "") return "信息";
|
||||
if (c == rec) return "合理";
|
||||
if (("," + acc + ",").Contains("," + c + ",")) return "可接受";
|
||||
return "不合理";
|
||||
}
|
||||
|
||||
public static string GeneralFitJudge(string code, int purpose, out string recommend, out string basis)
|
||||
{
|
||||
string hole, shaft;
|
||||
ParseFit(code, out hole, out shaft);
|
||||
string c = (code ?? "").Trim().ToUpper();
|
||||
string fitType, fitUse;
|
||||
LookupFitTable(hole + "/" + shaft, out fitType, out fitUse);
|
||||
string rec = "", acc = "", purposeName = "";
|
||||
basis = "机械设计手册 第2卷 孔轴公差与配合 (GB/T 1801)";
|
||||
switch (purpose)
|
||||
{
|
||||
case 1: purposeName = "滑动配合"; rec = "H8/f7"; acc = "H9/d9,H7/g6"; break;
|
||||
case 2: purposeName = "定位配合"; rec = "H7/js6"; acc = "H7/h6,H7/k6"; break;
|
||||
case 3: purposeName = "传动配合"; rec = "H7/n6"; acc = "H7/p6"; break;
|
||||
default: purposeName = "过盈连接"; rec = "H7/s6"; acc = "H7/r6,H7/u6"; break;
|
||||
}
|
||||
recommend = rec;
|
||||
basis += ": " + purposeName + ", 推荐 " + rec + " (可选 " + acc + ")";
|
||||
if (fitType == "")
|
||||
{
|
||||
basis += "; 当前代码 " + c + " 不在常用配合表中, 请核对";
|
||||
return "信息";
|
||||
}
|
||||
string needType = "间隙";
|
||||
if (purpose == 2) needType = "间隙/过渡";
|
||||
if (purpose == 3) needType = "过渡/过盈";
|
||||
if (purpose == 4) needType = "过盈";
|
||||
if (c == rec) return "合理";
|
||||
if (("," + acc + ",").Contains("," + c + ",")) return "可接受";
|
||||
if (needType.Contains(fitType))
|
||||
{
|
||||
basis += "; 当前 " + c + " 为" + fitType + "配合(" + fitUse + "), 类型方向正确但非优先推荐";
|
||||
return "可接受";
|
||||
}
|
||||
basis += "; 当前 " + c + " 为" + fitType + "配合(" + fitUse + "), 与用途不符";
|
||||
return "不合理";
|
||||
}
|
||||
|
||||
public static void LookupFitTable(string code, out string fitType, out string fitUse)
|
||||
{
|
||||
fitType = ""; fitUse = "";
|
||||
switch ((code ?? "").Trim().ToUpper())
|
||||
{
|
||||
case "H11/C11": fitType = "间隙"; fitUse = "低精度/粗糙滑动, 吊架等"; break;
|
||||
case "H9/D9": fitType = "间隙"; fitUse = "较松滑动, 联轴器导向"; break;
|
||||
case "H8/F7": fitType = "间隙"; fitUse = "一般滑动, 机床导轨低速"; break;
|
||||
case "H7/G6": fitType = "间隙"; fitUse = "精密滑动, 导向件/移动齿轮"; break;
|
||||
case "H7/H6": fitType = "间隙"; fitUse = "小间隙定位, 挂轮/联轴器"; break;
|
||||
case "H7/JS6": fitType = "过渡"; fitUse = "定位, 手轮/隔套"; break;
|
||||
case "H7/K6": fitType = "过渡"; fitUse = "精密定位, 隔套/滚动轴承内圈"; break;
|
||||
case "H7/N6": fitType = "过渡"; fitUse = "较紧定位/传动, 齿轮与轴/连杆"; break;
|
||||
case "H7/P6": fitType = "过盈"; fitUse = "小过盈, 定位兼传小扭矩"; break;
|
||||
case "H7/R6": fitType = "过盈"; fitUse = "一般过盈, 受冲击装配"; break;
|
||||
case "H7/S6": fitType = "过盈"; fitUse = "液压装配过盈"; break;
|
||||
case "H7/U6": fitType = "过盈"; fitUse = "大过盈, 重型压装"; break;
|
||||
}
|
||||
}
|
||||
|
||||
public static string RaSuggest(string role)
|
||||
{
|
||||
if (role.StartsWith("轴承-轴颈")) return "0.4~0.8 um (磨削)";
|
||||
if (role.StartsWith("轴承-座孔")) return "0.8~1.6 um (精镗/铰)";
|
||||
if (role == "密封") return "动密封面 0.4~0.8; 静密封面 0.8~1.6 um";
|
||||
if (role == "GMP") return "物料接触面 Ra<=0.8 (电解抛光 0.4)";
|
||||
return "一般配合面 1.6~3.2 um";
|
||||
}
|
||||
|
||||
public static string GmpMaterialJudge(string matName, out string rec, out string basis)
|
||||
{
|
||||
string m = (matName ?? "").Trim().ToUpper();
|
||||
basis = "GMP 设备设计规范: 与物料接触部件应使用耐腐蚀、易清洁材料";
|
||||
rec = "";
|
||||
if (m == "") { rec = "应填写材料并选用卫生级不锈钢"; return "未通过"; }
|
||||
if (m.Contains("316L") || m.Contains("904L") || m.Contains("2205")) { rec = m + " 符合 GMP 物料接触要求(首选)"; return "合理"; }
|
||||
if (m.Contains("316")) { rec = m + " 符合 GMP 物料接触要求"; return "合理"; }
|
||||
if (m.Contains("钛") || m.Contains("哈氏")) { rec = m + " 耐腐蚀, 符合 GMP 要求"; return "合理"; }
|
||||
if (m.Contains("304") || m.Contains("不锈钢")) { rec = "304 级可接受, 接触面建议电解抛光; 长期接触含氯介质建议 316L"; return "可接受"; }
|
||||
if (m.Contains("PTFE") || m.Contains("聚四氟") || m.Contains("PFA") || m.Contains("PVDF") ||
|
||||
m.Contains("EPDM") || m.Contains("三元乙丙") || m.Contains("FKM") || m.Contains("氟胶") ||
|
||||
m.Contains("硅胶") || m.Contains("PEEK") || m.Contains("聚丙烯") || m.Contains("玻璃"))
|
||||
{ rec = m + " 可用于密封/非金属部件, 需确认符合 FDA/药典要求及温度等级"; return "可接受"; }
|
||||
if (m.Contains("铝") || m == "AL") { rec = "铝合金不可直接接触物料, 需阳极氧化/隔离处理"; return "警告"; }
|
||||
if (m.Contains("钢") || m.Contains("铁")) { rec = "碳钢/普通钢不可接触物料, 需改不锈钢或加涂层隔离"; return "未通过"; }
|
||||
if (m.Contains("铜") || m.Contains("锌")) { rec = "铜/锌及其合金不宜直接接触药品物料"; return "未通过"; }
|
||||
rec = "无法识别的材料, 请人工确认";
|
||||
return "警告";
|
||||
}
|
||||
|
||||
private static readonly string[] SealKeys = { "O型圈", "O形圈", "O-RING", "密封圈", "密封垫", "密封条", "密封件", "SEAL", "GASKET", "垫片", "EPDM", "三元乙丙", "氟胶", "硅胶圈" };
|
||||
private static readonly string[] StdKeys = { "螺栓", "螺钉", "螺母", "垫圈", "垫片", "销", "键", "轴承", "电机", "减速机", "气缸", "阀", "泵", "传感器", "PLC", "变频器", "伺服", "型材", "钢管", "法兰", "接头", "卡箍", "视镜", "密封圈", "联轴器", "导向轴", "导轨", "弹簧", "内六角", "GB", "TB", "ISO", "DIN", "JB" };
|
||||
|
||||
public static bool IsSealPartName(string nm)
|
||||
{
|
||||
string u = (nm ?? "").ToUpper();
|
||||
foreach (string k in SealKeys)
|
||||
if (u.Contains(k.ToUpper())) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsStdPartName(string nm)
|
||||
{
|
||||
string u = (nm ?? "").ToUpper();
|
||||
foreach (string k in StdKeys)
|
||||
if (u.Contains(k.ToUpper())) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
// 检查主窗口: TableLayoutPanel 百分比布局, 左树 25% + 右表 75%, 无固定尺寸不遮罩
|
||||
public class MainForm : Form
|
||||
{
|
||||
private DataGridView grid;
|
||||
private TreeView tree;
|
||||
private Label lblSummary;
|
||||
private StatusStrip status;
|
||||
private string mStage = "";
|
||||
|
||||
public MainForm()
|
||||
{
|
||||
BuildUI();
|
||||
}
|
||||
|
||||
private void BuildUI()
|
||||
{
|
||||
Text = "Design Express Res - 设计标注检查";
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
WindowState = FormWindowState.Normal;
|
||||
Rectangle wa = Screen.PrimaryScreen.WorkingArea;
|
||||
Size = new Size(wa.Width / 2, wa.Height / 2);
|
||||
MinimumSize = new Size(720, 460);
|
||||
|
||||
// 主布局: 两列百分比 25% / 75%
|
||||
TableLayoutPanel master = new TableLayoutPanel();
|
||||
master.Dock = DockStyle.Fill;
|
||||
master.ColumnCount = 2;
|
||||
master.RowCount = 1;
|
||||
master.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 25F));
|
||||
master.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 75F));
|
||||
master.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||
master.Margin = new Padding(0);
|
||||
master.Padding = new Padding(0);
|
||||
|
||||
// 左: 检查项树
|
||||
tree = new TreeView();
|
||||
tree.Dock = DockStyle.Fill;
|
||||
tree.FullRowSelect = true;
|
||||
tree.ShowLines = true;
|
||||
tree.ShowPlusMinus = true;
|
||||
tree.HideSelection = false;
|
||||
tree.BorderStyle = BorderStyle.FixedSingle;
|
||||
FillTree();
|
||||
master.Controls.Add(tree, 0, 0);
|
||||
|
||||
// 右: 汇总 + 结果表格
|
||||
Panel right = new Panel();
|
||||
right.Dock = DockStyle.Fill;
|
||||
right.Margin = new Padding(0);
|
||||
|
||||
grid = new DataGridView();
|
||||
grid.Dock = DockStyle.Fill;
|
||||
grid.ReadOnly = true;
|
||||
grid.AllowUserToAddRows = false;
|
||||
grid.AllowUserToDeleteRows = false;
|
||||
grid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||
grid.MultiSelect = false;
|
||||
grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
|
||||
grid.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
grid.BorderStyle = BorderStyle.None;
|
||||
grid.Columns.Add("CheckID", "编号");
|
||||
grid.Columns.Add("Name", "检查项");
|
||||
grid.Columns.Add("Obj", "对象");
|
||||
grid.Columns.Add("Result", "结果");
|
||||
grid.Columns.Add("Note", "说明");
|
||||
grid.Columns.Add("Basis", "判定依据");
|
||||
grid.Columns["Note"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
|
||||
grid.Columns["Basis"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
|
||||
right.Controls.Add(grid);
|
||||
|
||||
lblSummary = new Label();
|
||||
lblSummary.Dock = DockStyle.Top;
|
||||
lblSummary.AutoSize = true;
|
||||
lblSummary.TextAlign = ContentAlignment.MiddleLeft;
|
||||
lblSummary.Padding = new Padding(8, 6, 0, 6);
|
||||
lblSummary.Font = new Font("Microsoft YaHei", 9.5f);
|
||||
lblSummary.Text = "就绪: 请先打开文档, 然后在功能区点击检查按钮";
|
||||
right.Controls.Add(lblSummary);
|
||||
|
||||
master.Controls.Add(right, 1, 0);
|
||||
|
||||
// Dock 顺序: Fill 先 Add, Bottom 后 Add
|
||||
Controls.Add(master);
|
||||
status = new StatusStrip();
|
||||
Controls.Add(status);
|
||||
|
||||
Shown += delegate { LoadCurrentResults(); };
|
||||
}
|
||||
|
||||
private void FillTree()
|
||||
{
|
||||
tree.Nodes.Clear();
|
||||
TreeNode root = new TreeNode("检查项清单");
|
||||
TreeNode part = new TreeNode("零件阶段 (P)");
|
||||
part.Nodes.Add("P01~P07 保存状态/代号/名称/材料/设计者/审核者/修订号");
|
||||
part.Nodes.Add("P08 模型标注统计/公差覆盖/形位公差/粗糙度");
|
||||
part.Nodes.Add("P09 公差配合检查 (GB/T 275/GB/T 1801)");
|
||||
part.Nodes.Add("P10~P12 配合面形位公差/粗糙度/公差等级");
|
||||
part.Nodes.Add("P13 螺纹孔检查");
|
||||
part.Nodes.Add("P14 物料接触 + GMP 专项");
|
||||
part.Nodes.Add("P15 焊接标注");
|
||||
part.Nodes.Add("P16 表面处理/防锈");
|
||||
part.Nodes.Add("P17 结构强度/仿真指引");
|
||||
root.Nodes.Add(part);
|
||||
|
||||
TreeNode asm = new TreeNode("装配阶段 (A)");
|
||||
asm.Nodes.Add("A01 文档保存状态");
|
||||
asm.Nodes.Add("A02 GMP 材料合规");
|
||||
asm.Nodes.Add("A03/A04 密封件存在性 + 密封设计提示");
|
||||
asm.Nodes.Add("A05 清洁性设计要求");
|
||||
asm.Nodes.Add("A06 GMP 粗糙度标注");
|
||||
asm.Nodes.Add("A07 静态干涉检查");
|
||||
asm.Nodes.Add("A08 运动干涉(动态)指引");
|
||||
asm.Nodes.Add("A09 外购件优先统计");
|
||||
asm.Nodes.Add("A10 电气选型/西门子联网");
|
||||
asm.Nodes.Add("A11 施工/公共动力系统");
|
||||
asm.Nodes.Add("A12 整机强度/仿真指引");
|
||||
root.Nodes.Add(asm);
|
||||
|
||||
TreeNode drw = new TreeNode("工程图阶段 (D)");
|
||||
drw.Nodes.Add("D00~D09 保存/图框/标题栏/空白/更新/剖视/越界/尺寸/公差/文本");
|
||||
drw.Nodes.Add("D10~D17 形位公差/基准/粗糙度/焊接/孔标注/中心线/越界/图幅");
|
||||
drw.Nodes.Add("D18 物料接触类别声明");
|
||||
drw.Nodes.Add("D19 焊接技术要求(双面焊/打磨)");
|
||||
drw.Nodes.Add("D20 死角/夹角要求(R10/135度)");
|
||||
drw.Nodes.Add("D21~D25 公差/轴承位/螺纹孔/镀镍/平面度");
|
||||
drw.Nodes.Add("D26~D32 角度管/治具/辅助件/外购/测试/装配/防锈");
|
||||
drw.Nodes.Add("D33~D39 施工动力/配孔/吊顶/电气/西门子/强度/夹角");
|
||||
root.Nodes.Add(drw);
|
||||
|
||||
tree.Nodes.Add(root);
|
||||
root.ExpandAll();
|
||||
}
|
||||
|
||||
public void LoadCurrentResults()
|
||||
{
|
||||
grid.Rows.Clear();
|
||||
int pass = 0, warn = 0, fail = 0, info = 0;
|
||||
foreach (CheckResult r in AppState.Results)
|
||||
{
|
||||
int idx = grid.Rows.Add(r.CheckID, r.Name, r.Obj, r.Result, r.Note, r.Basis);
|
||||
DataGridViewRow row = grid.Rows[idx];
|
||||
switch (r.Result)
|
||||
{
|
||||
case "通过": row.DefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(0xE8, 0xFF, 0xE8); break;
|
||||
case "警告": row.DefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(0xFF, 0xFF, 0xE0); break;
|
||||
case "未通过": row.DefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(0xFF, 0xE0, 0xE0); break;
|
||||
default: row.DefaultCellStyle.BackColor = System.Drawing.Color.FromArgb(0xF0, 0xF0, 0xF0); break;
|
||||
}
|
||||
switch (r.Result)
|
||||
{
|
||||
case "通过": pass++; break;
|
||||
case "警告": warn++; break;
|
||||
case "未通过": fail++; break;
|
||||
default: info++; break;
|
||||
}
|
||||
}
|
||||
lblSummary.Text = string.Format("检查项: {0} 通过: {1} 警告: {2} 未通过: {3} 信息: {4}",
|
||||
AppState.Results.Count, pass, warn, fail, info);
|
||||
status.Items.Clear();
|
||||
status.Items.Add("当前阶段: " + (mStage == "" ? "全部" : mStage));
|
||||
}
|
||||
|
||||
public void RunAndLoad(string stage, Action run)
|
||||
{
|
||||
try
|
||||
{
|
||||
Cursor = Cursors.WaitCursor;
|
||||
AppState.Results.Clear();
|
||||
mStage = stage;
|
||||
run();
|
||||
LoadCurrentResults();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("检查出错: " + ex.Message, "Design Express Res", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Cursor = Cursors.Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
// 设计数据查询窗口: 一个按钮对应一个功能页, 无切换菜单
|
||||
// TableLayoutPanel 百分比布局: 头部 AutoSize(自适应文字高度), 左输入 35% / 右结果 65%
|
||||
public class QueryForm : Form
|
||||
{
|
||||
private static QueryForm mForm;
|
||||
|
||||
private class ModuleDef
|
||||
{
|
||||
public string Title; // 窗口标题
|
||||
public string SubTitle; // 页头主标题
|
||||
public string Desc; // 功能说明
|
||||
}
|
||||
|
||||
private static readonly ModuleDef[] Modules = new ModuleDef[]
|
||||
{
|
||||
new ModuleDef { Title = "卡簧槽查询 (GB/T 894)", SubTitle = "轴用/孔用弹性挡圈槽尺寸查询", Desc = "输入轴径或孔径, 查询挡圈型号、槽径、槽宽、槽深等设计尺寸" },
|
||||
new ModuleDef { Title = "键槽查询 (GB/T 1095)", SubTitle = "平键键槽尺寸查询", Desc = "输入轴径, 查询键的公称尺寸(b×h×L)、轴槽深、轮毂槽深、键槽长度系列等" },
|
||||
new ModuleDef { Title = "O 型密封圈查询 (GB/T 3452.1)", SubTitle = "O 型密封圈设计", Desc = "输入密封轴径/孔径, 查询圈规格、沟槽尺寸(径向/轴向密封)、压缩量、挡圈配合等" },
|
||||
new ModuleDef { Title = "轴承挡圈查询", SubTitle = "轴承挡圈设计", Desc = "输入轴承外径/内径, 查询挡圈规格、挡边高度、安装槽尺寸、轴向定位设计等" }
|
||||
};
|
||||
|
||||
private Label lblTitle;
|
||||
private Label lblDesc;
|
||||
private FlowLayoutPanel inFlow;
|
||||
private DataGridView grid;
|
||||
private Label outHint;
|
||||
|
||||
public QueryForm(int moduleIndex)
|
||||
{
|
||||
BuildUI(moduleIndex);
|
||||
}
|
||||
|
||||
public static void ShowQuery(int moduleIndex)
|
||||
{
|
||||
if (moduleIndex < 0 || moduleIndex >= Modules.Length) return;
|
||||
if (mForm == null || mForm.IsDisposed)
|
||||
mForm = new QueryForm(moduleIndex);
|
||||
mForm.ApplyModule(moduleIndex);
|
||||
mForm.Show();
|
||||
mForm.Activate();
|
||||
}
|
||||
|
||||
private void BuildUI(int moduleIndex)
|
||||
{
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
WindowState = FormWindowState.Normal;
|
||||
Rectangle wa = Screen.PrimaryScreen.WorkingArea;
|
||||
Size = new Size(wa.Width / 2, wa.Height / 2);
|
||||
MinimumSize = new Size(700, 460);
|
||||
|
||||
// 主布局: 2 行(头部 AutoSize + 主体 100%), 主体 2 列(左 35% / 右 65%)
|
||||
TableLayoutPanel master = new TableLayoutPanel();
|
||||
master.Dock = DockStyle.Fill;
|
||||
master.ColumnCount = 2;
|
||||
master.RowCount = 2;
|
||||
master.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 35F));
|
||||
master.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 65F));
|
||||
master.RowStyles.Add(new RowStyle(SizeType.AutoSize));
|
||||
master.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||
master.Margin = new Padding(0);
|
||||
master.Padding = new Padding(0);
|
||||
|
||||
// 头部标题区: 占满两列, AutoSize 高度, 文字永远不会被裁剪
|
||||
FlowLayoutPanel headFlow = new FlowLayoutPanel();
|
||||
headFlow.AutoSize = true;
|
||||
headFlow.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right;
|
||||
headFlow.FlowDirection = FlowDirection.TopDown;
|
||||
headFlow.WrapContents = false;
|
||||
headFlow.Padding = new Padding(10, 8, 0, 2);
|
||||
headFlow.Margin = new Padding(0);
|
||||
|
||||
lblTitle = new Label();
|
||||
lblTitle.Font = new Font("Microsoft YaHei", 12.5f, FontStyle.Bold);
|
||||
lblTitle.AutoSize = true;
|
||||
lblTitle.Margin = new Padding(0, 0, 0, 2);
|
||||
headFlow.Controls.Add(lblTitle);
|
||||
|
||||
lblDesc = new Label();
|
||||
lblDesc.Font = new Font("Microsoft YaHei", 9f);
|
||||
lblDesc.ForeColor = System.Drawing.Color.Gray;
|
||||
lblDesc.AutoSize = true;
|
||||
lblDesc.Margin = new Padding(0);
|
||||
headFlow.Controls.Add(lblDesc);
|
||||
|
||||
master.Controls.Add(headFlow, 0, 0);
|
||||
master.SetColumnSpan(headFlow, 2);
|
||||
|
||||
// 左: 输入参数 (35%)
|
||||
GroupBox input = new GroupBox();
|
||||
input.Dock = DockStyle.Fill;
|
||||
input.Text = "输入参数";
|
||||
input.Font = new Font("Microsoft YaHei", 10f);
|
||||
input.Margin = new Padding(6, 3, 3, 6);
|
||||
|
||||
inFlow = new FlowLayoutPanel();
|
||||
inFlow.Dock = DockStyle.Fill;
|
||||
inFlow.FlowDirection = FlowDirection.TopDown;
|
||||
inFlow.WrapContents = false;
|
||||
inFlow.Padding = new Padding(10, 8, 10, 8);
|
||||
inFlow.AutoScroll = true;
|
||||
input.Controls.Add(inFlow);
|
||||
master.Controls.Add(input, 0, 1);
|
||||
|
||||
// 右: 查询结果 (65%)
|
||||
GroupBox result = new GroupBox();
|
||||
result.Dock = DockStyle.Fill;
|
||||
result.Text = "查询结果";
|
||||
result.Font = new Font("Microsoft YaHei", 10f);
|
||||
result.Margin = new Padding(3, 3, 6, 6);
|
||||
|
||||
grid = new DataGridView();
|
||||
grid.Dock = DockStyle.Fill;
|
||||
grid.ReadOnly = true;
|
||||
grid.AllowUserToAddRows = false;
|
||||
grid.AllowUserToDeleteRows = false;
|
||||
grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
|
||||
grid.RowHeadersVisible = false;
|
||||
grid.BackgroundColor = Color.White;
|
||||
grid.BorderStyle = BorderStyle.None;
|
||||
grid.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||
grid.Columns.Add("Item", "项目");
|
||||
grid.Columns.Add("Value", "数值");
|
||||
grid.Columns.Add("Std", "标准");
|
||||
grid.Columns.Add("Remark", "备注");
|
||||
result.Controls.Add(grid);
|
||||
|
||||
outHint = new Label();
|
||||
outHint.Dock = DockStyle.Top;
|
||||
outHint.AutoSize = true;
|
||||
outHint.TextAlign = ContentAlignment.MiddleLeft;
|
||||
outHint.Padding = new Padding(6, 4, 0, 4);
|
||||
outHint.ForeColor = System.Drawing.Color.Gray;
|
||||
outHint.Font = new Font("Microsoft YaHei", 9.5f);
|
||||
result.Controls.Add(outHint);
|
||||
|
||||
master.Controls.Add(result, 1, 1);
|
||||
|
||||
Controls.Add(master);
|
||||
|
||||
ApplyModule(moduleIndex);
|
||||
}
|
||||
|
||||
// 切换到指定功能模块(无菜单, 直接换内容)
|
||||
private void ApplyModule(int moduleIndex)
|
||||
{
|
||||
ModuleDef m = Modules[moduleIndex];
|
||||
Text = "Design Express Res - " + m.Title;
|
||||
lblTitle.Text = m.SubTitle;
|
||||
lblDesc.Text = m.Desc;
|
||||
BuildModuleUI((QueryKind)moduleIndex);
|
||||
}
|
||||
|
||||
private void BuildModuleUI(QueryKind kind)
|
||||
{
|
||||
inFlow.Controls.Clear();
|
||||
|
||||
if (kind == QueryKind.Keyway || kind == QueryKind.Circlip)
|
||||
{
|
||||
Label hint = new Label();
|
||||
hint.Text = "输入轴径, 点击查询获取设计尺寸";
|
||||
hint.Font = new Font("Microsoft YaHei", 9.5f);
|
||||
hint.ForeColor = System.Drawing.Color.Gray;
|
||||
hint.AutoSize = true;
|
||||
hint.Margin = new Padding(0, 0, 0, 6);
|
||||
inFlow.Controls.Add(hint);
|
||||
|
||||
TextBox txtDia = new TextBox();
|
||||
txtDia.Width = 110;
|
||||
txtDia.Font = new Font("Microsoft YaHei", 10f);
|
||||
txtDia.Text = "30";
|
||||
|
||||
Button btnQuery = new Button();
|
||||
btnQuery.Text = "查询";
|
||||
btnQuery.Width = 70;
|
||||
btnQuery.Height = 26;
|
||||
btnQuery.Font = new Font("Microsoft YaHei", 9.5f);
|
||||
|
||||
AddInputRow("轴径 d (mm):", txtDia, btnQuery);
|
||||
|
||||
Label note = new Label();
|
||||
note.Text = "数据为常用参考值, 正式设计请核对最新版标准";
|
||||
note.Font = new Font("Microsoft YaHei", 8.5f);
|
||||
note.ForeColor = System.Drawing.Color.Gray;
|
||||
note.AutoSize = true;
|
||||
note.Margin = new Padding(0, 10, 0, 0);
|
||||
inFlow.Controls.Add(note);
|
||||
|
||||
btnQuery.Click += delegate { DoQuery(kind, txtDia.Text); };
|
||||
txtDia.KeyDown += delegate(object s, KeyEventArgs e)
|
||||
{
|
||||
if (e.KeyCode == Keys.Enter) DoQuery(kind, txtDia.Text);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Label hint1 = new Label();
|
||||
hint1.Text = "参数输入区(开发中)";
|
||||
hint1.Font = new Font("Microsoft YaHei", 10f, FontStyle.Bold);
|
||||
hint1.AutoSize = true;
|
||||
hint1.Margin = new Padding(0, 0, 0, 6);
|
||||
inFlow.Controls.Add(hint1);
|
||||
|
||||
foreach (string t in new string[] {
|
||||
"后续在此放置:",
|
||||
"直径/尺寸输入框",
|
||||
"标准选择(系列/等级)",
|
||||
"查询按钮" })
|
||||
{
|
||||
Label l = new Label();
|
||||
l.Text = t;
|
||||
l.AutoSize = true;
|
||||
l.ForeColor = System.Drawing.Color.Gray;
|
||||
l.Margin = new Padding(0, 0, 0, 2);
|
||||
inFlow.Controls.Add(l);
|
||||
}
|
||||
}
|
||||
outHint.Text = "请输入参数后点击查询";
|
||||
}
|
||||
|
||||
private void AddInputRow(string labelText, TextBox txt, Button btn)
|
||||
{
|
||||
FlowLayoutPanel row = new FlowLayoutPanel();
|
||||
row.AutoSize = true;
|
||||
row.WrapContents = false;
|
||||
row.FlowDirection = FlowDirection.LeftToRight;
|
||||
row.Margin = new Padding(0, 2, 0, 2);
|
||||
|
||||
Label l = new Label();
|
||||
l.Text = labelText;
|
||||
l.AutoSize = true;
|
||||
l.Font = new Font("Microsoft YaHei", 10f);
|
||||
l.Margin = new Padding(0, 5, 6, 0);
|
||||
row.Controls.Add(l);
|
||||
|
||||
if (txt != null) row.Controls.Add(txt);
|
||||
if (btn != null) row.Controls.Add(btn);
|
||||
|
||||
inFlow.Controls.Add(row);
|
||||
}
|
||||
|
||||
private void DoQuery(QueryKind kind, string diaText)
|
||||
{
|
||||
double d;
|
||||
if (!double.TryParse(diaText.Trim(), out d) || d <= 0)
|
||||
{
|
||||
MessageBox.Show("请输入有效直径(mm)", "Design Express Res", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
|
||||
return;
|
||||
}
|
||||
grid.Rows.Clear();
|
||||
var rows = DesignQuery.Query(kind, d);
|
||||
foreach (QueryRow r in rows)
|
||||
{
|
||||
grid.Rows.Add(r.Item, r.Value, r.Std, r.Remark);
|
||||
}
|
||||
outHint.Text = "查询完成: 共 " + rows.Count + " 项结果 (输入直径 d=" + d.ToString("0.0") + " mm)";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
// 报告输出: Excel(COM 动态调用) 优先, CSV 兜底
|
||||
public static class Report
|
||||
{
|
||||
public const string ToolVersion = "1.3.0";
|
||||
|
||||
public static string WriteExcel(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
Type xlType = Type.GetTypeFromProgID("Excel.Application");
|
||||
if (xlType == null) return WriteCsv(path);
|
||||
dynamic xl = Activator.CreateInstance(xlType);
|
||||
try
|
||||
{
|
||||
xl.Visible = false;
|
||||
xl.DisplayAlerts = false;
|
||||
dynamic wb = xl.Workbooks.Add();
|
||||
|
||||
dynamic ws1 = wb.Worksheets[1];
|
||||
ws1.Name = "汇总";
|
||||
dynamic ws2 = wb.Worksheets.Add(Type.Missing, ws1);
|
||||
ws2.Name = "明细";
|
||||
dynamic ws3 = wb.Worksheets.Add(Type.Missing, ws2);
|
||||
ws3.Name = "检查项清单";
|
||||
|
||||
ws1.Cells[1, 1] = "设计标注检查报告";
|
||||
ws1.Cells[2, 1] = "检查时间: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
ws1.Cells[3, 1] = "工具版本: " + ToolVersion;
|
||||
|
||||
int pass, warn, fail, info;
|
||||
AppState.Count(out pass, out warn, out fail, out info);
|
||||
ws1.Cells[5, 1] = "检查项总数"; ws1.Cells[5, 2] = AppState.Results.Count;
|
||||
ws1.Cells[6, 1] = "通过"; ws1.Cells[6, 2] = pass;
|
||||
ws1.Cells[7, 1] = "警告"; ws1.Cells[7, 2] = warn;
|
||||
ws1.Cells[8, 1] = "未通过"; ws1.Cells[8, 2] = fail;
|
||||
ws1.Cells[9, 1] = "信息"; ws1.Cells[9, 2] = info;
|
||||
|
||||
ws1.Cells[11, 1] = "按检查项统计:";
|
||||
ws1.Cells[12, 1] = "编号"; ws1.Cells[12, 2] = "检查项";
|
||||
ws1.Cells[12, 3] = "总数"; ws1.Cells[12, 4] = "通过";
|
||||
ws1.Cells[12, 5] = "警告"; ws1.Cells[12, 6] = "未通过";
|
||||
BuildCheckStat(ws1, 13);
|
||||
ws1.Columns["A:F"].AutoFit();
|
||||
|
||||
ws2.Cells[1, 1] = "序号"; ws2.Cells[1, 2] = "阶段";
|
||||
ws2.Cells[1, 3] = "检查对象"; ws2.Cells[1, 4] = "编号";
|
||||
ws2.Cells[1, 5] = "检查项"; ws2.Cells[1, 6] = "结果";
|
||||
ws2.Cells[1, 7] = "说明"; ws2.Cells[1, 8] = "判定依据";
|
||||
int row = 2;
|
||||
foreach (CheckResult r in AppState.Results)
|
||||
{
|
||||
ws2.Cells[row, 1] = row - 1;
|
||||
ws2.Cells[row, 2] = r.Stage;
|
||||
ws2.Cells[row, 3] = r.Obj;
|
||||
ws2.Cells[row, 4] = r.CheckID;
|
||||
ws2.Cells[row, 5] = r.Name;
|
||||
ws2.Cells[row, 6] = r.Result;
|
||||
ws2.Cells[row, 7] = r.Note;
|
||||
ws2.Cells[row, 8] = r.Basis;
|
||||
dynamic cell = ws2.Cells[row, 6];
|
||||
if (r.Result == "通过") cell.Interior.Color = 0x00C8FFC8;
|
||||
else if (r.Result == "警告") cell.Interior.Color = 0x00C8FFFF;
|
||||
else if (r.Result == "未通过") cell.Interior.Color = 0x00C8C8FF;
|
||||
else cell.Interior.Color = 0x00E1E1E1;
|
||||
row++;
|
||||
}
|
||||
ws2.Columns["A:H"].AutoFit();
|
||||
|
||||
ws3.Cells[1, 1] = "编号"; ws3.Cells[1, 2] = "检查项";
|
||||
ws3.Cells[1, 3] = "阶段"; ws3.Cells[1, 4] = "说明";
|
||||
string[,] L = CheckList;
|
||||
for (int i = 0; i < L.GetLength(0); i++)
|
||||
{
|
||||
ws3.Cells[i + 2, 1] = L[i, 0];
|
||||
ws3.Cells[i + 2, 2] = L[i, 1];
|
||||
ws3.Cells[i + 2, 3] = L[i, 2];
|
||||
ws3.Cells[i + 2, 4] = L[i, 3];
|
||||
}
|
||||
ws3.Columns["A:D"].AutoFit();
|
||||
|
||||
string save = path.ToLower().EndsWith(".xlsx") ? path : path + ".xlsx";
|
||||
wb.SaveAs(save, 51);
|
||||
wb.Close(false);
|
||||
xl.Quit();
|
||||
return save;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { xl.Quit(); } catch { }
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return WriteCsv(path);
|
||||
}
|
||||
}
|
||||
|
||||
private static string[,] CheckList = BuildCheckList();
|
||||
|
||||
private static string[,] BuildCheckList()
|
||||
{
|
||||
string[,] L = new string[75, 4];
|
||||
string[] rows = new string[]
|
||||
{
|
||||
"P01,文档保存状态,零件,是否有未保存修改",
|
||||
"P02,零件代号,零件,标题栏必填",
|
||||
"P03,名称,零件,标题栏必填",
|
||||
"P04,材料,零件,必填且非默认",
|
||||
"P05,设计者,零件,标题栏必填",
|
||||
"P06,审核者,零件,标题栏必填",
|
||||
"P07,修订号,零件,版本追溯",
|
||||
"P08,模型标注统计,零件,PMI 三维标注完整性",
|
||||
"P08b,尺寸公差覆盖,零件,配合尺寸必须带公差",
|
||||
"P08c,形位公差标注,零件,跳动/同轴度/平面度等",
|
||||
"P08d,粗糙度标注,零件,配合/密封面必须标注",
|
||||
"P09,公差配合检查,零件,轴承配合按 GB/T 275, 一般配合按 GB/T 1801",
|
||||
"P10,配合面形位公差,零件,轴承位跳动/同轴度 IT5~IT6",
|
||||
"P11,配合面粗糙度,零件,轴颈 0.4~0.8, 座孔 0.8~1.6",
|
||||
"P12,轴承位公差等级,零件,轴颈 IT5~IT6, 座孔 IT7",
|
||||
"P13,螺纹孔检查,零件,螺纹特征及标注齐全",
|
||||
"P14,物料接触检查,零件,直接/间接/非接触分类",
|
||||
"P14b,GMP 接触材料,零件,直接接触须用 316L 级",
|
||||
"P14c,GMP 接触面粗糙度,零件,Ra<=0.8",
|
||||
"P14d,GMP 无死角检查,零件,圆角>=R10, 内夹角>=135度",
|
||||
"P15,焊接标注检查,零件,双面焊/打磨要求",
|
||||
"P16,表面处理/防锈,零件,镀镍/磨床/抛光/防锈包装",
|
||||
"P17,结构强度/仿真,零件,材料指定+CAE 校核指引",
|
||||
"A01,文档保存状态,装配,是否有未保存修改",
|
||||
"A02,GMP 材料合规,装配,全部零件材料合规",
|
||||
"A03,密封件存在性,装配,密封圈/O型圈/垫片识别",
|
||||
"A04,密封设计提示,装配,GB/T 3452.3 密封槽/FDA",
|
||||
"A05,清洁性设计要求,装配,清洁/CIP/死角/排空",
|
||||
"A06,GMP 粗糙度标注,装配,接触面 Ra<=0.8",
|
||||
"A07,静态干涉,装配,干涉分析",
|
||||
"A08,运动干涉(动态),装配,驱动约束/运动仿真",
|
||||
"A09,外购件优先,装配,标准/外购件比例",
|
||||
"A10,电气选型/西门子联网,装配,西门子/PROFINET/防爆/IP等级",
|
||||
"A11,施工/公共动力系统,装配,压缩空气/纯化水/蒸汽/排风/配孔/吊顶",
|
||||
"A12,整机强度/仿真指引,装配,建议应力分析/有限元校核",
|
||||
"D00,文档保存状态,工程图,是否有未保存修改",
|
||||
"D01,图框/标题栏,工程图,每张图纸必须有图框",
|
||||
"D02,标题栏属性,工程图,图号/名称/材料/设计/审核/修订号",
|
||||
"D03,空白图纸,工程图,无视图无标注",
|
||||
"D04,视图更新状态,工程图,出图前必须更新视图",
|
||||
"D05,剖视图统计,工程图,剖面线/剖切位置标注",
|
||||
"D06,视图越界,工程图,视图超出图框",
|
||||
"D07,尺寸数量,工程图,信息项",
|
||||
"D08,尺寸公差,工程图,配合/关键尺寸必须带公差",
|
||||
"D09,尺寸文本异常,工程图,含?的尺寸(测量失败)",
|
||||
"D10,形位公差,工程图,信息项",
|
||||
"D11,基准符号,工程图,API 不支持自动读取",
|
||||
"D12,表面粗糙度,工程图,信息项",
|
||||
"D13,焊接符号,工程图,API 不支持自动读取, 由 D19 覆盖",
|
||||
"D14,孔标注,工程图,API 不支持自动读取, 由 D23 覆盖",
|
||||
"D15,中心线/件号,工程图,信息项",
|
||||
"D16,标注越界,工程图,标注超出图框",
|
||||
"D17,图幅信息,工程图,信息项",
|
||||
"D18,物料接触类别声明,工程图,直接/间接接触标注",
|
||||
"D19,焊接技术要求,工程图,双面焊/打磨/焊接标准",
|
||||
"D20,死角/夹角要求,工程图,无死角/夹角>=135度",
|
||||
"D21,公差要求完整性,工程图,未注公差说明",
|
||||
"D22,轴承位公差标注,工程图,跳动/同轴/旋转精度",
|
||||
"D23,螺纹孔标注,工程图,螺纹代号/深度/攻深",
|
||||
"D24,表面处理/镀镍,工程图,镀镍后是否磨床/抛光",
|
||||
"D25,平面度/平行度,工程图,关键面平面度要求",
|
||||
"D26,特殊角度管加工,工程图,角度管/弯管要求",
|
||||
"D27,装配治具与检验,工程图,治具/检具/检验要求",
|
||||
"D28,加工辅助件要求,工程图,工艺/毛坯/余量",
|
||||
"D29,外购件优先,工程图,标准件优先采购",
|
||||
"D30,测试要求,工程图,试压/气密/出厂测试",
|
||||
"D31,装配要求,工程图,安装/扭矩/间隙",
|
||||
"D32,防锈要求,工程图,防锈/包装/海运",
|
||||
"D33,施工/公共动力系统,工程图,压缩空气/纯化水/蒸汽/排风",
|
||||
"D34,配孔技术要求,工程图,配孔/配钻/现场配",
|
||||
"D35,吊顶配件要求,工程图,吊顶/吊架/吊装",
|
||||
"D36,电气元件选型,工程图,防爆/IP等级/选型",
|
||||
"D37,西门子联网器件,工程图,西门子/PROFINET/联网",
|
||||
"D38,结构强度/仿真,工程图,强度校核/仿真说明",
|
||||
"D39,夹角R10/135度确认,工程图,死角夹角要求确认"
|
||||
};
|
||||
for (int i = 0; i < rows.Length; i++)
|
||||
{
|
||||
string[] p = rows[i].Split(',');
|
||||
for (int j = 0; j < 4; j++)
|
||||
if (j < p.Length) L[i, j] = p[j];
|
||||
}
|
||||
return L;
|
||||
}
|
||||
|
||||
private static void BuildCheckStat(dynamic ws, int startRow)
|
||||
{
|
||||
List<string> ids = new List<string>();
|
||||
List<string> names = new List<string>();
|
||||
foreach (CheckResult r in AppState.Results)
|
||||
{
|
||||
if (!ids.Contains(r.CheckID))
|
||||
{
|
||||
ids.Add(r.CheckID);
|
||||
names.Add(r.Name);
|
||||
}
|
||||
}
|
||||
int row = startRow;
|
||||
for (int i = 0; i < ids.Count; i++)
|
||||
{
|
||||
int nT = 0, nP = 0, nW = 0, nF = 0;
|
||||
foreach (CheckResult r in AppState.Results)
|
||||
{
|
||||
if (r.CheckID == ids[i])
|
||||
{
|
||||
nT++;
|
||||
if (r.Result == "通过") nP++;
|
||||
else if (r.Result == "警告") nW++;
|
||||
else if (r.Result == "未通过") nF++;
|
||||
}
|
||||
}
|
||||
ws.Cells[row, 1] = ids[i];
|
||||
ws.Cells[row, 2] = names[i];
|
||||
ws.Cells[row, 3] = nT;
|
||||
ws.Cells[row, 4] = nP;
|
||||
ws.Cells[row, 5] = nW;
|
||||
ws.Cells[row, 6] = nF;
|
||||
row++;
|
||||
}
|
||||
}
|
||||
|
||||
public static string WriteCsv(string path)
|
||||
{
|
||||
string save = path.ToLower().EndsWith(".csv") ? path : path + ".csv";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("序号,阶段,检查对象,编号,检查项,结果,说明,判定依据");
|
||||
int i = 1;
|
||||
foreach (CheckResult r in AppState.Results)
|
||||
{
|
||||
sb.Append(i).Append(',').Append(r.Stage).Append(',').Append(r.Obj).Append(',')
|
||||
.Append(r.CheckID).Append(',').Append(r.Name).Append(',').Append(r.Result).Append(',')
|
||||
.Append("\"").Append(r.Note.Replace("\"", "\"\"")).Append("\",\"")
|
||||
.Append(r.Basis.Replace("\"", "\"\"")).AppendLine("\"");
|
||||
i++;
|
||||
}
|
||||
System.IO.File.WriteAllText(save, sb.ToString(), new UTF8Encoding(true));
|
||||
return save;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
// 文档快照: Link 层把 CAD 文档状态拍成纯数据, Core 只处理快照, 与 CAD 完全解耦
|
||||
public class DocSnapshot
|
||||
{
|
||||
public string Kind = ""; // Part / Assembly / Drawing
|
||||
public bool Dirty;
|
||||
public string DisplayName = "";
|
||||
public string Folder = "";
|
||||
public Dictionary<string, string> Props = new Dictionary<string, string>();
|
||||
public string MaterialName = "";
|
||||
public ModelInfo Model; // 零件/装配的三维标注
|
||||
public AssemblyInfo Asm; // 装配
|
||||
public List<SheetInfo> Sheets = new List<SheetInfo>(); // 工程图
|
||||
public List<DocInfo> OpenDocs = new List<DocInfo>(); // 会话中已打开的文档
|
||||
}
|
||||
|
||||
public class DocInfo
|
||||
{
|
||||
public string Name = "";
|
||||
public Dictionary<string, string> Props = new Dictionary<string, string>();
|
||||
public string Material = "";
|
||||
public int TexCount = 0;
|
||||
}
|
||||
|
||||
public class ModelInfo
|
||||
{
|
||||
public int DimCount = -1;
|
||||
public int FcfCount = -1;
|
||||
public int TexCount = -1;
|
||||
public int DatumCount = -1;
|
||||
public int ThreadNoteCount = -1;
|
||||
public int TolCount = 0;
|
||||
public bool TolReadable = true;
|
||||
public string FirstTexText = "";
|
||||
public int ThreadFeatureCount = -1;
|
||||
public string ThreadDesignation = "";
|
||||
public bool MinFilletReadable = false;
|
||||
public double MinFilletRadiusMM = -1;
|
||||
}
|
||||
|
||||
public class AssemblyInfo
|
||||
{
|
||||
public List<string> OccurrenceNames = new List<string>();
|
||||
public List<InterferencePair> Interferences = new List<InterferencePair>();
|
||||
public int InterferenceState = 0; // 0=无干涉 1=发现干涉 2=检查失败
|
||||
public string InterferenceError = "";
|
||||
public int TopLevelCount = 0;
|
||||
}
|
||||
|
||||
public class InterferencePair
|
||||
{
|
||||
public string Name1 = "";
|
||||
public string Name2 = "";
|
||||
public double VolumeCM3 = 0;
|
||||
}
|
||||
|
||||
public class RectD
|
||||
{
|
||||
public double L, T, R, B;
|
||||
}
|
||||
|
||||
public class SheetInfo
|
||||
{
|
||||
public string Name = "";
|
||||
public bool HasBorder = false;
|
||||
public bool HasTitleBlock = false;
|
||||
public string TitleBlockName = "";
|
||||
public double SheetWidth = 0, SheetHeight = 0;
|
||||
public RectD BorderRect; // null 表示无图框
|
||||
public int ViewCount = 0;
|
||||
public int UpdateNeeded = 0;
|
||||
public int UpdateError = 0;
|
||||
public int SectionCount = 0;
|
||||
public List<RectD> ViewRects = new List<RectD>();
|
||||
public int DimCount = 0;
|
||||
public int DimTolCount = 0;
|
||||
public int DimQuestionCount = 0;
|
||||
public int FcfCount = 0;
|
||||
public int TexCount = 0;
|
||||
public int CenterlineCount = 0;
|
||||
public int BalloonCount = 0;
|
||||
public List<string> NotesTexts = new List<string>();
|
||||
public List<RectD> FcfRects = new List<RectD>();
|
||||
public List<RectD> TexRects = new List<RectD>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace DesignExpress.Core
|
||||
{
|
||||
// 功能按钮图标类型
|
||||
public enum ToolIcon
|
||||
{
|
||||
Part, // 零件-齿轮
|
||||
Asm, // 装配-方块
|
||||
Drw, // 工程图-图纸
|
||||
Export, // 导出-报告
|
||||
Help, // 说明-问号
|
||||
Circlip, // 卡簧槽-开口卡簧
|
||||
Keyway, // 键槽-轴槽
|
||||
Oring, // O型圈-圆环
|
||||
Bearing // 轴承挡圈-轴承
|
||||
}
|
||||
|
||||
// 共享图标生成器: 仓鼠品牌形象 + 功能符号, 供 Inventor(.ico) 和 SolidWorks(图标条BMP) 复用
|
||||
public static class ToolIcons
|
||||
{
|
||||
private static readonly Color[] BgColors = new Color[]
|
||||
{
|
||||
Color.FromArgb(0x2E, 0x75, 0xB6), // Part 蓝
|
||||
Color.FromArgb(0x33, 0x8A, 0x4E), // Asm 绿
|
||||
Color.FromArgb(0xE6, 0x8A, 0x00), // Drw 橙
|
||||
Color.FromArgb(0x7B, 0x4F, 0xB0), // Export 紫
|
||||
Color.FromArgb(0x5F, 0x5F, 0x5F), // Help 灰
|
||||
Color.FromArgb(0x1F, 0x8A, 0x8A), // Circlip 青
|
||||
Color.FromArgb(0x8A, 0x5A, 0x2E), // Keyway 棕
|
||||
Color.FromArgb(0xC0, 0x3A, 0x2B), // Oring 红
|
||||
Color.FromArgb(0xD2, 0x5E, 0x8A) // Bearing 粉
|
||||
};
|
||||
|
||||
public static Color IconColor(ToolIcon icon)
|
||||
{
|
||||
return BgColors[(int)icon];
|
||||
}
|
||||
|
||||
// 绘制单个图标到指定位置: 中央大功能符号 + 底部小仓鼠品牌点缀
|
||||
private static void DrawIcon(Graphics g, int ox, int oy, int size, ToolIcon icon, Color bg)
|
||||
{
|
||||
Color fur = Color.FromArgb(0xE8, 0xC0, 0x7D);
|
||||
Color ear = Color.FromArgb(0xC8, 0x8A, 0x4F);
|
||||
Color dark = Color.FromArgb(0x3A, 0x24, 0x10);
|
||||
Color pink = Color.FromArgb(0xF2, 0x9E, 0xB6);
|
||||
|
||||
using (GraphicsPath path = RoundedRect(ox + 1, oy + 1, size - 2, size - 2, 6))
|
||||
using (SolidBrush bgb = new SolidBrush(bg))
|
||||
{
|
||||
g.FillPath(bgb, path);
|
||||
}
|
||||
|
||||
using (SolidBrush bEar = new SolidBrush(ear))
|
||||
using (SolidBrush bFur = new SolidBrush(fur))
|
||||
using (SolidBrush bDark = new SolidBrush(dark))
|
||||
using (SolidBrush bPink = new SolidBrush(pink))
|
||||
using (SolidBrush bWhite = new SolidBrush(Color.White))
|
||||
using (Pen pWhite = new Pen(Color.White, 2f))
|
||||
{
|
||||
// 中央功能符号(大, 醒目)
|
||||
int cx = ox + size / 2;
|
||||
int cy = oy + size / 2 - 2;
|
||||
switch (icon)
|
||||
{
|
||||
case ToolIcon.Part: // 齿轮
|
||||
g.FillEllipse(bWhite, cx - 4, cy - 4, 8, 8);
|
||||
g.FillRectangle(bWhite, cx - 6.5f, cy - 1.5f, 13, 3);
|
||||
g.FillRectangle(bWhite, cx - 1.5f, cy - 6.5f, 3, 13);
|
||||
g.FillRectangle(bWhite, cx - 5.5f, cy - 5.5f, 3, 3);
|
||||
g.FillRectangle(bWhite, cx + 2.5f, cy - 5.5f, 3, 3);
|
||||
g.FillRectangle(bWhite, cx - 5.5f, cy + 2.5f, 3, 3);
|
||||
g.FillRectangle(bWhite, cx + 2.5f, cy + 2.5f, 3, 3);
|
||||
break;
|
||||
case ToolIcon.Asm: // 三个方块(品字)
|
||||
g.FillRectangle(bWhite, cx - 8, cy - 5, 6, 6);
|
||||
g.FillRectangle(bWhite, cx + 2, cy - 5, 6, 6);
|
||||
g.FillRectangle(bWhite, cx - 3, cy + 2, 6, 6);
|
||||
break;
|
||||
case ToolIcon.Drw: // 图纸
|
||||
g.DrawRectangle(pWhite, cx - 6, cy - 6, 12, 12);
|
||||
g.DrawLine(pWhite, cx - 6, cy - 2, cx + 0, cy - 2);
|
||||
g.DrawLine(pWhite, cx - 6, cy + 2, cx + 2, cy + 2);
|
||||
g.DrawLine(pWhite, cx - 2, cy + 6, cx + 3, cy + 1);
|
||||
break;
|
||||
case ToolIcon.Export: // 报告表格
|
||||
g.FillRectangle(bWhite, cx - 6, cy - 6, 12, 12);
|
||||
using (SolidBrush bBg = new SolidBrush(bg))
|
||||
{
|
||||
g.FillRectangle(bBg, cx - 4, cy - 3, 8, 2);
|
||||
g.FillRectangle(bBg, cx - 4, cy + 0, 8, 2);
|
||||
g.FillRectangle(bBg, cx - 4, cy + 3, 5, 2);
|
||||
}
|
||||
break;
|
||||
case ToolIcon.Help: // 问号
|
||||
using (Font f = new Font("Arial", 13f, FontStyle.Bold, GraphicsUnit.Pixel))
|
||||
{
|
||||
g.DrawString("?", f, bWhite, cx - 4, cy - 9);
|
||||
}
|
||||
break;
|
||||
case ToolIcon.Circlip: // 开口卡簧
|
||||
g.DrawArc(pWhite, cx - 6, cy - 5.5f, 12, 11, 40, 280);
|
||||
break;
|
||||
case ToolIcon.Keyway: // 轴键槽
|
||||
g.DrawEllipse(pWhite, cx - 6.5f, cy - 5, 13, 10);
|
||||
g.FillRectangle(bWhite, cx - 3, cy - 5, 6, 5);
|
||||
break;
|
||||
case ToolIcon.Oring: // O型圈
|
||||
g.DrawEllipse(pWhite, cx - 6.5f, cy - 5, 13, 10);
|
||||
g.DrawEllipse(pWhite, cx - 3.5f, cy - 2, 7, 4);
|
||||
break;
|
||||
case ToolIcon.Bearing: // 轴承
|
||||
g.DrawEllipse(pWhite, cx - 6.5f, cy - 5, 13, 10);
|
||||
g.FillEllipse(bWhite, cx - 1.5f, cy - 0.5f, 3, 3);
|
||||
g.FillEllipse(bWhite, cx - 5f, cy - 4f, 2, 2);
|
||||
g.FillEllipse(bWhite, cx + 3f, cy - 4f, 2, 2);
|
||||
g.FillEllipse(bWhite, cx - 5f, cy + 3f, 2, 2);
|
||||
g.FillEllipse(bWhite, cx + 3f, cy + 3f, 2, 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 直接绘制 Bitmap 并转 IPictureDisp(Inventor 按钮图标)
|
||||
public static object CreatePictureDisp(ToolIcon icon, int size)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Bitmap bmp = new Bitmap(size, size))
|
||||
{
|
||||
using (Graphics g = Graphics.FromImage(bmp))
|
||||
{
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
DrawIcon(g, 0, 0, size, icon, BgColors[(int)icon]);
|
||||
}
|
||||
IntPtr hbm = bmp.GetHbitmap();
|
||||
PICTDESC pd;
|
||||
pd.cbSizeofstruct = Marshal.SizeOf(typeof(PICTDESC));
|
||||
pd.picType = 1; // CT_BITMAP
|
||||
pd.hbitmap = hbm;
|
||||
pd.hpal = IntPtr.Zero;
|
||||
Guid iid = new Guid("7BF80981-BF32-101A-8BBB-00AA00300CAB"); // stdole.IPictureDisp 正确 IID(注意是81结尾)
|
||||
object ppv;
|
||||
int hr = OleCreatePictureIndirect(ref pd, ref iid, true, out ppv);
|
||||
if (hr != 0 || ppv == null) return Type.Missing;
|
||||
return ppv;
|
||||
}
|
||||
}
|
||||
catch { return Type.Missing; }
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct PICTDESC
|
||||
{
|
||||
public int cbSizeofstruct;
|
||||
public int picType;
|
||||
public IntPtr hbitmap;
|
||||
public IntPtr hpal;
|
||||
}
|
||||
|
||||
[DllImport("oleaut32.dll")]
|
||||
private static extern int OleCreatePictureIndirect(ref PICTDESC pDesc, ref Guid riid, bool fOwn, out object ppvObj);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool DeleteObject(IntPtr hObject);
|
||||
|
||||
// 生成单个 .ico 文件
|
||||
public static string CreateIco(ToolIcon icon, int size, string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Bitmap bmp = new Bitmap(size, size))
|
||||
{
|
||||
using (Graphics g = Graphics.FromImage(bmp))
|
||||
{
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.Clear(Color.FromArgb(0xFF, 0x00, 0xFF));
|
||||
DrawIcon(g, 0, 0, size, icon, BgColors[(int)icon]);
|
||||
}
|
||||
Icon ic = Icon.FromHandle(bmp.GetHicon());
|
||||
try
|
||||
{
|
||||
using (FileStream fs = new FileStream(file, FileMode.Create))
|
||||
ic.Save(fs);
|
||||
}
|
||||
finally
|
||||
{
|
||||
DestroyIcon(ic.Handle);
|
||||
}
|
||||
}
|
||||
return file;
|
||||
}
|
||||
catch { return ""; }
|
||||
}
|
||||
|
||||
// 生成 SolidWorks 图标条 BMP(每格 size, 横向拼接)
|
||||
public static string CreateStripBmp(ToolIcon[] icons, int size, string file)
|
||||
{
|
||||
try
|
||||
{
|
||||
int n = icons.Length;
|
||||
using (Bitmap bmp = new Bitmap(size * n, size))
|
||||
{
|
||||
using (Graphics g = Graphics.FromImage(bmp))
|
||||
{
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.Clear(Color.FromArgb(0xFF, 0x00, 0xFF));
|
||||
for (int i = 0; i < n; i++)
|
||||
DrawIcon(g, i * size, 0, size, icons[i], BgColors[(int)icons[i]]);
|
||||
}
|
||||
bmp.Save(file, System.Drawing.Imaging.ImageFormat.Bmp);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
catch { return ""; }
|
||||
}
|
||||
|
||||
[System.Runtime.InteropServices.DllImport("user32.dll")]
|
||||
private static extern bool DestroyIcon(IntPtr hIcon);
|
||||
|
||||
private static GraphicsPath RoundedRect(int x, int y, int w, int h, int r)
|
||||
{
|
||||
GraphicsPath p = new GraphicsPath();
|
||||
p.AddArc(x, y, r, r, 180, 90);
|
||||
p.AddArc(x + w - r, y, r, r, 270, 90);
|
||||
p.AddArc(x + w - r, y + h - r, r, r, 0, 90);
|
||||
p.AddArc(x, y + h - r, r, r, 90, 90);
|
||||
p.CloseFigure();
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Inventor;
|
||||
using DesignExpress.Core;
|
||||
|
||||
[assembly: ComVisible(true)]
|
||||
|
||||
namespace DesignExpress.InventorLink
|
||||
{
|
||||
[Guid("D422E0BF-02D0-4DAE-958A-7BBA80B718E9")]
|
||||
[ComVisible(true)]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[ProgId("DesignExpress.InventorLink.AddInServer")]
|
||||
public class AddInServer : ApplicationAddInServer
|
||||
{
|
||||
public const string TabId = "InvDesignCheck_Tab";
|
||||
public const string PanelId = "InvDesignCheck_Panel";
|
||||
public const string PanelQueryId = "InvDesignCheck_PanelQuery";
|
||||
private Application mApp;
|
||||
private string mClientId;
|
||||
private static Dictionary<string, Inventor.ButtonDefinition> mDefs = new Dictionary<string, Inventor.ButtonDefinition>();
|
||||
|
||||
public void Activate(ApplicationAddInSite addInSiteObject, bool firstTime)
|
||||
{
|
||||
try { mApp = (Application)addInSiteObject.Application; } catch { }
|
||||
try { mClientId = addInSiteObject.Parent.ClientId; } catch { }
|
||||
if (mApp == null) return;
|
||||
AppState.Host = new InventorHost(mApp);
|
||||
try { CreateRibbon(); } catch { }
|
||||
}
|
||||
|
||||
private void CreateRibbon()
|
||||
{
|
||||
Inventor.UserInterfaceManager uim = mApp.UserInterfaceManager;
|
||||
string[] ribNames = { "Part", "Assembly", "Drawing", "Presentation", "ZeroDoc" };
|
||||
foreach (string n in ribNames)
|
||||
{
|
||||
try
|
||||
{
|
||||
Inventor.Ribbon ribbon = uim.Ribbons[n];
|
||||
AddTabToRibbon(ribbon);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
private void AddTabToRibbon(Inventor.Ribbon ribbon)
|
||||
{
|
||||
Inventor.RibbonTab tab = null;
|
||||
try { tab = ribbon.RibbonTabs[TabId]; } catch { }
|
||||
if (tab == null)
|
||||
tab = ribbon.RibbonTabs.Add("Design Express Res", TabId, "", "", false, false);
|
||||
Inventor.RibbonPanel panel = null;
|
||||
try { panel = tab.RibbonPanels[PanelId]; } catch { }
|
||||
if (panel == null)
|
||||
panel = tab.RibbonPanels.Add("设计检查", PanelId, "", "", false);
|
||||
|
||||
if (panel.CommandControls.Count == 0)
|
||||
{
|
||||
panel.CommandControls.AddButton(GetDef("零件检查", "InvDesignCheck_CmdPart",
|
||||
"对当前零件进行三维标注、公差配合、GMP 检查",
|
||||
"零件检查:标注统计、公差配合(GB/T 275)、形位公差、粗糙度、螺纹孔、物料接触 GMP、表面处理",
|
||||
Checks.PartCheck));
|
||||
panel.CommandControls.AddButton(GetDef("装配检查", "InvDesignCheck_CmdAsm",
|
||||
"对当前装配进行 GMP、密封、干涉、外购件检查",
|
||||
"装配检查:GMP 材料合规、密封件、清洁性、粗糙度、静态干涉、外购件、电气/西门子、动力系统",
|
||||
Checks.AssemblyCheck));
|
||||
panel.CommandControls.AddButton(GetDef("工程图检查", "InvDesignCheck_CmdDrw",
|
||||
"对当前工程图进行标注与 spec 技术要求检查",
|
||||
"工程图检查:图框、标题栏、视图更新、尺寸公差、标注统计、spec 技术要求关键词齐全性",
|
||||
Checks.DrawingCheck));
|
||||
panel.CommandControls.AddButton(GetDef("导出报告", "InvDesignCheck_CmdExport",
|
||||
"导出检查报告(Excel/CSV)",
|
||||
"导出检查报告(Excel/CSV)",
|
||||
Checks.ExportReport));
|
||||
panel.CommandControls.AddButton(GetDef("使用说明", "InvDesignCheck_CmdHelp",
|
||||
"查看检查项清单与使用说明",
|
||||
"查看检查项清单与使用说明",
|
||||
Checks.Help));
|
||||
}
|
||||
|
||||
Inventor.RibbonPanel panelQuery = null;
|
||||
try { panelQuery = tab.RibbonPanels[PanelQueryId]; } catch { }
|
||||
if (panelQuery == null)
|
||||
panelQuery = tab.RibbonPanels.Add("设计数据查询", PanelQueryId, "", "", false);
|
||||
if (panelQuery.CommandControls.Count == 0)
|
||||
{
|
||||
panelQuery.CommandControls.AddButton(GetDef("卡簧槽查询", "InvDesignCheck_CmdCirclip",
|
||||
"轴用/孔用弹性挡圈槽尺寸查询 (GB/T 894)",
|
||||
"卡簧槽: 输入轴径/孔径, 查询挡圈型号、槽径、槽宽、槽深",
|
||||
Checks.CirclipQuery));
|
||||
panelQuery.CommandControls.AddButton(GetDef("键槽查询", "InvDesignCheck_CmdKeyway",
|
||||
"平键键槽尺寸查询 (GB/T 1095)",
|
||||
"键槽: 输入轴径, 查询键尺寸 b×h、轴槽深、轮毂槽深",
|
||||
Checks.KeywayQuery));
|
||||
panelQuery.CommandControls.AddButton(GetDef("O型密封圈查询", "InvDesignCheck_CmdOring",
|
||||
"O 型密封圈设计与沟槽尺寸查询 (GB/T 3452.1)",
|
||||
"O型密封圈: 查询圈规格、沟槽尺寸、压缩量",
|
||||
Checks.OringQuery));
|
||||
panelQuery.CommandControls.AddButton(GetDef("轴承挡圈查询", "InvDesignCheck_CmdBRing",
|
||||
"轴承挡圈与挡边设计查询",
|
||||
"轴承挡圈: 查询挡圈规格、挡边高度、安装槽尺寸",
|
||||
Checks.BearingRingQuery));
|
||||
}
|
||||
}
|
||||
|
||||
private Inventor.ButtonDefinition GetDef(string display, string internalName,
|
||||
string desc, string tip, Action action)
|
||||
{
|
||||
Inventor.ButtonDefinition def;
|
||||
lock (mDefs)
|
||||
{
|
||||
if (mDefs.TryGetValue(internalName, out def)) return def;
|
||||
// Inventor 图标需要 IPictureDisp(直接内存绘制, 不经过文件)
|
||||
object stdIcon = Type.Missing, largeIcon = Type.Missing;
|
||||
try
|
||||
{
|
||||
ToolIcon ic = IconEnum(IconName(internalName));
|
||||
stdIcon = ToolIcons.CreatePictureDisp(ic, 16);
|
||||
largeIcon = ToolIcons.CreatePictureDisp(ic, 32);
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
def = mApp.CommandManager.ControlDefinitions.AddButtonDefinition(
|
||||
display, internalName, CommandTypesEnum.kNonShapeEditCmdType, mClientId, desc, tip,
|
||||
stdIcon, largeIcon, ButtonDisplayEnum.kAlwaysDisplayText);
|
||||
}
|
||||
catch
|
||||
{
|
||||
def = mApp.CommandManager.ControlDefinitions.AddButtonDefinition(
|
||||
display, internalName, CommandTypesEnum.kNonShapeEditCmdType, mClientId, desc, tip,
|
||||
Type.Missing, Type.Missing, ButtonDisplayEnum.kAlwaysDisplayText);
|
||||
}
|
||||
mDefs[internalName] = def;
|
||||
// 关键: 直接订阅按钮的 OnExecute 事件处理点击(与 Joyea 一致, 不依赖 ExecuteCommand 路由)
|
||||
try
|
||||
{
|
||||
Inventor.ButtonDefinitionSink_Event evt = (Inventor.ButtonDefinitionSink_Event)def;
|
||||
evt.OnExecute += delegate(NameValueMap context)
|
||||
{
|
||||
try { action(); }
|
||||
catch (Exception ex) { System.Windows.Forms.MessageBox.Show("执行出错: " + ex.Message); }
|
||||
};
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
private static string IconName(string internalName)
|
||||
{
|
||||
if (internalName.EndsWith("Part")) return "part";
|
||||
if (internalName.EndsWith("Asm")) return "asm";
|
||||
if (internalName.EndsWith("Drw")) return "drw";
|
||||
if (internalName.EndsWith("Export")) return "export";
|
||||
if (internalName.EndsWith("Help")) return "help";
|
||||
if (internalName.EndsWith("Circlip")) return "circlip";
|
||||
if (internalName.EndsWith("Keyway")) return "keyway";
|
||||
if (internalName.EndsWith("Oring")) return "oring";
|
||||
if (internalName.EndsWith("BRing")) return "bearing";
|
||||
return "help";
|
||||
}
|
||||
|
||||
private static ToolIcon IconEnum(string name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case "part": return ToolIcon.Part;
|
||||
case "asm": return ToolIcon.Asm;
|
||||
case "drw": return ToolIcon.Drw;
|
||||
case "export": return ToolIcon.Export;
|
||||
case "help": return ToolIcon.Help;
|
||||
case "circlip": return ToolIcon.Circlip;
|
||||
case "keyway": return ToolIcon.Keyway;
|
||||
case "oring": return ToolIcon.Oring;
|
||||
case "bearing": return ToolIcon.Bearing;
|
||||
default: return ToolIcon.Help;
|
||||
}
|
||||
}
|
||||
|
||||
public void ExecuteCommand(int commandID)
|
||||
{
|
||||
// OnExecute 事件为主要路径, 此方法保留兼容(无操作)
|
||||
}
|
||||
|
||||
public object Automation { get { return null; } }
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
try
|
||||
{
|
||||
Inventor.UserInterfaceManager uim = mApp.UserInterfaceManager;
|
||||
string[] ribNames = { "Part", "Assembly", "Drawing", "Presentation", "ZeroDoc" };
|
||||
foreach (string n in ribNames)
|
||||
{
|
||||
try
|
||||
{
|
||||
Inventor.Ribbon ribbon = uim.Ribbons[n];
|
||||
Inventor.RibbonTab tab = null;
|
||||
try { tab = ribbon.RibbonTabs[TabId]; } catch { }
|
||||
if (tab != null) { try { tab.Delete(); } catch { } }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Inventor;
|
||||
using DesignExpress.Core;
|
||||
|
||||
namespace DesignExpress.InventorLink
|
||||
{
|
||||
// Inventor 适配器: 实现 ICadHost, 把 Inventor 文档状态拍成 Core 快照
|
||||
public class InventorHost : ICadHost
|
||||
{
|
||||
private Application mApp;
|
||||
|
||||
public InventorHost(Application app)
|
||||
{
|
||||
mApp = app;
|
||||
}
|
||||
|
||||
public string AppName { get { return "Inventor"; } }
|
||||
|
||||
public object GetActiveDocument()
|
||||
{
|
||||
try { return mApp.ActiveDocument; } catch { return null; }
|
||||
}
|
||||
|
||||
public string GetDocType(object doc)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic d = doc;
|
||||
DocumentTypeEnum t = (DocumentTypeEnum)d.DocumentType;
|
||||
if (t == DocumentTypeEnum.kPartDocumentObject) return "Part";
|
||||
if (t == DocumentTypeEnum.kAssemblyDocumentObject) return "Assembly";
|
||||
if (t == DocumentTypeEnum.kDrawingDocumentObject) return "Drawing";
|
||||
}
|
||||
catch { }
|
||||
return "";
|
||||
}
|
||||
|
||||
public void SetStatusText(string text)
|
||||
{
|
||||
try { mApp.StatusBarText = text; } catch { }
|
||||
}
|
||||
|
||||
public double PickCylinderDiameterMM(out string faceName)
|
||||
{
|
||||
faceName = "手动输入";
|
||||
try
|
||||
{
|
||||
object pick = mApp.CommandManager.Pick(SelectionFilterEnum.kPartFaceCylindricalFilter,
|
||||
"请选择轴承/配合圆柱面(轴或孔), 取消则手动输入直径");
|
||||
if (pick != null)
|
||||
{
|
||||
Face f = pick as Face;
|
||||
if (f != null)
|
||||
{
|
||||
object geom = f.Geometry;
|
||||
if (geom is Cylinder)
|
||||
{
|
||||
double d = ((Cylinder)geom).Radius * 20;
|
||||
try { faceName = Convert.ToString(((dynamic)f).Name); } catch { }
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return 0;
|
||||
}
|
||||
|
||||
public DocSnapshot Capture(object doc)
|
||||
{
|
||||
DocSnapshot snap = new DocSnapshot();
|
||||
dynamic d = doc;
|
||||
snap.Kind = GetDocType(doc);
|
||||
try { snap.Dirty = (bool)d.Dirty; } catch { }
|
||||
try { snap.DisplayName = Convert.ToString(d.DisplayName); } catch { }
|
||||
try
|
||||
{
|
||||
string full = Convert.ToString(d.FullDocumentName);
|
||||
int p = full.LastIndexOf('\\');
|
||||
if (p > 0) snap.Folder = full.Substring(0, p + 1);
|
||||
}
|
||||
catch { }
|
||||
|
||||
snap.Props = ReadProps(doc);
|
||||
|
||||
if (snap.Kind == "Part" || snap.Kind == "Assembly")
|
||||
{
|
||||
snap.MaterialName = ReadMaterial(d);
|
||||
snap.Model = ReadModelInfo(d);
|
||||
snap.Asm = new AssemblyInfo();
|
||||
}
|
||||
if (snap.Kind == "Assembly")
|
||||
{
|
||||
ReadAssemblyInfo(d, snap);
|
||||
}
|
||||
if (snap.Kind == "Drawing")
|
||||
{
|
||||
ReadDrawingInfo(d, snap);
|
||||
}
|
||||
ReadOpenDocs(snap);
|
||||
return snap;
|
||||
}
|
||||
|
||||
private Dictionary<string, string> ReadProps(object doc)
|
||||
{
|
||||
Dictionary<string, string> props = new Dictionary<string, string>();
|
||||
try
|
||||
{
|
||||
dynamic d = doc;
|
||||
foreach (PropertySet ps in d.PropertySets)
|
||||
{
|
||||
foreach (Property p in ps)
|
||||
{
|
||||
try
|
||||
{
|
||||
string key = Convert.ToString(p.Name);
|
||||
string val = Convert.ToString(p.Value);
|
||||
if (!string.IsNullOrEmpty(key) && !props.ContainsKey(key))
|
||||
props[key] = val ?? "";
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return props;
|
||||
}
|
||||
|
||||
private string ReadMaterial(dynamic d)
|
||||
{
|
||||
try { return Convert.ToString(d.ComponentDefinition.Material.Name); } catch { return ""; }
|
||||
}
|
||||
|
||||
private ModelInfo ReadModelInfo(dynamic d)
|
||||
{
|
||||
ModelInfo m = new ModelInfo();
|
||||
try
|
||||
{
|
||||
dynamic ma = d.ComponentDefinition.ModelAnnotations;
|
||||
try { m.DimCount = (int)ma.ModelDimensions.Count; } catch { }
|
||||
try { m.FcfCount = (int)ma.ModelFeatureControlFrames.Count; } catch { }
|
||||
try { m.TexCount = (int)ma.ModelSurfaceTextureSymbols.Count; } catch { }
|
||||
try { m.DatumCount = (int)ma.ModelDatumIdentifiers.Count; } catch { }
|
||||
try { m.ThreadNoteCount = (int)ma.ModelHoleThreadNotes.Count; } catch { }
|
||||
if (m.DimCount > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
int tol = 0;
|
||||
for (int i = 1; i <= m.DimCount; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic dd = ma.ModelDimensions[i];
|
||||
dynamic tolObj = dd.Definition.Tolerance;
|
||||
if (tolObj != null && tolObj.ToleranceType != ToleranceTypeEnum.kDefaultTolerance)
|
||||
tol++;
|
||||
}
|
||||
catch { m.TolReadable = false; }
|
||||
}
|
||||
m.TolCount = tol;
|
||||
}
|
||||
catch { m.TolReadable = false; }
|
||||
}
|
||||
if (m.TexCount > 0)
|
||||
{
|
||||
try { m.FirstTexText = Convert.ToString(ma.ModelSurfaceTextureSymbols[1].Text); } catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
dynamic tf = d.ComponentDefinition.Features.ThreadFeatures;
|
||||
m.ThreadFeatureCount = (int)tf.Count;
|
||||
if (m.ThreadFeatureCount > 0)
|
||||
{
|
||||
try { m.ThreadDesignation = Convert.ToString(tf[1].Designation); } catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
dynamic ff = d.ComponentDefinition.Features.FilletFeatures;
|
||||
int n = (int)ff.Count;
|
||||
double minR = -1;
|
||||
bool found = false;
|
||||
for (int i = 1; i <= n; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
double r = (double)ff[i].Radius;
|
||||
if (r > 0)
|
||||
{
|
||||
if (!found || r < minR) minR = r;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
m.MinFilletReadable = found;
|
||||
m.MinFilletRadiusMM = found ? minR * 10 : -1;
|
||||
}
|
||||
catch { }
|
||||
return m;
|
||||
}
|
||||
|
||||
private void ReadAssemblyInfo(dynamic d, DocSnapshot snap)
|
||||
{
|
||||
AssemblyInfo asm = snap.Asm;
|
||||
try
|
||||
{
|
||||
dynamic occs = d.ComponentDefinition.Occurrences;
|
||||
try { asm.TopLevelCount = (int)occs.Count; } catch { }
|
||||
CollectOccurrenceNames(occs, asm.OccurrenceNames);
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
dynamic acd = d.ComponentDefinition;
|
||||
ObjectCollection set1 = mApp.TransientObjects.CreateObjectCollection();
|
||||
dynamic occs = acd.Occurrences;
|
||||
int cnt = (int)occs.Count;
|
||||
for (int i = 1; i <= cnt; i++)
|
||||
set1.Add(occs[i]);
|
||||
dynamic res = acd.AnalyzeInterference(set1, null);
|
||||
int n = (int)res.Count;
|
||||
if (n > 0) asm.InterferenceState = 1;
|
||||
for (int j = 1; j <= n && j <= 50; j++)
|
||||
{
|
||||
InterferencePair pair = new InterferencePair();
|
||||
try
|
||||
{
|
||||
dynamic ir = res[j];
|
||||
try { pair.Name1 = Convert.ToString(ir.OccurrenceOne.Name); } catch { }
|
||||
try { pair.Name2 = Convert.ToString(ir.OccurrenceTwo.Name); } catch { }
|
||||
try { pair.VolumeCM3 = (double)ir.Volume; } catch { }
|
||||
asm.Interferences.Add(pair);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
asm.InterferenceState = 2;
|
||||
asm.InterferenceError = ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
private void CollectOccurrenceNames(dynamic occs, List<string> names)
|
||||
{
|
||||
try
|
||||
{
|
||||
int cnt = (int)occs.Count;
|
||||
for (int i = 1; i <= cnt; i++)
|
||||
{
|
||||
dynamic occ = occs[i];
|
||||
if (occ == null) continue;
|
||||
try { names.Add(Convert.ToString(occ.Name)); } catch { }
|
||||
try
|
||||
{
|
||||
dynamic sub = occ.SubOccurrences;
|
||||
if (sub != null) CollectOccurrenceNames(sub, names);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void ReadDrawingInfo(dynamic d, DocSnapshot snap)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic dd = d;
|
||||
int nSheets = (int)dd.Sheets.Count;
|
||||
for (int i = 1; i <= nSheets; i++)
|
||||
{
|
||||
SheetInfo sh = new SheetInfo();
|
||||
try
|
||||
{
|
||||
dynamic sheet = dd.Sheets[i];
|
||||
sh.Name = Convert.ToString(sheet.Name);
|
||||
try { sh.SheetWidth = (double)sheet.Width; } catch { }
|
||||
try { sh.SheetHeight = (double)sheet.Height; } catch { }
|
||||
|
||||
try
|
||||
{
|
||||
dynamic bd = sheet.Border;
|
||||
if (bd != null)
|
||||
{
|
||||
sh.HasBorder = true;
|
||||
try
|
||||
{
|
||||
dynamic box = bd.RangeBox;
|
||||
RectD r = new RectD();
|
||||
r.L = (double)box.MinPoint.X; r.T = (double)box.MinPoint.Y;
|
||||
r.R = (double)box.MaxPoint.X; r.B = (double)box.MaxPoint.Y;
|
||||
sh.BorderRect = r;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
dynamic tb = sheet.TitleBlock;
|
||||
if (tb != null)
|
||||
{
|
||||
sh.HasTitleBlock = true;
|
||||
try { sh.TitleBlockName = Convert.ToString(tb.Name); } catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
dynamic views = sheet.DrawingViews;
|
||||
sh.ViewCount = (int)views.Count;
|
||||
for (int j = 1; j <= sh.ViewCount; j++)
|
||||
{
|
||||
dynamic vw = views[j];
|
||||
try
|
||||
{
|
||||
if (!(bool)vw.IsUpdateComplete) sh.UpdateNeeded++;
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
if ((DrawingViewTypeEnum)vw.ViewType == DrawingViewTypeEnum.kSectionDrawingViewType)
|
||||
sh.SectionCount++;
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
dynamic pos = vw.Position;
|
||||
double w = (double)vw.Width, h = (double)vw.Height;
|
||||
RectD r = new RectD();
|
||||
r.L = (double)pos.X - w / 2; r.R = (double)pos.X + w / 2;
|
||||
r.T = (double)pos.Y - h / 2; r.B = (double)pos.Y + h / 2;
|
||||
sh.ViewRects.Add(r);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
dynamic dims = sheet.DrawingDimensions;
|
||||
sh.DimCount = (int)dims.Count;
|
||||
for (int j = 1; j <= sh.DimCount; j++)
|
||||
{
|
||||
dynamic dm = dims[j];
|
||||
try
|
||||
{
|
||||
if (dm.Tolerance.ToleranceType != ToleranceTypeEnum.kDefaultTolerance)
|
||||
sh.DimTolCount++;
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
if (Convert.ToString(dm.Text.Text).Contains("?")) sh.DimQuestionCount++;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try { sh.FcfCount = (int)sheet.FeatureControlFrames.Count; } catch { }
|
||||
try { sh.TexCount = (int)sheet.SurfaceTextureSymbols.Count; } catch { }
|
||||
try { sh.CenterlineCount = (int)sheet.Centerlines.Count; } catch { }
|
||||
try { sh.BalloonCount = (int)sheet.Balloons.Count; } catch { }
|
||||
|
||||
try
|
||||
{
|
||||
dynamic notes = sheet.DrawingNotes;
|
||||
int nn = (int)notes.Count;
|
||||
for (int j = 1; j <= nn; j++)
|
||||
{
|
||||
try { sh.NotesTexts.Add(Convert.ToString(notes[j].Text)); } catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
for (int j = 1; j <= sh.FcfCount; j++)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic ann = sheet.FeatureControlFrames[j];
|
||||
dynamic p1 = mApp.TransientGeometry.CreatePoint2d();
|
||||
dynamic p2 = mApp.TransientGeometry.CreatePoint2d();
|
||||
ann.GetBounds(p1, p2);
|
||||
RectD r = new RectD();
|
||||
r.L = (double)p1.X; r.T = (double)p1.Y; r.R = (double)p2.X; r.B = (double)p2.Y;
|
||||
sh.FcfRects.Add(r);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
for (int j = 1; j <= sh.TexCount; j++)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic ann = sheet.SurfaceTextureSymbols[j];
|
||||
dynamic p1 = mApp.TransientGeometry.CreatePoint2d();
|
||||
dynamic p2 = mApp.TransientGeometry.CreatePoint2d();
|
||||
ann.GetBounds(p1, p2);
|
||||
RectD r = new RectD();
|
||||
r.L = (double)p1.X; r.T = (double)p1.Y; r.R = (double)p2.X; r.B = (double)p2.Y;
|
||||
sh.TexRects.Add(r);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
snap.Sheets.Add(sh);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void ReadOpenDocs(DocSnapshot snap)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic docs = mApp.Documents;
|
||||
int n = (int)docs.Count;
|
||||
for (int i = 1; i <= n; i++)
|
||||
{
|
||||
dynamic dd = docs[i];
|
||||
if (dd == null) continue;
|
||||
try
|
||||
{
|
||||
DocumentTypeEnum t = (DocumentTypeEnum)dd.DocumentType;
|
||||
if (t != DocumentTypeEnum.kPartDocumentObject) continue;
|
||||
}
|
||||
catch { continue; }
|
||||
DocInfo info = new DocInfo();
|
||||
try { info.Name = Convert.ToString(dd.DisplayName); } catch { }
|
||||
info.Props = ReadProps(dd);
|
||||
info.Material = AppState.GetProp(info.Props, "Material", "材料", "材质");
|
||||
if (info.Material == "")
|
||||
{
|
||||
try { info.Material = Convert.ToString(dd.ComponentDefinition.Material.Name); } catch { }
|
||||
}
|
||||
try { info.TexCount = (int)dd.ComponentDefinition.ModelAnnotations.ModelSurfaceTextureSymbols.Count; } catch { }
|
||||
snap.OpenDocs.Add(info);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SolidWorks.Interop.sldworks;
|
||||
using DesignExpress.Core;
|
||||
|
||||
namespace DesignExpress.SolidWorksLink
|
||||
{
|
||||
// SolidWorks 适配器: 实现 ICadHost, 把 SW 文档状态拍成 Core 快照
|
||||
public class SolidWorksHost : ICadHost
|
||||
{
|
||||
private ISldWorks mSwApp;
|
||||
|
||||
public SolidWorksHost(ISldWorks swApp)
|
||||
{
|
||||
mSwApp = swApp;
|
||||
}
|
||||
|
||||
public string AppName { get { return "SolidWorks"; } }
|
||||
|
||||
public object GetActiveDocument()
|
||||
{
|
||||
try { return mSwApp.IActiveDoc2; } catch { return null; }
|
||||
}
|
||||
|
||||
public string GetDocType(object doc)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 注意: 不能用 dynamic 调 GetType()(会解析成 Object.GetType), 必须编译时调用
|
||||
ModelDoc2 m = doc as ModelDoc2;
|
||||
if (m != null)
|
||||
{
|
||||
int t = m.GetType();
|
||||
if (t == 1) return "Part"; // swDocPART
|
||||
if (t == 2) return "Assembly"; // swDocASSEMBLY
|
||||
if (t == 3) return "Drawing"; // swDocDRAWING
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return "";
|
||||
}
|
||||
|
||||
public void SetStatusText(string text)
|
||||
{
|
||||
try { ((dynamic)mSwApp).SetStatusBarText(text); } catch { }
|
||||
}
|
||||
|
||||
public double PickCylinderDiameterMM(out string faceName)
|
||||
{
|
||||
faceName = "手动输入";
|
||||
try
|
||||
{
|
||||
dynamic doc = mSwApp.IActiveDoc2;
|
||||
if (doc == null) return 0;
|
||||
dynamic selMgr = doc.ISelectionManager;
|
||||
if (selMgr == null) return 0;
|
||||
dynamic face = selMgr.GetSelectedObject6(1, -1);
|
||||
if (face == null) return 0;
|
||||
double[] origin = new double[3];
|
||||
double[] axis = new double[3];
|
||||
double radius = 0;
|
||||
face.IGetCylinderParams(origin, axis, out radius);
|
||||
if (radius > 0) return radius * 2 * 1000; // 米 -> 毫米
|
||||
}
|
||||
catch { }
|
||||
return 0;
|
||||
}
|
||||
|
||||
public DocSnapshot Capture(object doc)
|
||||
{
|
||||
DocSnapshot snap = new DocSnapshot();
|
||||
dynamic d = doc;
|
||||
snap.Kind = GetDocType(doc);
|
||||
try { snap.Dirty = (bool)d.GetSaveFlag(); } catch { }
|
||||
try { snap.DisplayName = Convert.ToString(d.GetTitle()); } catch { }
|
||||
try
|
||||
{
|
||||
string full = Convert.ToString(d.GetPathName());
|
||||
int p = full.LastIndexOf('\\');
|
||||
if (p > 0) snap.Folder = full.Substring(0, p + 1);
|
||||
}
|
||||
catch { }
|
||||
|
||||
snap.Props = ReadProps(d);
|
||||
snap.MaterialName = ReadMaterial(d);
|
||||
|
||||
if (snap.Kind == "Part" || snap.Kind == "Assembly")
|
||||
{
|
||||
snap.Model = ReadModelInfo(d);
|
||||
snap.Asm = new AssemblyInfo();
|
||||
}
|
||||
if (snap.Kind == "Assembly")
|
||||
{
|
||||
ReadAssemblyInfo(d, snap);
|
||||
}
|
||||
if (snap.Kind == "Drawing")
|
||||
{
|
||||
ReadDrawingInfo(d, snap);
|
||||
}
|
||||
ReadOpenDocs(snap);
|
||||
return snap;
|
||||
}
|
||||
|
||||
private Dictionary<string, string> ReadProps(dynamic d)
|
||||
{
|
||||
Dictionary<string, string> props = new Dictionary<string, string>();
|
||||
try
|
||||
{
|
||||
dynamic ext = d.Extension;
|
||||
dynamic cpm = ext.CustomPropertyManager("");
|
||||
if (cpm != null)
|
||||
{
|
||||
object names = cpm.GetNames();
|
||||
if (names is object[])
|
||||
{
|
||||
foreach (object n in (object[])names)
|
||||
{
|
||||
try
|
||||
{
|
||||
string name = Convert.ToString(n);
|
||||
string val = "", resolved = "";
|
||||
bool wasResolved = false, link = false;
|
||||
cpm.Get6(name, false, out val, out resolved, out wasResolved, out link);
|
||||
if (name != "" && !props.ContainsKey(name))
|
||||
props[name] = val ?? "";
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return props;
|
||||
}
|
||||
|
||||
private string ReadMaterial(dynamic d)
|
||||
{
|
||||
try
|
||||
{
|
||||
string mat = "";
|
||||
string config = "";
|
||||
try { config = Convert.ToString(d.ConfigurationManager.ActiveConfiguration.Name); } catch { }
|
||||
if (d.GetMaterialPropertyName2(config, out mat))
|
||||
return mat ?? "";
|
||||
}
|
||||
catch { }
|
||||
return "";
|
||||
}
|
||||
|
||||
private ModelInfo ReadModelInfo(dynamic d)
|
||||
{
|
||||
ModelInfo m = new ModelInfo();
|
||||
// 最小圆角(遍历特征中的 Fillet)
|
||||
try
|
||||
{
|
||||
dynamic fm = d.FeatureManager;
|
||||
dynamic feat = fm.GetFirstFeature();
|
||||
double minR = -1;
|
||||
bool found = false;
|
||||
while (feat != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
string tn = Convert.ToString(feat.GetTypeName2());
|
||||
if (tn == "Fillet")
|
||||
{
|
||||
dynamic fd = feat.GetDefinition();
|
||||
double r = (double)fd.Radius;
|
||||
if (r > 0)
|
||||
{
|
||||
if (!found || r < minR) minR = r;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
feat = feat.GetNextFeature();
|
||||
}
|
||||
m.MinFilletReadable = found;
|
||||
m.MinFilletRadiusMM = found ? minR * 1000 : -1;
|
||||
}
|
||||
catch { }
|
||||
return m;
|
||||
}
|
||||
|
||||
private void ReadAssemblyInfo(dynamic d, DocSnapshot snap)
|
||||
{
|
||||
AssemblyInfo asm = snap.Asm;
|
||||
try
|
||||
{
|
||||
dynamic comps = d.GetComponents(false);
|
||||
if (comps is object[])
|
||||
{
|
||||
asm.TopLevelCount = ((object[])comps).Length;
|
||||
CollectComponentNames(comps, asm.OccurrenceNames);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
try
|
||||
{
|
||||
object comps = d.GetComponents(false);
|
||||
object pComp = null, pFace = null;
|
||||
d.ToolsCheckInterference2(0, comps, true, out pComp, out pFace);
|
||||
if (pComp is object[])
|
||||
{
|
||||
int n = ((object[])pComp).Length;
|
||||
if (n > 0)
|
||||
{
|
||||
asm.InterferenceState = 1;
|
||||
for (int i = 0; i < n && i < 50; i++)
|
||||
{
|
||||
InterferencePair pair = new InterferencePair();
|
||||
try
|
||||
{
|
||||
dynamic c1 = ((object[])pComp)[i];
|
||||
dynamic c2 = null;
|
||||
if (pFace is object[] && i < ((object[])pFace).Length)
|
||||
c2 = ((object[])pFace)[i];
|
||||
try { pair.Name1 = Convert.ToString(c1.Name2); } catch { }
|
||||
try { pair.Name2 = Convert.ToString(c2.Name2); } catch { }
|
||||
asm.Interferences.Add(pair);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
asm.InterferenceState = 2;
|
||||
asm.InterferenceError = ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
private void CollectComponentNames(object comps, List<string> names)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (object c in (object[])comps)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic comp = c;
|
||||
names.Add(Convert.ToString(comp.Name2));
|
||||
object children = comp.GetChildren();
|
||||
if (children is object[] && ((object[])children).Length > 0)
|
||||
CollectComponentNames(children, names);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void ReadDrawingInfo(dynamic d, DocSnapshot snap)
|
||||
{
|
||||
try
|
||||
{
|
||||
object sheetNamesObj = d.GetSheetNames();
|
||||
string[] sheetNames = null;
|
||||
if (sheetNamesObj is string[]) sheetNames = (string[])sheetNamesObj;
|
||||
if (sheetNamesObj is object[]) sheetNames = Array.ConvertAll((object[])sheetNamesObj, o => Convert.ToString(o));
|
||||
if (sheetNames == null || sheetNames.Length == 0) return;
|
||||
foreach (string sn in sheetNames)
|
||||
{
|
||||
SheetInfo sh = new SheetInfo();
|
||||
sh.Name = sn;
|
||||
try
|
||||
{
|
||||
d.ActivateSheet(sn);
|
||||
dynamic views = d.GetViews();
|
||||
if (views is object[])
|
||||
{
|
||||
sh.ViewCount = ((object[])views).Length;
|
||||
foreach (object v in (object[])views)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic view = v;
|
||||
object notes = view.GetNotes();
|
||||
if (notes is object[])
|
||||
{
|
||||
foreach (object n in (object[])notes)
|
||||
{
|
||||
try { sh.NotesTexts.Add(Convert.ToString(((dynamic)n).GetText())); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
snap.Sheets.Add(sh);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void ReadOpenDocs(DocSnapshot snap)
|
||||
{
|
||||
try
|
||||
{
|
||||
object docs = mSwApp.GetDocuments();
|
||||
if (!(docs is object[])) return;
|
||||
foreach (object d in (object[])docs)
|
||||
{
|
||||
DocInfo info = new DocInfo();
|
||||
dynamic dd = d;
|
||||
try { info.Name = Convert.ToString(dd.GetTitle()); } catch { }
|
||||
try
|
||||
{
|
||||
int t = (int)dd.GetType();
|
||||
if (t != 1) continue;
|
||||
}
|
||||
catch { continue; }
|
||||
info.Props = ReadProps(dd);
|
||||
info.Material = AppState.GetProp(info.Props, "Material", "材料", "材质");
|
||||
if (info.Material == "") info.Material = ReadMaterial(dd);
|
||||
snap.OpenDocs.Add(info);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using SolidWorks.Interop.sldworks;
|
||||
using SolidWorks.Interop.swpublished;
|
||||
using DesignExpress.Core;
|
||||
|
||||
[assembly: ComVisible(true)]
|
||||
|
||||
namespace DesignExpress.SolidWorksLink
|
||||
{
|
||||
// SolidWorks 加载项外壳: 实现 ISwAddin, 延迟创建 CommandManager 选项卡, 回调全部转到 Core
|
||||
[Guid("4A7E023E-EDD8-4642-B337-425E02394C81")]
|
||||
[ComVisible(true)]
|
||||
[ClassInterface(ClassInterfaceType.AutoDual)]
|
||||
[ProgId("DesignExpress.SolidWorksLink.SwAddin")]
|
||||
public class SwAddin : ISwAddin
|
||||
{
|
||||
private const string AddinClsid = "{4A7E023E-EDD8-4642-B337-425E02394C81}";
|
||||
private const string Title = "Design Express Res";
|
||||
private const int GroupId = 23130;
|
||||
private ISldWorks mSwApp;
|
||||
private int mCookie;
|
||||
private DSldWorksEvents_Event mSwEvents;
|
||||
private ICommandGroup mCmdGroup;
|
||||
private int[] mCmdIndexes;
|
||||
private readonly object mTabLock = new object();
|
||||
|
||||
static SwAddin()
|
||||
{
|
||||
// COM 激活的程序集依赖按宿主进程目录探测, 手动解析同目录的 Core.dll
|
||||
AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
string name = new AssemblyName(args.Name).Name;
|
||||
if (name == "DesignExpress.Core")
|
||||
{
|
||||
string dir = Path.GetDirectoryName(typeof(SwAddin).Assembly.Location);
|
||||
string path = Path.Combine(dir, "DesignExpress.Core.dll");
|
||||
if (File.Exists(path)) return Assembly.LoadFrom(path);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
public bool ConnectToSW(object ThisSW, int cookie)
|
||||
{
|
||||
try
|
||||
{
|
||||
mSwApp = (ISldWorks)ThisSW;
|
||||
mCookie = cookie;
|
||||
AppState.Host = new SolidWorksHost(mSwApp);
|
||||
// 关键: SW 启动早期命令系统未就绪, 命令组/选项卡延迟到文档激活事件创建
|
||||
try
|
||||
{
|
||||
mSwEvents = (DSldWorksEvents_Event)mSwApp;
|
||||
mSwEvents.ActiveDocChangeNotify += OnActiveDocChange;
|
||||
}
|
||||
catch { }
|
||||
EnsureAll();
|
||||
return true;
|
||||
}
|
||||
catch { return false; }
|
||||
}
|
||||
|
||||
private int OnActiveDocChange()
|
||||
{
|
||||
EnsureAll();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void EnsureAll()
|
||||
{
|
||||
lock (mTabLock)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mCmdGroup == null)
|
||||
{
|
||||
SetupCommandGroup();
|
||||
Log("SetupCommandGroup: " + (mCmdGroup != null ? "OK" : "NULL"));
|
||||
}
|
||||
if (mCmdGroup != null)
|
||||
{
|
||||
// 每次文档激活都幂等确保选项卡存在(文档切换时 SW 可能清除 addin 选项卡)
|
||||
AddCommandManagerTabs();
|
||||
}
|
||||
MakeTabVisible();
|
||||
}
|
||||
catch (Exception ex) { Log("EnsureAll 异常: " + ex.Message); }
|
||||
}
|
||||
}
|
||||
|
||||
public bool DisconnectFromSW()
|
||||
{
|
||||
Log("DisconnectFromSW 被调用!");
|
||||
try
|
||||
{
|
||||
ICommandManager cmdMgr = mSwApp.GetCommandManager(mCookie);
|
||||
cmdMgr.RemoveCommandGroup2(GroupId, true);
|
||||
}
|
||||
catch { }
|
||||
return true;
|
||||
}
|
||||
|
||||
// 启用回调: 返回 1 = 命令始终可用
|
||||
public int EnableMethod() { return 1; }
|
||||
|
||||
// 创建命令组+命令项(菜单可用), 选项卡延迟创建
|
||||
private void SetupCommandGroup()
|
||||
{
|
||||
try
|
||||
{
|
||||
ICommandManager cmdMgr = mSwApp.GetCommandManager(mCookie);
|
||||
mSwApp.SetAddinCallbackInfo(0, this, mCookie);
|
||||
|
||||
string iconList = "";
|
||||
try { iconList = SwIcons.EnsureIcons(); } catch { }
|
||||
|
||||
ICommandGroup grp = cmdMgr.CreateCommandGroup(GroupId, Title, Title, "", -1);
|
||||
if (grp == null) return;
|
||||
|
||||
if (iconList != "")
|
||||
{
|
||||
try { grp.LargeIconList = iconList; } catch { }
|
||||
try { grp.SmallIconList = iconList; } catch { }
|
||||
}
|
||||
|
||||
int[] idx = new int[9];
|
||||
idx[0] = grp.AddCommandItem2("零件检查", -1, "对当前零件进行三维标注、公差配合、GMP 检查", "零件检查", 0, "PartCheck", "EnableMethod", 0, 1);
|
||||
idx[1] = grp.AddCommandItem2("装配检查", -1, "对当前装配进行 GMP、密封、干涉、外购件检查", "装配检查", 1, "AssemblyCheck", "EnableMethod", 1, 1);
|
||||
idx[2] = grp.AddCommandItem2("工程图检查", -1, "对当前工程图进行标注与 spec 技术要求检查", "工程图检查", 2, "DrawingCheck", "EnableMethod", 2, 1);
|
||||
idx[3] = grp.AddCommandItem2("导出报告", -1, "导出检查报告(Excel/CSV)", "导出报告", 3, "ExportReport", "EnableMethod", 3, 1);
|
||||
idx[4] = grp.AddCommandItem2("使用说明", -1, "查看检查项清单与使用说明", "使用说明", 4, "Help", "EnableMethod", 4, 1);
|
||||
idx[5] = grp.AddCommandItem2("卡簧槽查询", -1, "轴用/孔用弹性挡圈槽尺寸查询 (GB/T 894)", "卡簧槽查询", 5, "CirclipQuery", "EnableMethod", 5, 1);
|
||||
idx[6] = grp.AddCommandItem2("键槽查询", -1, "平键键槽尺寸查询 (GB/T 1095)", "键槽查询", 6, "KeywayQuery", "EnableMethod", 6, 1);
|
||||
idx[7] = grp.AddCommandItem2("O型密封圈查询", -1, "O 型密封圈设计与沟槽尺寸查询 (GB/T 3452.1)", "O型密封圈查询", 7, "OringQuery", "EnableMethod", 7, 1);
|
||||
idx[8] = grp.AddCommandItem2("轴承挡圈查询", -1, "轴承挡圈与挡边设计查询", "轴承挡圈查询", 8, "BearingRingQuery", "EnableMethod", 8, 1);
|
||||
|
||||
try { grp.HasToolbar = true; } catch { }
|
||||
try { grp.HasMenu = true; } catch { }
|
||||
grp.Activate();
|
||||
|
||||
mCmdGroup = grp;
|
||||
mCmdIndexes = idx;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// 文档激活后创建 CommandManager 选项卡(SW 命令系统就绪后)
|
||||
private void AddCommandManagerTabs()
|
||||
{
|
||||
try
|
||||
{
|
||||
ICommandManager cmdMgr = mSwApp.GetCommandManager(mCookie);
|
||||
foreach (int docType in new int[] { 1, 2, 3 })
|
||||
{
|
||||
try
|
||||
{
|
||||
ICommandTab cmdTab = cmdMgr.GetCommandTab(docType, Title);
|
||||
if (cmdTab == null)
|
||||
{
|
||||
cmdTab = cmdMgr.AddCommandTab(docType, Title);
|
||||
}
|
||||
if (cmdTab != null)
|
||||
{
|
||||
// 幂等: 已有命令则不重复添加, 避免按钮重复
|
||||
int boxCount = cmdTab.GetCommandTabBoxCount();
|
||||
bool hasCommands = false;
|
||||
if (boxCount > 0)
|
||||
{
|
||||
object boxes = cmdTab.CommandTabBoxes();
|
||||
if (boxes is object[])
|
||||
{
|
||||
foreach (object b in (object[])boxes)
|
||||
{
|
||||
try
|
||||
{
|
||||
dynamic box = b;
|
||||
object ids = null, tts = null;
|
||||
if (box.GetCommands(out ids, out tts) > 0) hasCommands = true;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasCommands)
|
||||
{
|
||||
Log("docType=" + docType + " 已有命令, 跳过");
|
||||
}
|
||||
else
|
||||
{
|
||||
ICommandTabBox cmdBox = cmdTab.AddCommandTabBox();
|
||||
int[] cmdIDs = new int[mCmdIndexes.Length];
|
||||
int[] textType = new int[mCmdIndexes.Length];
|
||||
for (int i = 0; i < mCmdIndexes.Length; i++)
|
||||
{
|
||||
cmdIDs[i] = mCmdGroup.CommandID[mCmdIndexes[i]];
|
||||
textType[i] = 2; // swCommandTabButton_TextBelow
|
||||
}
|
||||
cmdBox.AddCommands(cmdIDs, textType);
|
||||
Log("docType=" + docType + " AddCommands 9 个");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// 文档扩展: 设置选项卡可见并激活(仅运行时创建时可能需强制显示)
|
||||
private void MakeTabVisible()
|
||||
{
|
||||
try
|
||||
{
|
||||
ModelDoc2 doc = mSwApp.IActiveDoc2;
|
||||
if (doc == null) { Log("MakeTabVisible: 无文档"); return; }
|
||||
ModelDocExtension ext = doc.Extension;
|
||||
if (ext == null) return;
|
||||
object tabs = ext.GetCommandTabs();
|
||||
if (tabs is string[])
|
||||
{
|
||||
string[] names = (string[])tabs;
|
||||
Log("GetCommandTabs 共 " + names.Length + " 个");
|
||||
for (int i = 0; i < names.Length; i++)
|
||||
{
|
||||
Log(" Tab[" + i + "]=" + names[i]);
|
||||
if (names[i] == Title)
|
||||
{
|
||||
ext.set_CommandTabVisible(i, true);
|
||||
try
|
||||
{
|
||||
ICommandManager cmdMgr = mSwApp.GetCommandManager(mCookie);
|
||||
dynamic ourTab = cmdMgr.GetCommandTab(1, Title);
|
||||
if (ourTab != null) { ourTab.Active = true; Log("tab.Active=true"); }
|
||||
else { Log("GetCommandTab 返回 null"); }
|
||||
}
|
||||
catch (Exception ex) { Log("tab.Active 失败: " + ex.Message); }
|
||||
try { ext.ActiveCommandTab = Title; Log("ActiveCommandTab 已设"); } catch (Exception ex) { Log("ActiveCommandTab 失败: " + ex.Message); }
|
||||
return;
|
||||
}
|
||||
}
|
||||
Log("未找到 " + Title);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) { Log("MakeTabVisible 异常: " + ex.Message); }
|
||||
}
|
||||
|
||||
private static void Log(string msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.IO.File.AppendAllText(
|
||||
System.IO.Path.Combine(System.IO.Path.GetTempPath(), "DesignExpress_SW.log"),
|
||||
DateTime.Now.ToString("HH:mm:ss.fff") + " " + msg + System.Environment.NewLine);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// ============ 命令回调(公开方法, SW 通过 IDispatch 调用) ============
|
||||
|
||||
public void PartCheck() { Safe(Checks.PartCheck); }
|
||||
public void AssemblyCheck() { Safe(Checks.AssemblyCheck); }
|
||||
public void DrawingCheck() { Safe(Checks.DrawingCheck); }
|
||||
public void ExportReport() { Safe(Checks.ExportReport); }
|
||||
public void Help() { Safe(Checks.Help); }
|
||||
public void CirclipQuery() { Safe(Checks.CirclipQuery); }
|
||||
public void KeywayQuery() { Safe(Checks.KeywayQuery); }
|
||||
public void OringQuery() { Safe(Checks.OringQuery); }
|
||||
public void BearingRingQuery() { Safe(Checks.BearingRingQuery); }
|
||||
|
||||
private static void Safe(Action action)
|
||||
{
|
||||
try { action(); }
|
||||
catch (Exception ex) { System.Windows.Forms.MessageBox.Show("执行出错: " + ex.Message); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using DesignExpress.Core;
|
||||
|
||||
namespace DesignExpress.SolidWorksLink
|
||||
{
|
||||
// SolidWorks 命令图标条: 复用 Core.ToolIcons(仓鼠品牌+功能符号), 生成 9 格 BMP
|
||||
public static class SwIcons
|
||||
{
|
||||
public static string EnsureIcons()
|
||||
{
|
||||
try
|
||||
{
|
||||
string dir = Path.GetDirectoryName(typeof(SwIcons).Assembly.Location);
|
||||
string file = Path.Combine(dir, "DesignExpress_icons.bmp");
|
||||
if (File.Exists(file)) return file;
|
||||
ToolIcon[] icons = new ToolIcon[]
|
||||
{
|
||||
ToolIcon.Part, // 零件检查
|
||||
ToolIcon.Asm, // 装配检查
|
||||
ToolIcon.Drw, // 工程图检查
|
||||
ToolIcon.Export, // 导出报告
|
||||
ToolIcon.Help, // 使用说明
|
||||
ToolIcon.Circlip, // 卡簧槽查询
|
||||
ToolIcon.Keyway, // 键槽查询
|
||||
ToolIcon.Oring, // O型密封圈查询
|
||||
ToolIcon.Bearing // 轴承挡圈查询
|
||||
};
|
||||
return ToolIcons.CreateStripBmp(icons, 32, file);
|
||||
}
|
||||
catch { return ""; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
# Design Express Res — CAD 设计标注检查与设计数据查询工具
|
||||
|
||||
基于 **Core + Link 架构**(类似 COMSOL LiveLink):独立核心库与 CAD 完全解耦,Inventor / SolidWorks 各自通过 Link 适配层调用 Core 功能。
|
||||
|
||||
## 架构
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────┐
|
||||
│ DesignExpress.Core.dll (独立核心, 不依赖CAD) │
|
||||
│ - KB 知识库 (GB/T 275/1800/1801/894/1095) │
|
||||
│ - CheckEngine 检查引擎 (P/A/D 三阶段) │
|
||||
│ - DesignQuery 设计数据查询 (键槽/卡簧槽已实装)│
|
||||
│ - UI: MainForm/QueryForm/FitForm │
|
||||
│ - Report 报告 (Excel/CSV) │
|
||||
│ - ICadHost 抽象接口 + DocSnapshot 快照 │
|
||||
│ - ToolIcons 共享图标(仓鼠品牌+功能符号) │
|
||||
└────────────────────────────────────────────┘
|
||||
▲ ▲
|
||||
InventorLink SolidWorksLink
|
||||
(已交付) (已交付)
|
||||
```
|
||||
|
||||
- **ICadHost 接口**:`GetActiveDocument / GetDocType / Capture / PickCylinderDiameterMM / SetStatusText`
|
||||
- **DocSnapshot 快照**:Link 层把 CAD 文档状态拍成纯数据,Core 只处理快照
|
||||
- 新增 CAD 支持 = 实现一个 ICadHost + 该 CAD 的选项卡壳
|
||||
|
||||
## 功能
|
||||
|
||||
| 系统 | 内容 |
|
||||
|------|------|
|
||||
| 设计检查 | 零件(标注/公差配合GB/T 275/形位/粗糙度/螺纹/物料接触GMP/表面处理/强度指引)、装配(GMP材料/密封/清洁/静态干涉/外购件/电气西门子/动力)、工程图(图框/视图/尺寸公差/22项spec关键词检查) |
|
||||
| 设计数据查询 | 键槽(GB/T 1095)、卡簧槽(GB/T 894.1)已实装; O型密封圈(GB/T 3452.1)、轴承挡圈规划中 |
|
||||
|
||||
## 部署
|
||||
|
||||
### Inventor
|
||||
1. 复制 `AddIn/deploy` 文件夹到目标机器
|
||||
2. 右键 `install.ps1` → **使用 PowerShell 运行**(无需管理员)
|
||||
3. 重启 Inventor,功能区出现 **[Design Express Res]** 选项卡
|
||||
|
||||
### SolidWorks
|
||||
1. 复制 `AddIn/deploy` 文件夹
|
||||
2. 运行 `install_solidworks.ps1`(用户级注册)
|
||||
3. **首次需管理员执行两条 reg add**(脚本末尾有提示):
|
||||
- `HKLM\SOFTWARE\SolidWorks\AddIns\{4A7E023E-...}` 键(default=1, Title)
|
||||
4. 启动 SolidWorks → 工具→插件 勾选 Design Express Res
|
||||
5. 打开零件 → 出现选项卡 → **正常退出并重启一次**(持久化选项卡定义)
|
||||
|
||||
## 文件清单
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `AddIn/deploy/DesignExpress.Core.dll` | 独立核心(成品) |
|
||||
| `AddIn/deploy/DesignExpress.InventorLink.dll` | Inventor 适配层(成品) |
|
||||
| `AddIn/deploy/DesignExpress.SolidWorksLink.dll` | SolidWorks 适配层(成品) |
|
||||
| `AddIn/deploy/install.ps1` | Inventor 一键部署脚本 |
|
||||
| `AddIn/deploy/install_solidworks.ps1` | SolidWorks 部署脚本 |
|
||||
| `AddIn/src/Core/*.cs` | 核心源码(ICadHost/Snapshots/KB/CheckEngine/DesignQuery/UI/ToolIcons) |
|
||||
| `AddIn/src/InventorLink/*.cs` | Inventor 适配源码 |
|
||||
| `AddIn/src/SolidWorksLink/*.cs` | SolidWorks 适配源码 |
|
||||
|
||||
## 关键技术点
|
||||
|
||||
### Inventor
|
||||
- **按钮点击**:`ButtonDefinition.OnExecute` 事件(不依赖 ExecuteCommand 路由)
|
||||
- **加载规则**:`AddInLoadRules` 二进制文件控制加载,install.ps1 自动修复(DWORD=0 允许加载)
|
||||
|
||||
### SolidWorks
|
||||
- **延迟创建**:命令组/选项卡在**文档激活事件**(`ActiveDocChangeNotify`)中创建——SW 启动早期命令系统未就绪,ConnectToSW 时创建会静默失败
|
||||
- **EnableMethod 回调**:命令必须提供启用方法(返回 1),否则 SW 禁用命令导致按钮不可见
|
||||
- **tab.Active = true**:选项卡可见性 + 激活必须直接设置,否则不显示在选项卡栏
|
||||
- **持久化**:SW 正常退出时把选项卡定义写入注册表,重启后读取显示
|
||||
- **GetDocType 注意**:不能 `dynamic.GetType()`(解析成 Object.GetType),必须编译时调用
|
||||
|
||||
### 通用
|
||||
- **窗口**:1/4 屏幕面积,TableLayoutPanel 百分比布局,无固定尺寸不遮罩
|
||||
- **报告**:Excel COM 动态调用,未装 Excel 回退 CSV
|
||||
- **图标**:ToolIcons 共享生成(功能符号集中式),SolidWorks 用 9 格 BMP 图标条;Inventor 因 AddButtonDefinition 对 IPictureDisp 兼容性问题暂用文字按钮(可后续手动补图标)
|
||||
|
||||
## 建议的 iProperties 自定义属性
|
||||
|
||||
| 属性名 | 取值示例 | 用途 |
|
||||
|--------|----------|------|
|
||||
| 物料接触 | 直接接触 / 间接接触 / 非接触 | 触发 GMP 专项检查 |
|
||||
| 表面处理 | 镀镍+磨削 / 抛光 / 发黑 | 表面处理检查 |
|
||||
| 材料 | 316L / 304 / PTFE | GMP 材料判定 |
|
||||
|
||||
## 编译
|
||||
|
||||
```powershell
|
||||
# Core (无 CAD 依赖)
|
||||
csc /target:library /platform:x64 /codepage:65001 /out:DesignExpress.Core.dll ^
|
||||
/r:System.Windows.Forms.dll /r:System.Drawing.dll /r:Microsoft.CSharp.dll /r:System.Core.dll ^
|
||||
src\Core\*.cs
|
||||
|
||||
# Inventor Link
|
||||
csc /target:library /platform:x64 /codepage:65001 /out:DesignExpress.InventorLink.dll ^
|
||||
/r:DesignExpress.Core.dll /r:"<Inventor>\Bin\Public Assemblies\Autodesk.Inventor.Interop.dll" ^
|
||||
/r:System.Windows.Forms.dll /r:System.Drawing.dll /r:Microsoft.CSharp.dll /r:System.Core.dll ^
|
||||
src\InventorLink\*.cs
|
||||
|
||||
# SolidWorks Link
|
||||
csc /target:library /platform:x64 /codepage:65001 /out:DesignExpress.SolidWorksLink.dll ^
|
||||
/r:DesignExpress.Core.dll /r:"<SW>\SolidWorks.Interop.sldworks.dll" ^
|
||||
/r:"<SW>\SolidWorks.Interop.swpublished.dll" /r:"<SW>\SolidWorks.Interop.swconst.dll" ^
|
||||
/r:System.Windows.Forms.dll /r:System.Drawing.dll /r:Microsoft.CSharp.dll /r:System.Core.dll ^
|
||||
src\SolidWorksLink\*.cs
|
||||
```
|
||||
|
||||
## 版本历史
|
||||
|
||||
- **1.3.0** (2026-08-21): SolidWorks Link 交付; 功能图标(集中式功能符号); 生产版代码清理
|
||||
- **1.3.1** (2026-08-22): 清理调试代码与临时文件; Inventor 图标方案(IPictureDisp)因 API 兼容性暂缓, 保留文字按钮
|
||||
Reference in New Issue
Block a user