把一个database里的某个 layout 复制到当前图形里,简化代码如下 (代码无意义,只为表达问题):
<CommandMethod("test", CommandFlags.Modal)>
Public Sub Test2()
Dim db As Database = Application.DocumentManager.MdiActiveDocument.Database
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim tm As DatabaseServices.TransactionManager = db.TransactionManager
Dim myT As Transaction = tm.StartTransaction()
Try
Using oDbSource As New Database(True, False)
Dim oLayoutsSource As DBDictionary = CType(tm.GetObject(oDbSource.LayoutDictionaryId, OpenMode.ForRead), DBDictionary)
Dim oLayoutFrom As Layout = CType(tm.GetObject(oLayoutsSource.GetAt("布局1"), OpenMode.ForRead), Layout)
Dim oBtrFrom As BlockTableRecord = CType(tm.GetObject(oLayoutFrom.BlockTableRecordId, OpenMode.ForRead), BlockTableRecord)
Dim idNewBtr As ObjectId = db.Insert(oBtrFrom.Name, oBtrFrom.Name, oDbSource, True)
Dim oNewBtr As BlockTableRecord = CType(tm.GetObject(idNewBtr, OpenMode.ForRead), BlockTableRecord)
Dim idNewLayout As ObjectId = oNewBtr.LayoutId
Dim oNewLayout As Layout = CType(tm.GetObject(idNewLayout, OpenMode.ForRead), Layout)
Dim oLM As LayoutManager = LayoutManager.Current
oLM.CurrentLayout = oNewLayout.LayoutName
End Using
Catch ex As Exception
ed.WriteMessage(ex.Message)
Finally
myT.Commit()
End Try
End Sub
其中 Dim idNewBtr As ObjectId = db.Insert(oBtrFrom.Name, oBtrFrom.Name, oDbSource, True) 那一行,从oDbSource中把“布局1”的内容复制到本图中,然后建立layout,并把新的layout设置为当前布局。
这段代码在ACAD中可以正常运行。
但中望会产生非法内存读写错误并闪退:“System.AccessViolationException:“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”
试着把myT.Commit移到End Using前面,就能产生正常结果。但是在实际程序中,这只是一个小部分,不可能在这里commit。
这是不是说明database.insert那里有点问题?按说把布局上的东西复制到本图中之后,对原oDbSource就没有依赖了,oDbSource被End Using,不应该影响后续的commit。
把一个database里的layout复制到本图中,有什么绕过去的建议?