马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
问题:
How to modify a drawing object inside a VBA event handler like the document object’s ObjectAdded event
解答:
Consider this: Using WithEvents in VB(A), you are trying to modify an object passed to the document's ObjectAdded, ObjectModified events, or drawing object's Modified event. However, this results in Error that look similar to this: "Object was opened for read" or similar. How can you work around this?
Firstly, modifying objects in events such as these is generally not recommended and not worth the trouble you might face later; especially if you are trying to modify objects that are already in the process of being modified. That is rarely a good idea.
However, if you absolutely need to modify objects in event handlers, there are some ways to achieve it.
ActiveX events are modeled on ObjectARX Event handling mechanism (reactors). There are many notifications when object is in an open state (for Read, Write or Notify) so in general, you cannot change it from within the event, evidenced by the fact for instance that the object is passed ByVal to the ObjectAdded event. You can however access any object for write in the CommandEnded event. So, you can set some global flags, trigger them in CommandStart, store ObjectIds during ObjectAdded and use the Ids in CommandEnded to change the relevant objects. For example, the code below will alter any line added to the document. This is the solution specific to VBA. For VB you have additional complexity of attaching events to docs (but that is a topic for another blog post).
下面是VBA代码
- Option Explicit
- Dim cIDs As New Collection ' collection for line IDs to be modified
- Dim bFlag As Boolean ' flag to indicate when modification needed
- Private Sub AcadDocument_BeginCommand(ByVal CommandName As String)
- ' Here we can set the flag ONLY for particular command.
- ' For simplicity, set always in this sample
- bFlag = True
- Call ClearCollection(cIDs)'Just in case
- '(done already in EndCommand)
- End Sub
- Private Sub AcadDocument_ObjectAdded(ByVal Object As Object)
- If bFlag Then ' If flag on and line - add the ID to the collection
- Dim obj As AcadObject
- Set obj = Object
- If obj.ObjectName = "AcDbLine" Then
- cIDs.Add obj.ObjectID
- End If
- End If
- End Sub
- Private Sub AcadDocument_EndCommand(ByVal CommandName As String)
- ' Set all line start points to origin and color to magenta
- If bFlag Then
- Dim pntO(0 To 2) As Double
- pntO(0) = 0#: pntO(1) = 0#: pntO(2) = 0#
- Dim id As Variant
- For Each id In cIDs
- Dim line As AcadLine
- Set line = ThisDrawing.ObjectIdToObject(id)
- line.StartPoint = pntO
- line.Color = acMagenta
- Next id
- ' Reset flag and collection
- bFlag = False
- Call ClearCollection(cIDs)
- End If
- End Sub
- Private Sub ClearCollection(cCol As Collection)
- Dim iCnt As Long
- For iCnt = 1 To cCol.Count
- cCol.Remove 1 ' Since collections are reindexed
- 'automatically, remove the first member
- Next iCntEnd
- End Sub
|