
简介CadSoftTools CAD VCL v10.2 Enterprise for Delphi 10-12 Athens Full Source 是一套面向 Delphi 开发者的专业 CAD 控件集适用于需要在 Windows 应用中嵌入 DXF、DWG 等工程图形查看、编辑与转换功能的场景尤其适合中高级开发者构建 CAD 查看器或编辑器。压缩包共 541 个文件约 16MB以 199 个 pas 源码、174 个 dcu 编译单元、24 个 dfm 窗体、13 个 dproj 工程文件及 12 个 dpr 项目文件为主另含 shx 字体、dwg/dxf 示例图纸、chm 帮助文档与 exe 演示程序覆盖从源码到示例的完整结构。资源支持 Delphi 10 至 12 全版本并附带完整源代码开发者可查看、修改并定制底层实现灵活适配复杂图形处理与渲染需求。目前已有 98 人学习下载适合希望深入掌握 CAD 集成方案的 Delphi 开发者参考。1. Delphi 12.3 里把 CAD VCL v10.2 Enterprise 源码包跑起来先搞清楚它到底解决什么问题如果你正在用 Delphi 12.3 Athens 做工程类桌面软件迟早会撞上一个需求在窗体里显示 DWG/DXF 图纸还要能缩放、平移、图层开关、打印。自己从零写一个 DWG 解析器基本不现实DWG 是闭源二进制格式版本从 R12 到 2018 差异巨大光实体类型就有几十种。CadSoftTools 的 CAD VCL v10.2 Enterprise 就是干这个的它是一套原生 VCL 控件直接嵌进 Delphi 的 TForm 里不依赖 AutoCAD不依赖 ODA 的运行时授权加载 DWG/DXF/HPGL/PDF 等格式后给你一个可交互的绘图区。标题里的 “Full Source” 意味着拿到的是完整源码不是只有 DCU 的试用版这对需要改渲染逻辑、加自定义实体、做国产化适配的团队来说差别很大。这篇笔记按“先跑通最小加载 → 再拆参数和源码结构 → 最后讲避坑和进阶”的顺序走适合已经会用 Delphi 12.3 建 VCL 项目、但第一次接触 CAD 控件的工程师。2. 从零跑通第一个 DWG 加载环境、包安装与最小可运行代码2.1 Delphi 12.3 Athens 下的包结构长什么样拿到 “CAD VCL v10.2 Enterprise for Delphi 10-12 Athens Full Source.7z” 之后先别急着打开 .dproj。解压出来通常能看到几个关键目录Source放的是全部 .pas 源码Packages下按 Delphi 版本分目录Delphi 10 到 12 各有一套 .dpk/.dprojDemos里是示例工程Help是 CHM 或 PDF 文档。Enterprise 版比 Standard 多出来的部分主要在PDF 导入导出、DWG 写回、图层和块的高级操作、以及一些三维视角相关的单元。判断你拿到的是不是完整 Enterprise 源码看Source里有没有CADImage.pas、DWGImage.pas、PDFImage.pas这几个大文件以及Packages下对应 Athens 的包是否齐全。安装顺序上我一般先在 Delphi 12.3 里打开Packages下对应版本的运行时包通常叫CADVCLR.dproj之类Build 一次再 Install 设计时包。设计时包装完工具面板上会出现TCADImage、TCADViewer这类控件。如果 Build 报找不到单元八成是Source路径没加到 Library Path 里去Tools Options Language Delphi Library把Source和Source\Utils之类的子目录都加进去。提示Delphi 12.3 的编译器对inline和泛型比 10.x 严格老版本源码里如果有inline函数跨单元调用可能报 “cannot inline”。遇到就在项目选项里把优化临时关掉或者直接改源码去掉 inline 修饰。2.2 最小加载代码一个按钮加一个 TCADImage下面这段是我用来验证包是否装好的最小工程。窗体上放一个TButton、一个TOpenDialog、一个TCADImage按钮点击时加载选中的 DWG。procedure TForm1.btnLoadClick(Sender: TObject); begin if OpenDialog1.Execute then begin // 先清空避免上一次的图层和实体残留 CADImage1.Clear; // LoadFromFile 会根据扩展名自动选解析器 CADImage1.LoadFromFile(OpenDialog1.FileName); // 让图纸自适应窗体大小 CADImage1.FitToRect(CADImage1.ClientRect); // 强制重绘否则有时要拖动窗口才刷新 CADImage1.Repaint; end; end;逻辑说明Clear不是可有可无的CAD VCL 内部维护了图层表、块表、线型表连续加载两张图如果不 Clear第二张图可能继承第一张的图层状态出现“图层莫名其妙多出来”的玄学问题。LoadFromFile是入口它内部按文件头判断格式DWG 走DWGImageDXF 走DXFImage。FitToRect传入的是绘图区客户区矩形它会算一个缩放比让整张图可见。Repaint在部分显卡驱动下必须显式调否则首帧是黑的。参数上CADImage1.LoadFromFile有个重载可以传TLoadFromFileParams里面能指定是否加载线宽、是否解析布局空间。默认全加载大图会慢。如果你只做预览把线宽和填充关掉能快不少。2.3 验证加载成功的三个检查点跑起来之后别只看“图出来了没有”按这三个点确认第一看CADImage1.Layouts.Count正常 DWG 至少有 Model 布局图纸空间可能还有多个 Layout。如果 Count 是 0说明解析器没识别成功多半是文件版本太新或加密。第二看CADImage1.Layers.Count图层数量应该和你在 AutoCAD 里看到的一致。如果少了很多检查是不是加载参数里把冻结图层过滤掉了。第三随便取一个实体比如CADImage1.Entities[0].EntType看返回的类型是不是etLine、etCircle这类。如果全是etUnknown说明实体解析没走通通常是源码里某个条件编译开关没打开。3. 拆开源码看渲染管线TCADImage 的绘制流程与关键参数3.1 从 OnDraw 到 GDI 的调用链CAD VCL 的渲染不是一次性把图转成位图而是每次重绘时遍历可见实体逐个调 GDI/GDI 画。核心在CADImage.pas里的Draw方法它大致做这几件事先算当前视图变换矩阵缩放、平移再按图层可见性和实体包围盒做粗剔除然后对每个实体调DrawEntity最后画栅格、坐标轴这些辅助元素。Enterprise 版在DrawEntity里对样条曲线和椭圆弧做了细分缓存所以缩放时不会每次都重新算。理解这条链的意义在于你要改渲染性能改的是剔除逻辑和缓存策略不是去改 GDI 调用。比如大图卡顿先看Entities数量再看是不是所有实体都在视口内。我见过一个项目图纸有 8 万个实体每次重绘全遍历后来在Draw里加了一层按图层先过滤帧率从 3 帧涨到 30 帧。3.2 必调的五个参数缩放、平移、背景、线宽、抗锯齿CAD VCL 的参数分散在CADImage和CADViewer上下面这张表是我实际项目里最常动的五个。参数所在属性典型值作用与坑缩放比CADImage.Scale0.01 ~ 100直接改会以原点为中心要配合Offset才不跑偏平移量CADImage.Offset视口中心单位是像素不是图纸单位缩放后要重算背景色CADImage.BackgroundColorclWhite / clBlack改完必须 Repaint否则部分驱动不刷新线宽模式CADImage.LineWeightModelwmPixel / lwmReal用 Real 时细线在低缩放下会消失抗锯齿CADImage.AntialiasingTrue开了之后小图清晰大图明显掉帧缩放和平移是新手最容易翻车的地方。Scale改的是图纸单位到屏幕像素的比例Offset是图纸原点在屏幕上的位置。如果你只改 Scale 不改 Offset图会以左上角为锚点缩放看起来就是“越缩越往右下跑”。正确做法是先把鼠标位置转成图纸坐标改完 Scale 再反算 Offset让鼠标下的点不动。这个逻辑在Demos里的 Zoom 示例有可以直接抄。3.3 图层与实体过滤怎么只画我关心的部分工程图往往有几十个图层全部渲染既慢又乱。CAD VCL 给每个图层一个Visible属性但直接遍历改 Visible 会触发多次重绘。更好的做法是用CADImage.OnEntityDraw事件在里面判断实体所属图层不满足条件就把Draw参数设成 False。procedure TForm1.CADImage1EntityDraw(Sender: TObject; AEntity: TCADEntity; var ADraw: Boolean); begin // 只画图层名以 WALL 开头的实体 if Pos(WALL, UpperCase(AEntity.Layer.Name)) 0 then ADraw : False; end;逻辑说明这个事件每个实体绘制前都会调ADraw默认 True设 False 就跳过。参数AEntity.Layer.Name是图层名字符串注意大小写DWG 里图层名可能混用。性能上这个回调比改 Visible 快因为它不触发图层状态变更和重绘排队。注意在OnEntityDraw里不要做耗时操作比如查数据库、读文件。这个回调调用频率极高一次慢操作就能让整个界面卡死。4. 避坑与排查源码编译、字体、大图、打印里的五个血泪经验4.1 编译报 “Unit not found” 或 “Duplicate identifier”现象Build 时提示找不到CADImage或某个dx开头的单元或者提示标识符重复。原因Library Path 里同时存在多个版本的 CAD VCL 源码路径或者旧版 DCU 没清干净。Delphi 12.3 的搜索顺序是先 DCU 后源码如果之前装过试用版DCU 会优先命中。解决去Tools Options Library把无关路径删掉只留当前版本的Source。然后手动删掉项目目录下的Win32\Debug和Win64\Debug强制全量重编。如果还报重复搜一下Source里是不是有两个同名 .pasEnterprise 包有时会把 Standard 的单元也带进来。4.2 中文图层名和文字显示成问号现象图纸里中文图层名、中文标注文字显示为 “???” 或方块。原因CAD VCL 默认用 ANSI 编码读 DWG 里的字符串而中文 DWG 常用 GBK 或 UTF-16。源码里CADImage有个CodePage属性默认可能是 1252。解决加载前设CADImage1.CodePage : 936;GBK。如果图纸是 AutoCAD 2007 以上存的可能是 UTF-8试 65001。文字样式里的字体也要设CADImage1.TextStyle.FontName : SimSun;否则即使编码对了字体缺失还是方块。4.3 大图加载后内存暴涨、切换图纸崩溃现象加载一张 20MB 的 DWG任务管理器里内存从 200MB 跳到 1.5GB再加载第二张直接 Out of Memory。原因CAD VCL 会把所有实体、图层、块定义都缓存在内存而且默认不释放上一次的。Clear只清实体列表块表和线型表可能还挂着。解决加载新图前除了Clear再调CADImage1.Blocks.Clear和CADImage1.LineTypes.Clear。如果还不行把CADImage控件动态创建和释放不要复用同一个实例。另外LoadFromFile的参数里把lpLoadImages设 False不加载光栅底图能省一大块。4.4 打印和导出 PDF 时线宽全变成 1 像素现象屏幕上看着正常一打印或导出 PDF所有线都一样粗细线看不见。原因打印走的是另一套渲染路径LineWeightMode在打印时被强制成 Pixel而打印 DPI 远高于屏幕1 像素在纸上几乎不可见。解决打印前把CADImage1.LineWeightMode : lwmReal;并且设CADImage1.PrintScale为实际比例。如果导出 PDF用 Enterprise 版的PDFImage单元它支持矢量线宽。注意lwmReal在屏幕上会让细线太细所以我的习惯是屏幕用 Pixel打印前临时切 Real打完切回来。4.5 在 Delphi 12.3 的 FMX 项目里直接用 VCL 控件现象新建的是 FireMonkey 项目把TCADImage拖上去编译报错或者运行时窗体空白。原因CAD VCL 是纯 VCL 控件依赖Windows单元的 GDIFMX 的渲染层是 Direct2D 或 OpenGL两者不兼容。解决如果必须用 FMX常见做法是建一个 VCL 窗体嵌进去或者用TWindowsMedia之类的桥接。更省事的做法是 CAD 显示部分单独做一个 VCL 程序通过进程间通信把图渲染成位图传给 FMX。我一般直接建议客户用 VCL 做工程图模块FMX 做移动端或大屏展示别硬混。5. 进阶用源码改出自定义实体和批量出图的小技巧5.1 继承 TCADEntity 加一个自定义标注实体Full Source 最大的价值就是能加自己的实体。假设你要在图纸上画一种带二维码的标注AutoCAD 里没有对应类型可以继承TCADEntity重写Draw和GetBounds。type TQRCodeLabel class(TCADEntity) private FText: string; FPosition: TPoint2D; public procedure Draw(ACanvas: TCanvas; const ATransform: TTransform); override; function GetBounds: TRect2D; override; property Text: string read FText write FText; property Position: TPoint2D read FPosition write FPosition; end; procedure TQRCodeLabel.Draw(ACanvas: TCanvas; const ATransform: TTransform); var P: TPoint; begin // 把图纸坐标转成屏幕坐标 P : ATransform.PointToScreen(FPosition); // 这里用第三方二维码库画或者简单画个矩形占位 ACanvas.Rectangle(P.X, P.Y, P.X 40, P.Y 40); ACanvas.TextOut(P.X 2, P.Y 2, FText); end;逻辑说明Draw里拿到的ACanvas是当前渲染画布ATransform是视图变换必须用它转坐标不能自己算否则缩放平移后位置全错。GetBounds返回实体在图纸坐标系里的包围盒用于剔除和选择。加完实体后把它Add到CADImage1.Entities里重绘就能看到。参数上TTransform有PointToScreen和ScreenToPoint两个方向鼠标交互时用后者。自定义实体的EntType可以返回一个自定义枚举值但注意别和内置的冲突建议从 1000 开始。5.2 批量出图遍历布局导出 PDF 的脚本工程交付经常要把一张 DWG 里的多个布局批量导成 PDF。用 Enterprise 版的PDFImage可以写个循环。var i: Integer; PDF: TPDFImage; begin PDF : TPDFImage.Create(nil); try for i : 0 to CADImage1.Layouts.Count - 1 do begin CADImage1.CurrentLayout : CADImage1.Layouts[i]; // 每次切换布局后要重新适配 CADImage1.FitToRect(CADImage1.ClientRect); PDF.Assign(CADImage1); PDF.SaveToFile(D:\out\ CADImage1.Layouts[i].Name .pdf); end; finally PDF.Free; end; end;逻辑说明CurrentLayout切换后CADImage内部会重新解析该布局的视口和实体所以必须再FitToRect一次。PDF.Assign把当前渲染结果拷过去SaveToFile输出。参数上PDF的分辨率由CADImage的PrintScale决定想要 300 DPI 就设PrintScale : 300 / 96。提示批量导出时如果布局里有外部参照XRef确保 XRef 文件路径可访问否则导出的 PDF 里 XRef 部分是空白。CAD VCL 不会自动搜索路径需要你提前把 XRef 加载到CADImage1.Images里。5.3 验证自定义改动是否生效的两个土办法改完源码最怕“改了没生效”。我的习惯是第一在改动的Draw里加一句OutputDebugString(QRCodeLabel.Draw called);用 DebugView 看有没有输出。第二故意把颜色改成红色如果图上出现红色块说明渲染路径走通了。这两个办法比断点快尤其在有大量重绘的场合断点会卡到怀疑人生。最后说个习惯每次升级 Delphi 版本或 CAD VCL 版本先把Demos里的例子全跑一遍再跑自己的工程。源码包里的 Demo 是作者验证过的基线你的工程跑不通而 Demo 能跑问题一定在你的代码或路径配置上。这个顺序能省掉大量“到底是控件坏了还是我写错了”的纠结。希望帮到你。本文还有配套的精品资源点击获取