bug:字体偏移
动图演示:绑定参照后出现
动图演示:代码克隆后出现
有问题的代码
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
namespace BlockImport
{
public class BlockImportClass
{
[CommandMethod("tt")]
public void ImportBlocks()
{
DocumentCollection dm = Application.DocumentManager;
Editor ed = dm.MdiActiveDocument.Editor;
Database destDb = dm.MdiActiveDocument.Database;
Database sourceDb = new Database(false, true);
PromptResult sourceFileName;
try
{
//从命令行要求用户输入以得到要导入的块所在的源 DWG 文件的名字
#if false
sourceFileName = ed.GetString("
输入来源DWG的完整路径: "); //把源 DWG 读入辅助数据库
sourceDb.ReadDwgFile(sourceFileName.StringResult, System.IO.FileShare.Read, true, "");
#else
sourceDb.ReadDwgFile(@"D:桌面T.dwg", System.IO.FileShare.Read, true, "");
#endif
//用集合变量来存储块 ID 的列表
var blockIds = new ObjectIdCollection();
using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
{
//打开块表
BlockTable bt = tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false) as BlockTable;
//在块表中检查每个块
foreach (ObjectId btrId in bt)
{
var btr = tr.GetObject(btrId, OpenMode.ForRead, false) as BlockTableRecord;
//只添加有名块和非 layout 块(layout 块是非 MS 和非 PS 的块)
if (!btr.IsAnonymous && !btr.IsLayout)
blockIds.Add(btrId);
btr.Dispose(); //释放块表记录引用变量所占用的资源
}
bt.Dispose();//释放块表引用变量所占用的资源 //没有作改变,不需要提交事务
tr.Dispose();
}
//用 WblockCloneObjects 把所有的块从源库拷贝块到目的库的块表中
//这只能实现导入块到指定的数据库中,但不是深度克隆,
//若对块参照实行深度克隆的话,其所引用的块也会被克隆到指定的数据库中
IdMapping mapping = new IdMapping();
sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
ed.WriteMessage
("
复制 "
+ blockIds.Count.ToString()
+ " 个块的定义"
//+ sourceFileName.StringResult
+ " 到当前绘图的块表记录."
);
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
ed.WriteMessage("
复制过程中的错误: " + ex.Message);
}
sourceDb.Dispose();
}
}
}
这是一个kean在博客的dbx例子,也就是后台打开dwg.
使用它时,在某些情况下单行文字/属性会出现不在文字图形的对齐点位置,此问题称为"字体偏移".
bug图元
单行文字或属性.
当克隆来源使用了:"新宋体.TTF",对齐样式为:"中间,正中,中"等...非"左"的对齐方式,这将导致偏移发生.
左: AttachmentPoint.BaseLeft
但是由于本人测试过少,不清楚此问题的出现是否存在于所有的.TTF文件下,便已经找到了解决方案了,对此并没有详尽的bug报告.
测试环境
测试环境:中文版Acad2008~Acad2019
1:使用参照面板,然后绑定
2:使用克隆命令
测试环境:中文版Acad2020+
1:使用参照面板,然后绑定
2:使用克隆命令
3:由于这个版本桌子重写了一个新的insert命令,也就是i这个命令,它会弹出一个带预览的小面板,这个命令也会导致此问题发生.
解决方案1:
一旦出现了字体偏移,那么此情况会保存到dwg内.
而当你不加载问题功能前提下,打开图纸,双击文字,它会从偏移态恢复为正常态.
遇到此情况不妨用代码:遍历全图,移动0,0到0,0.
解决方案2:
1:来源数据库的文字样式表修改"新宋体"为任何一种大字体.
2:再更改文字实体对齐方式为"左",
3:再进行克隆(WblockCloneObjects).
4:最后在目标数据库还原样式.(已经亲测,必须这样做,只改一项都不行)
注意的是修改Dbtxt的对齐方式从左到其他时候,要提交一次事务,再开事务,才能获得到单行文字的新基点(很奇葩!),再能从新基点移动到旧基点..
这样克隆(WblockCloneObjects)才不会出现文字矩阵的错误!!
提供参考代码:
一些委托函数见委托的学习
/// <summary>
/// 克隆来源的某个块到目标数据库
/// 不允许事务包裹
/// </summary>
/// <param name="ddb">目标数据库,通常是当前数据库</param>
/// <param name="path">来源dwg的路径</param>
/// <param name="blockName">块名</param>
/// <returns></returns>
public static IdMapping CloneBlock(this Database ddb, string path, string blockName = null, string password = null)
{
if (!File.Exists(path))
{
return null;
}
IdMapping mapping = new IdMapping();//id映射
var sIds = new ObjectIdCollection(); //来源图的块id
var fontsNo = new string[] { "新宋体", "宋体" };
var fonstNames = new List<string>(); //st用户定义的名称
var fonstFileNames = new List<string>();//st字体本名
OpendDwg.Read(path, sdb =>
{
using (Transaction tr = sdb.TransactionManager.StartTransaction())//来源数据库的事务
{
//判断当前文件如果有新宋体,就修改为大字体
sdb.TraverseTextStyleTable(tr, tsRec =>
{
if (fontsNo.Contains(tsRec.Font.TypeFace))//字体本名不能是这些,否则引起文字矩阵错乱导致字体偏移现象!
{
fonstNames.Add(tsRec.Name);
fonstFileNames.Add(tsRec.FileName);
tr.AddTextStyle(sdb, tsRec.Name, "txt.shx", "gbcbig.shx");
}
return false;
});
//打开块表
sdb.TraverseBlockTable(tr, btRec =>
{
//只添加有名块和非 layout 块(layout 块是非 MS 和非 PS 的块)
if (!btRec.IsAnonymous && !btRec.IsLayout)
{
if (string.IsNullOrEmpty(blockName) && btRec.Name == blockName)//有输入块名的时候执行快点
{
sIds.Add(btRec.ObjectId);
return true;
}
else
{
sIds.Add(btRec.ObjectId);
}
}
btRec.Dispose(); //释放块表记录引用变量所占用的资源
return false;
});
}
//克隆到目标块表内
sdb.WblockCloneObjects(sIds, ddb.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);
});
return mapping;
}
后记
我的配置是32位修改的Acad2008安装到64位的win10上,但是我的Acad2019也会出现同样的情况,而e大用英文的2019却没有复现成功,
所以我没能正确告诉桌子如何修改的bug(毕竟他们是歪果仁),
后来群里有人说,如果使用了开图复制,那么文字矩阵不会出错.
Acad2008字体偏移在外部参照绑定的时候也会出现,但是insert却不会,
而Acad2020里面的insert小面板也会,
可见桌子的代码传承有问题,(这个时候没有说我为什么喜欢用旧版本了吧)
bug:Acad2008符号表NetAPI
Acad2008.NetAPI 如果你建一个块,再删除它,再添加一个同名块,用名称获取块定义会得到删除了的那个,然后爆了,
这在2008所有符号表上均存在,所以要循环获取并容错处理,或检测id是否已经被删除,
而高版本已经修复了这个问题.
(完)