简介:这是一份面向 CAD 用户的 SHX 字体合集,核心解决 AutoCAD 打开 DWG 图纸时提示缺少 SHX 字体、文字显示为问号或乱码的问题。包内既有通用西文字体,也有中文大字体,覆盖建筑、机械、地形图等专业图纸的常见标注需求,设计师、工程师和制图学习者均可直接选用。压缩包共 357 个文件,以 351 个 shx 字体文件为主体,同时包含 rsc 资源文件、pfb 字体文件、txt 说明及 sys/xml 等辅助文件,可兼容多版本 CAD 环境的字体安装、替换与标注样式修复;整包约 80.8MB,解压即可使用。已有 4843 人学习下载。这套字体库按常用字体名整理,许多不同来源的同名字体一并收录,便于遇到缺字报错时快速查找替换;可直接放入 CAD 的 Fonts 目录完成字体环境配置,与单纯单个字体下载相比,一次拿到完整字库,更适合图纸协作、设计院出图或旧图归档时统一字体环境。
1. 收到的 dwg 满屏问号,先别骂发图的人:shx 字体缺失才是元凶
上周某协作单位发来一版平面图,我打开后图上所有标注都变成了问号方块。第一反应是“对方用的字体太冷门”,查了样式表发现根本不是字库问题——图纸里引用的两个 shx 字体文件,我这边根本没安装。dwg 图纸保存的是字体文件名,不是字体本身,所以对面能正常显示的 shx,到你电脑上就成了黑匣子。下面把这件事拆开讲清楚:shx 字体的加载机制、怎么快速定位缺失项、用什么方式批量替换,以及替换路上的几个常见踩坑点。这个过程不需要任何高级工具,普通 CAD 环境就能完成。
2. 先弄懂 shx 字体再动手:加载机制、大字体与 TTF 的取舍
2.1 文字样式是中间层:dwg 为什么不直接存字体
dwg 里的每个文字对象,存储的并不是“宋体”或“txt.shx”这样的具体字体名,而是文字样式的名称。真正定义字体的是“文字样式”表:样式名、字体文件名、大字体文件名、字高、宽度因子、倾斜角等参数都在这张表里。图形里的文字对象只是引用样式名,这一层间接关系让图纸体积小、换字体方便,但也带来了麻烦——打开图纸时,CAD 必须根据样式表里的字体文件名去本机查找对应文件,查不到就显示替代字体或者问号。
常见做法是把文字样式当成一个“指针”,它指向本机的某个字体文件。同一个 shx 文件在不同电脑上是否存在、是否同名,直接影响显示结果。这也是为什么同一张 dwg,在 A 电脑打开全正常,到 B 电脑就满屏问号。理解这一层,你后续排查就不会去删文字对象,而是去改样式表。
2.2 字体搜索路径:CAD 默认去哪里找 shx
字体文件不是随便放个目录就能被识别,CAD 只在特定范围内查找。打开软件的选项设置(命令OPTIONS),切到“文件”选项卡,“支持文件搜索路径”里列了一串目录,字体查找就是按这些目录的顺序进行的。默认情况下包含 CAD 的安装目录、用户目录、以及当前图纸所在目录。你可以把常用 shx 字体集中放到其中一个目录,或者把自定义字库目录加进搜索路径。
搜索顺序对故障排查有实际影响:如果搜索路径里同时存在同名但内容不同的两个 shx,CAD 会使用排在前面的那个,导致同一张图在不同电脑上显示效果不一致。我的习惯是只保留一份字库,并放到搜索路径最前面。查找是否被识别,可以用(findfile "hztxt.shx")在 CAD 命令行直接测试,返回路径说明能找到,返回 nil 说明找不到。这一步是后面所有排查的基础。
2.3 小字体与大字体:中文注释碎成问号的核心原因
shx 字体分两种:普通小字体和大字体(Big Font)。小字体负责英文、数字、符号,大字体负责中文等多字节文字。一个完整的文字样式会同时指定一个小字体和一个大字体,缺了任何一个,对应部分的文字就会断。很多图纸的中文注释用的是 hztxt.shx、gbcbig.shx 这类大字体,如果替换时只把 hztxt.shx 对应的文字样式改成了西文字体,中文部分就会变成“?”或者空白。
为什么 CAD 要把中英文拆成两个文件?因为 shx 是单字节编码的形定义文件,一个 shx 文件最多只能表达 256 个字符,中文显然不够用,所以用大字体扩展字符集。这意味着检查字体时不能只看“字体名”那一栏,还要看“大字体”那一栏。判断一个文字样式是否完整,必须同时确认两个文件都存在,从没接触过这套机制的人通常只补了小字体就以为处理完了,结果中文照样乱码。
2.4 SHX 与 TTF 的取舍:稳定、快,但别迷信
有人一遇到乱码就直接把文字样式改成系统 TTF 字体,比如宋体、黑体。这条路很快,但会引入新问题:TTF 字体在不同操作系统上版本不同(比如微软雅黑在 Win7 和 Win10 上字形并不完全一致),图纸换机器后带圈数字、特殊符号的显示可能悄悄变化。另外 TTF 渲染慢,图纸里大量的 TTF 文字会导致缩放、平移掉帧,大图纸尤其明显。
我一般这么区分:标注类文字(尺寸、引注)继续用 shx 字体,图纸说明、标题栏这类“需要排版观感”的文字才用 TTF。shx 的优点是快、稳定、占用小,缺点是所见不完全所得——很多 shx 不包含真正的显示字形,打印时按向量输出,屏幕上看和纸面上看有差别。TTF 所见即所得,但代价是性能和跨机器一致性。对“接收外部图纸并统一显示”这个场景,优先保证 shx 完整,是性价比最高的做法。
3. 定位缺失字体:三种方式找出图纸到底缺了哪些 shx
3.1 启动提示与“指定字体给样式”弹窗:最直接的定位信号
打开 dwg 后,如果 CAD 弹窗提示“未找到字体 xxx.shx”,这就是第一手信息。这个弹窗里往往让用户给缺失字体指定替代字体,很多人的做法是随手选一个,但这只是解决了“此时打开”的显示问题,并没有真正修复图纸。弹窗列出的是 CAD 在加载时找不到的字体,记下来是第一优先级。
这里有个细节:弹窗出现时你选定的替代字体会被 CAD 记住,下次打开同一文件可能不再提示,而是直接使用替代字体打开。这会让后续排查误以为“字体没问题了”。我收到外部图纸时,如果看到这个弹窗,会先截个图,再决定临时替代还是修样式。临时替代适合只浏览不改图;如果要在图上做标注、修改或打印交付,必须回到文字样式里彻底改掉。
3.2 用 STYLE 命令逐项盘查:样式表里藏着的缺字信息
命令行输入STYLE打开文字样式对话框,里面列出当前图纸所有的文字样式。逐个选中,看右侧的字体名和大字体名。对照本机实际存在的字体文件,哪些抛锚一目了然。这个过程慢,但可靠,样式少的图几分钟能查完。
如果想更快,可以用LIST命令查具体文字对象:选中一个出错文字后执行 LIST,输出的信息里会带“样式名”,再用 STYLE 查那个样式即可。这种“从文字到样式”的反向定位方式适合大图纸里只有局部文字出错的情况。要注意多行文字(MTEXT)本身可以带字符格式,允许在局部覆盖字体,所以即便文字样式正确,某几行文字仍可能是另一种字体,这属于图层级的地雷,后面避坑章会专门提到。
3.3 导出 DXF 后用 Python 批量解析字体依赖
图纸多或样式杂时,手工盘查不现实。我常用的另一种做法是:先执行DXFOUT导出一份 ASCII 格式的 DXF 文件,再用 Python 脚本解析样式表。DXF 的 STYLE 表结构稳定,组码 3 是小字体文件名,组码 4 是大字体文件名。下面这段脚本会打印出所有文字样式及其引用的字体文件。
def parse_dxf_styles(path): with open(path, errors="ignore") as fp: lines = [line.strip() for line in fp] styles = [] cur = None # DXF 是“组码 + 值”交替排列的文本,按两行一组读取 for code, val in zip(lines[0::2], lines[1::2]): if code == "0": if cur is not None and ("3" in cur or "4" in cur): styles.append(cur) # 遇到 STYLE 实体才创建新记录,其余实体忽略 cur = {} if val == "STYLE" else None elif cur is not None: cur[code] = val return styles for style in parse_dxf_styles("drawing.dxf"): name = style.get("2", "") font = style.get("3", "") bigfont = style.get("4", "") print(f"{name}: {font} 大字体={bigfont}")这段脚本的逻辑是让 DXF 文件按组码对逐行扫描,遇到组码 0 且值为 STYLE 时开启一条样式记录,直到下一条实体结束。注意 DXF 是文本格式,导出的文件如果包含中文字符,要确保编码处理正确,脚本里errors="ignore"只是兜底,真出现乱码建议用文本编辑器确认原始编码。这个脚本的价值在于:可以批量对比本机字体目录,找出缺失项,而不用一张张图打开看。缺点是 DXF 文件可能比 dwg 大很多,导出的等待时间要有心理准备。
4. 替换与恢复:字体映射表、LISP 批量改样式与兜底
4.1 临时替换:在字体弹窗里指定替代字体
打开图纸时弹出的字体替换对话框,本质是“这个 Session 内用某字体替代缺失字体”,仅仅影响当前打开状态,不写入图纸。这种临时替换适合快速看图,不适合出图或存档。如果你发现图里绝大多数文字是正常的,只有极少数样式缺失,临时替换能最快消除问号,但需要留意替代字体的编码是否覆盖原字体的字符范围。比如原来的大字体是 gbcbig.shx(含中文、钢筋符号),你临时替代成西文字体,中文会变乱码。
临时替换的记忆行为有玄学成分:同一个文件,在 A 电脑选过的替代方案,到 B 电脑不会生效;在同一台电脑上,不同 CAD 版本之间也不通用。它只是一个“打开时间内的补丁”,我基本上只用于紧急看图。要稳定,还是得改图纸里的样式定义,或者用下面的全局映射。
4.2 acad.fmp 字体映射表:缺失字体的兜底规则
CAD 有一个字体映射文件,通常叫 acad.fmp,位于安装目录的支持文件目录下。这个文件的作用是定义“缺失字体 → 替代字体”的映射规则,只要规则里写了的字体缺失,CAD 打开图纸时会直接使用替代字体,不再弹窗。格式很简单,每行一条,左边是缺失字体名,右边是替代字体名,用分号隔开。
hztxt.shx;gbcbig.shx hzfs.shx;gbcbig.shx txt.shx;simplex.shx这里第二列可以是 shx 也可以是 ttf,比如hztxt.shx;simsun.ttf也能工作。改完文件后重启 CAD 生效。这个表的优势是全局生效,对“接收外部图纸统一显示”特别有用——同一套映射规则推给团队所有人,大家打开同一张图看到的效果就一致。要注意的是映射表只对“找不到原字体”的情况生效,如果原字体存在但不合适(比如字形太丑),fmp 管不了,得改样式。
修改 acad.fmp 前建议先备份一份,因为有些版本会把用户自己加的规则和默认规则混在一起,装插件时可能被覆盖。我习惯在文件末尾统一加自定义规则,并写注释,这样升级或重装后能快速恢复。另一个容易漏的点:fmp 只会把缺失字体替换成目标字体,但“大字体缺失”同样需要映射——如果 hztxt.shx 缺失,光是把它映射成 gbcbig.shx 不够,还要确认对应样式有没有启用大字体模式,否则中文照样断。
4.3 LISP 批量替换文字样式的小脚本
当你需要把图纸里所有用 hztxt.shx 的样式统一改成 gbcbig.shx 时,手工一个个改太慢。我常用一段 LISP 脚本,直接在命令行加载执行,遍历当前图纸所有文字样式并替换字体引用。以下脚本会提示用户输入旧字体名和新字体名,然后自动处理:
(vl-load-com) (defun c:REPLFONT (/ doc tss item oldfont newfont) (setq oldfont (strcase (getstring "\n输入被替换的字体文件名(不含路径): "))) (setq newfont (getstring "\n输入新字体文件名(不含路径): ")) (setq doc (vla-get-activedocument (vlax-get-acad-object))) (setq tss (vla-get-textstyles doc)) (vlax-for item tss (if (= (strcase (vla-get-fontfile item)) oldfont) (vla-put-fontfile item newfont)) ;; 大字体同样处理,按需打开下面的注释 ;; (if (= (strcase (vla-get-bigfontfile item)) oldfont) ;; (vla-put-bigfontfile item newfont)) ) (vla-regen doc 0) (princ (strcat "\n已把样式中的 " oldfont " 替换为 " newfont)) (princ) )把上面内容保存成replfont.lsp,在命令行用APPLOAD加载,然后输入REPLFONT运行。脚本用strcase统一大小写,避免因文件名字母大小写不一致而漏替换。vla-get-textstyles返回图纸的样式集,vlax-for遍历每个样式对象,vla-put-fontfile是写入新的字体名。替换后vla-regen强制刷新,效果立即可见。注意这段脚本只改字体名,不改变量宽高比、字高参数;如果新旧字体字形宽差得多,文字布局可能需要单独调整。
4.4 替换前备份,替换后核对样式数量
批量替换之前建议先另存一份原图,或者至少执行一次SAVEAS生成副本。字体替换是写操作,一旦保存原字体信息可能就丢失了,回头想恢复只能靠备份。我一般是复制一个_font_backup.dwg放到同目录,再在副本上做替换测试,确认无误后才处理正式文件。这一步很朴素,但能救回不少“替换完才发现图里某处特殊符号全变了”的现场。
替换后的核对不只看有没有问号,还要打开样式表数一下改动是否完整。比如图纸里原来有 12 个样式引用 hztxt.shx,运行脚本后应该全部变为 gbcbig.shx,可以通过 STYLE 对话框逐个看,或者再跑一遍第 3 章里的 Python 解析脚本,对比替换前后的字体依赖列表。这一步把“感觉没问题”变成“确认没问题”,值得花两分钟。
5. 避坑:shx 字体替换路上的五类翻车现场
5.1 替换了字体但中文还是问号:大字体根本没配上
现象:把缺失的 shx 替换成已有字体后,英文正常,中文仍显示为“?”或空方块。原因:这个文字样式可能只设置了一个小字体,没有勾选“使用大字体”,原图纸依赖的大字体文件虽然存在,但在样式里根本没启用。解决:打开 STYLE 对话框,选中样式,勾选“使用大字体”,再指定正确的大字体文件。如果不想保留原大字体,就用 gbcbig.shx。还有一种隐蔽情况:MTEXT 对象自身带了字符格式,局部指定了另一个字体,样式层查不出问题,需要选中具体文字,在属性面板里检查文字格式覆盖。
5.2 钢筋符号、二级钢符号变成乱码或“?”
现象:结构图里钢筋符号全变成奇怪的字母或方框,其他中文倒正常。原因:钢筋符号位于特殊编码区,原字体用的可能是带有钢筋符号映射的特定大字体(某些设计单位自用的专业 shx),你用通用 gbcbig.shx 替代后,覆盖不了那些码位。解决:优先找回设计单位的原字体;实在没有,可以在网上找同行业通用的带钢筋符号字库,替换后专门放大检查几处钢筋标注。这个坑没有完美替代方案,最好的做法是提前收集本单位常用的几个专业字体,放到统一搜索路径里,少指望用通用字体兼容专业图纸。
5.3 替换后文字位置偏移、宽度不对
现象:字体换完后,整张图的尺寸标注和注释文字变得拥挤或稀疏,引线错位。原因:shx 字体之间的字形宽高比不同,原字体可能本身较扁或较窄,替换字体更宽,导致每行文字占用的空间变了;尺寸标注的文字间隙也会受影响。解决:替换后检查样式的宽度因子,必要时微调文字样式里的宽度因子。如果图纸有大量不同样式,先对比同一段文字替换前后在屏幕上的宽度,大致估算差异,再决定是否批量调整。这一步很费时间,所以我更推荐用 acad.fmp 做“全局兜底”,而不是直接改样式文件——因为映射方式不修改原始样式定义,文字宽度参数不变,至少不会放大布局偏差。
5.4 屏幕上显示正常,打印出来却缺字
现象:屏幕上所有文字都对,打印成 PDF 或纸张后部分文字消失、变成空心或乱码。原因:CAD 打印时如果使用了打印样式表或某些打印驱动,可能会尝试用系统字体替代 shx,替代字体缺字符就留白;另外,后台打印(不弹窗直接出图)时字体缓存过期也可能导致这问题。解决:先尝试前台打印,关掉后台打印功能;确认打印对话框中的“shx 文字”相关选项没有被强制替换成 TTF。如果只在输出 PDF 时出现,换一个 PDF 虚拟打印机对比,判断是字体问题还是驱动问题。这个问题必须打印后才能发现,所以我每次换字体后都强制出一次 PDF,绝不只看屏幕。
5.5 自己装的 shx 重启后失效
现象:字体明明拷到了硬盘上,刚装好时打开图纸正常,重启 CAD 后又提示缺失。原因:字体文件放的位置不在支持文件搜索路径里,或者 CAD 启动时加载的路径列表不包含该目录;还有可能是单位版 CAD 有统一配置,每次启动会重置搜索路径。解决:不要只是把字体放在“Fonts”目录外的任意文件夹,打开OPTIONS检查“支持文件搜索路径”是否包含你的字体目录,没有就加上。更稳妥的做法是把常用 shx 统一放到某个共享目录,并把它提升到搜索路径最前方,同时修改 acad.fmp 做兜底。如果你用的某款 CAD 是精简安装版,安装目录的 Fonts 文件夹里本身只带了少数几个字体,别把别人给的 shx 一股脑塞进去,先确认目录权限和路径,否则重启后系统还原又会丢。
6. 换完别急着交图:一份自查命令和 PDF 对比习惯
前面几章解决的是一次性替换的问题,但实际项目里图纸会不断更新,每收一次外部图都可能引入新的字体缺失。我现在的做法是把“检查缺失字体”做成固定动作:在一张新开的图纸里,用APPLOAD加载 4.3 节那个脚本的增强版,运行FINDMISS命令,脚本会遍历所有文字样式,逐个用findfile检查字体和大字体是否存在,缺哪个列哪个。
(vl-load-com) (defun c:FINDMISS (/ doc tss item fname bname miss) (setq doc (vla-get-activedocument (vlax-get-acad-object))) (setq tss (vla-get-textstyles doc)) (setq miss "") (vlax-for item tss (setq fname (vla-get-fontfile item) bname (vla-get-bigfontfile item)) (if (and fname (/= fname "") (null (findfile fname))) (setq miss (strcat miss "\n- [" (vla-get-name item) "] 缺小字体: " fname))) (if (and bname (/= bname "") (null (findfile bname))) (setq miss (strcat miss "\n- [" (vla-get-name item) "] 缺大字体: " bname)))) (if (/= miss "") (alert (strcat "发现缺失字体:" miss)) (alert "所有字体均存在")) (princ) )这个脚本的原理很简单:findfile会在支持文件搜索路径里寻找参数指定的文件名,找不到就返回 nil。把检查结果直接弹窗显示,省去逐个样式查看的体力活。注意脚本只能查“路径范围”内是否存在文件,无法验证文件内容是不是真正的 shx,也无法判断同名字体是否是别人随便改名的空壳——这种情况只能靠最终打印样张确认。所以我收到关键图纸时,会先跑一遍 FINDMISS,把缺失项清掉,再导出 PDF 做最终验收。
PDF 对比的具体做法:出图之前先把原始 PDF 保存一份,字体替换后再出一份,然后逐屏对比标题栏、说明文字、尺寸标注、图例四个区域。没有原始 PDF 时,用看图工具放大局部,重点检查带圈数字、直径符号、正负号、钢筋符号这几类最容易翻车的字符。这个对比习惯救过我不少次,比如有一次替换后用通用字库,屏幕上看完全正常,PDF 里直径符号全变了,就是因为同一个 shx 在不同字库里的映射不同,只有出图那一步能暴露问题。总结我的经验:dwg 的字体问题从来不是“装个字体文件”那么简单,它是一个从样式到路径再到打印输出的链路,每一步都留下验证痕迹才可靠。希望帮到你。
本文还有配套的精品资源,点击获取