如何编写代码实现从外部输入块,并插入到当前文件中?
大家好。采用代码可以绘制简单的图形,但有时有些图形很复杂,采用代码绘制时很繁琐,故我想请问一下,有没有可能将这些复杂图形预先做成块保存在独立的dwg文件中,在自己编写的程序运行时再从这个dwg文件中导入到运行的文档中,这样做是可行的吗?如何操作?请给我给点提示啊。
建议LZ找一个图库就可以解决你的问题 /// <summary>
/// 使用一个新建的database从另外一个不打开的文件引入块记录
/// ImportBlock_DB里的ReadDwgFile方法在编译调试环境下会出错,错误为:尝试读取或写入受保护的内存
/// 但在正常AutoCAD启动装载程序情况下可用
/// Version : 2008.11.11 Sieben
/// </summary>
/// <param name="fileName">另外一个文件的文件名</param>
/// <param name="blockName">引入的一个块记录名,若为空字符串"",将引入文件里面的全部图块</param>
/// <returns>成功返回true,否则返回false</returns>
static public StringCollection ImportBlock_DB(string fileName, string blockName)
{
if (!File.Exists(fileName)) return null;
Database sourceDb = new Database(false, true);
try
{
//下面的ReadDwgFile方法在编译调试环境下会出错,错误为:尝试读取或写入受保护的内存
//但在正常AutoCAD启动装载程序情况下可用.
sourceDb.ReadDwgFile(fileName, System.IO.FileShare.Read, false, "");
Database destDb = aApp.DocumentManager.MdiActiveDocument.Database;
ObjectIdCollection blockIds = new ObjectIdCollection();
StringCollection reValue = new StringCollection();
using (Transaction ctrans = sourceDb.TransactionManager.StartTransaction())
{
BlockTable cbt = (BlockTable)ctrans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false);
if (blockName == "")
{
foreach (ObjectId btrId in cbt)
{
BlockTableRecord cbtr = (BlockTableRecord)ctrans.GetObject(btrId, OpenMode.ForRead, false);
if (!cbtr.IsAnonymous && !cbtr.IsLayout)
{
blockIds.Add(btrId);
reValue.Add(cbtr.Name);
}
cbtr.Dispose();
}
}
else if (cbt.Has(blockName))
{
blockIds.Add(cbt);
}
cbt.Dispose();
}
if (blockIds.Count == 0)
{
return null;
}
else
{
IdMapping mapping = new IdMapping();
sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, new IdMapping(), DuplicateRecordCloning.Replace, false);
return reValue;
}
}
catch (System.Exception ex)
{
se.WriteMessage(ex);
return null;
}
finally { sourceDb.Dispose(); }
} /// <summary>
/// 将dwg文件作为图块引入
/// 备注:
/// 1,不生成块参考
/// 2,应对文件Insbase不是原点的情况 2011.04.23
/// Version : 2011.04.23 Sieben
/// </summary>
/// <param name="fileName">dwg文件全名</param>
/// <param name="blockName">生成的块记录名,输入空字符串时将使用文件名作为块记录名(不含扩展名)</param>
/// <param name="replace">若对应的块记录名已存在,是否替换</param>
/// <returns>若成功返回块记录的ObjectId,否则返回ObjectId.Null </returns>
static public ObjectId InsertDwg(string fileName, ref string blockName, bool replace)
{
try
{
if (!replace)
{
ObjectId blockId = sn.GetRecordId(sc.db.BlockTableId, blockName);
if (blockId != ObjectId.Null)
return blockId;
}
if (fileName == "" || !File.Exists(fileName))
return ObjectId.Null;
if (!fileName.ToLower().EndsWith(".dwg"))
return ObjectId.Null;
}
catch (System.Exception ex)
{
se.WriteMessage(ex);
return ObjectId.Null;
}
Database newDB = new Database(false, false);
bool newDBHasDispose = false;
try
{
if (blockName == "")
{
FileInfo fileInfo = new FileInfo(fileName);
blockName = fileInfo.Name.Substring(0, fileInfo.Name.Length - 4);
}
newDB.ReadDwgFile(fileName, System.IO.FileShare.Read, true, fileName);
if (newDB.Insbase.GetAsVector().Length > 0.00001)
{
if (newDB.Insbase.X >= newDB.Extmin.X && newDB.Insbase.X <= newDB.Extmax.X
&& newDB.Insbase.Y >= newDB.Extmin.Y && newDB.Insbase.Y <= newDB.Extmax.Y)
{
//Insbase位于图形范围,不进行移动,有可能不符合预期
return sc.db.Insert(blockName, newDB, true);
}
else
{
if (newDB.Extmin.X > newDB.Extmax.X)
{
//图形范围Extmin Extmax未初始化,不进行移动,有可能不符合预期
return sc.db.Insert(blockName, newDB, true);
}
else
{
Matrix3d tMat = Matrix3d.Displacement(newDB.Insbase.GetAsVector().Negate());
newDB.Insbase = Point3d.Origin;
ObjectId blockId = sc.db.Insert(blockName, newDB, true);
if (0 >= newDB.Extmin.X && 0 <= newDB.Extmax.X&& 0 >= newDB.Extmin.Y && 0 <= newDB.Extmax.Y)
{
//坐标原点位于图形范围,不进行移动,有可能不符合预期
return blockId;
}
else
{
//Insbase不位于图形范围 坐标原点也不位于图形范围,将图形从Insbase移到原点,有可能不符合预期
using (Transaction ctrans = sc.db.TransactionManager.StartTransaction())
{
BlockTableRecord cbtr = (BlockTableRecord)ctrans.GetObject(blockId, OpenMode.ForWrite);
foreach (ObjectId tId in cbtr)
{
Entity ent = (Entity)ctrans.GetObject(tId, OpenMode.ForWrite);
ent.TransformBy(tMat);
}
ctrans.Commit();
}
return blockId;
}
}
}
}
else
{
//Insbase位于原点,不用做任何处理
return sc.db.Insert(blockName, newDB, true);
}
}
catch (System.Exception ex)
{
se.WriteMessage(ex);
return ObjectId.Null;
}
finally
{
if (!newDBHasDispose)
newDB.Dispose();
}
} sc.db = HostApplicationServices.WorkingDatabase sieben 发表于 2013-3-31 08:07 static/image/common/back.gif
sc.db = HostApplicationServices.WorkingDatabase
你好,sieben。
请问,在你的第二个解答方案中定义的变量“sc,se,sn”是怎么定义的,请再详细一点,谢谢。 ObjectId blockId = sn.GetRecordId(sc.db.BlockTableId, blockName);
if (blockId != ObjectId.Null)
return blockId;
---------------------
这里是检查当前Dwg文件有没有同名图块,其他没有什么了,你可以注销这些代码 sieben 发表于 2013-4-1 12:52 static/image/common/back.gif
ObjectId blockId = sn.GetRecordId(sc.db.BlockTableId, blockName);
if (blockId ! ...
你好,sieben。
谢谢帮助,你的第二个方法在我这里调试通了。但我还有点问题。
你的第二个函数InsertDwg()一定要是静态的吗?
第二个函数InsertDwg()的第二个形参为啥一定要传指针?“ref string blockName” ?
这个函数返回的应该是插入的块的Objectid吧? 本帖最后由 介之推 于 2013-4-1 16:05 编辑
你好,sieben。
你的第二个函数调试通了以后,编译不出问题,我这样调用你的InsertDwg()函数,运行时出错了,显示的是“eSelfReference”,就是自引用了,不知道问题出现在哪里?
这是我的调用函数。
public void InsertBlock()
{
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
using (Transaction trans = db.TransactionManager.StartTransaction())
{
//ImportBlock_DB("test.dwg", "sample");
string blockName = "sample"; InsertDwg("test.dwg", ref blockName);
trans.Commit();
}
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.StackTrace + "\n" + ex.Message + "\n" + ex.TargetSite);
return;
}
}
出错的代码在这里
if (newDB.Insbase.GetAsVector().Length > 0.00001)
{
//中间部分么有改动
}
else
{
//Insbase位于原点,不用做任何处理
//return sc.db.Insert(blockName, newDB, true);
return myDb.Insert(blockName, newDB, true); //这行出错了,错误信息:eSelfReference
}
介之推 发表于 2013-4-1 14:58 static/image/common/back.gif
你好,sieben。
谢谢帮助,你的第二个方法在我这里调试通了。但我还有点问题。
你的第二个函数InsertDw ...
1,否
2,不解析,无所谓