Through the Interface帖子中的代碼示例導入塊,但不會將它們插入到圖形中。您必須創建一個BlockReference
並將其添加到模型空間。它還從文件中插入所有塊,而不是將文件作爲單個塊插入。
這是我用來作爲一個整體塊導入文件的代碼。該函數返回一個可以插入到圖形中的塊引用。
Private Shared Function InsertFile(ByVal FileName as String, ByVal dwgdb As Database, ByVal tr As Transaction) As BlockReference
Dim br As BlockReference
Dim id As ObjectId
'use a temporary database
Using TempDB As New Database(False, True)
'Get block table
Dim bt As BlockTable = tr.GetObject(dwgdb.BlockTableId, OpenMode.ForWrite, False)
'Create unique block name
Dim BlockName As String = FileName.Replace("\", "").Replace(":", "").Replace(".", "")
'check if block already exists
If Not bt.Has(BlockName) Then
'check if file exists
If IO.File.Exists(FileName) Then
'read in the file into the temp database
TempDB.ReadDwgFile(FileName, IO.FileShare.Read, True, Nothing)
'insert the tempdb into the current drawing db, id is the new block id
id = dwgdb.Insert(BlockName, TempDB, True)
Else
'Throw exception for missing file
Throw New System.Exception(String.Format("File {0} is not found for library item {1}", FileName, item.PartNo))
End If
Else
id = bt.Item(BlockName)
End If
'create a new block reference
br = New BlockReference(New Point3d(0, 0, 0), id)
End Using
Return br
End Function
這裏是使用該函數將塊插入文件的示例。在這個例子中,我使用了一個夾具,它允許用戶將物體放到他們想要的位置,否則你可以設置位置。
' Get Editor
Dim ed As Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
' Get Database
Dim dwg As Database = ed.Document.Database
'Lock document
Using dl As DocumentLock = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument()
'### Changed Try Finally to using, try was hiding errors
'Begin Transaction
Using trans As Transaction = dwg.TransactionManager.StartTransaction()
Dim blockRef As BlockReference = InsertFile(FileName, dwg, trans)
'check if layer exists/create
AcadUtil.AcadFunctions.CheckLayer(LayerName, trans, dwg)
blockRef.Layer = LayerName
'set focus to the editor
Autodesk.AutoCAD.Internal.Utils.SetFocusToDwgView()
'have the user pick insert point
Dim BlockMove As New AcadJigs.JigBlockMove(blockRef, False, 0)
ed.Drag(BlockMove)
'optionally you could just set the .Position of the block reference
' add it to the current space, first open the current space for write
Dim btr As BlockTableRecord = trans.GetObject(dwg.CurrentSpaceId, OpenMode.ForWrite, True, True)
' Add block reference to current space
btr.AppendEntity(blockRef)
'Capture the handle
handle = blockRef.Handle.Value.ToString
' remember to tell the transaction about the new block reference so that the transaction can autoclose it
trans.AddNewlyCreatedDBObject(blockRef, True)
'commit the transaction
trans.Commit()
End Using
End Using
而這裏也是我所稱的CheckLayer
函數。
Public Shared Sub CheckLayer(ByVal Name As String, ByVal tr As Transaction, ByVal dwg As Database)
Dim lt As LayerTable = CType(tr.GetObject(dwg.LayerTableId, OpenMode.ForWrite), LayerTable)
If lt.Has(Name) Then
Return
Else
Dim ly As New LayerTableRecord
ly.Name = Name
lt.Add(ly)
tr.AddNewlyCreatedDBObject(ly, True)
End If
End Sub
正如一個音符,基恩的博客是一個偉大的資源,我幾乎學會了所有上面的代碼從那裏。
爲了完整起見,這裏是夾具類我在插入代碼中引用,在
.NET ObjectARX的
Class JigBlockMove
Inherits EntityJig
Private _CenterPt As Point3d
Private _ActualPoint As Point3d
Private _LockZ As Boolean
Private _Z As Double
Public ReadOnly Property SelectedPoint() As Point3d
Get
Return _ActualPoint
End Get
End Property
Public Sub New(ByVal BlockRef As BlockReference, ByVal LockZ As Boolean, ByVal Z As Double)
MyBase.New(BlockRef)
_CenterPt = BlockRef.Position
_LockZ = LockZ
_Z = Z
End Sub
Protected Overloads Overrides Function Sampler(ByVal prompts As JigPrompts) As SamplerStatus
Dim jigOpts As New JigPromptPointOptions()
jigOpts.UserInputControls = (UserInputControls.Accept3dCoordinates Or UserInputControls.NoZeroResponseAccepted Or UserInputControls.NoNegativeResponseAccepted)
jigOpts.Message = vbLf & "Enter insert point: "
Dim dres As PromptPointResult = prompts.AcquirePoint(jigOpts)
If _ActualPoint = dres.Value Then
Return SamplerStatus.NoChange
Else
_ActualPoint = dres.Value
End If
Return SamplerStatus.OK
End Function
Protected Overloads Overrides Function Update() As Boolean
If _LockZ Then
_CenterPt = New Point3d(_ActualPoint.X, _ActualPoint.Y, _Z)
Else
_CenterPt = _ActualPoint
End If
Try
DirectCast(Entity, BlockReference).Position = _CenterPt
Catch generatedExceptionName As System.Exception
Return False
End Try
Return True
End Function
Public Function GetEntity() As Entity
Return Entity
End Function
End Class
一個說明有關工作,有一個與AutoCAD的單線程性質的問題, .NET垃圾收集器在單獨的線程上運行的事實。如果您創建任何不會添加到數據庫中的臨時AutoCAD對象,則必須明確地在其上調用.Dispose()
,否則AutoCAD可能會崩潰!這個崩潰看起來也是隨機的,因爲它會被垃圾收集器線程觸發。看到這篇文章,http://through-the-interface.typepad.com/through_the_interface/2008/06/cleaning-up-aft.html。
謝謝。一旦我開始工作,我正在檢查這個。另外,我幾乎在任何事情上都使用Using語句,所以所有事情都得到了處理(保證,即使有例外等)。 – Alxandr
你知道是否有任何簡單的方法讓autocad彈出「輸入(多個)屬性(字符串)」 - 窗口?就像,如果我只是使用「-IMPORT」命令,它會彈出一個窗口告訴我輸入「修訂號」和「修訂名稱」。我可以在.NET中以某種方式獲得相同的行爲嗎? – Alxandr
不確定,但您可以在代碼中設置屬性,以便始終可以顯示自己的模式對話框以獲取信息。 – Kratz