That was embarrassing. I was testing with a block without attributes for simplificy, but its the attributes that cause the problem in Janet's drawing. The fix is to also overrule the SetAttributes function. In the example code below, I'm unsetting bit 32 of the returned value from that function to stop the overruled BlockReference reporting that it has attributes. We can then draw the AttributeReferences ourselves. Here's the code (now in VB, as Janet and CBC both said they're working in VB):
Public Class test2
Friend Shared BlockOverrule1 As toverrule
<CommandMethod("tt")> _
Public Sub TestMethod()
If BlockOverrule1 Is Nothing Then
BlockOverrule1 = New toverrule
Overrule.AddOverrule(RXClass.GetClass(GetType(BlockReference)), BlockOverrule1, True)
Overrule.Overruling = True
End If
Application.DocumentManager.MdiActiveDocument.Editor.Regen()
End Sub
Public Class toverrule
Inherits Autodesk.AutoCAD.GraphicsInterface.DrawableOverrule
Private Shared _circle As Circle
'Create our circle which gives for the duration of the overrule
Public Sub New()
_circle = New Circle(New Point3d(0.5, 0, 0), New Vector3d(0, 0, 1), 0.25)
End Sub
Public Overrides Function SetAttributes(ByVal drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, ByVal traits As Autodesk.AutoCAD.GraphicsInterface.DrawableTraits) As Integer
Dim res As Integer = MyBase.SetAttributes(drawable, traits)
'See ARX ref guide entry for "AcGiDrawable::SetAttributesFlags Enumeration"
'Bit 32 indicates entity has attributes. If we unset that bit,
' then overruling blockref with attributes works fine. We do
' this because we're drawing the attributes ourself.
Dim test As Integer = res And 32
If test Then
res = res - 32
End If
Return res
End Function
Public Overrides Function WorldDraw(ByVal drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, ByVal Wd As Autodesk.AutoCAD.GraphicsInterface.WorldDraw) As Boolean
Dim thisBR As BlockReference = CType(drawable, BlockReference)
Wd.Geometry.PushModelTransform(thisBR.BlockTransform)
If thisBR Is Nothing Then
Return MyBase.WorldDraw(drawable, Wd)
End If
If thisBR.Database Is Nothing Then
Return MyBase.WorldDraw(drawable, Wd)
End If
Using trans As Transaction = thisBR.Database.TransactionManager.StartOpenCloseTransaction()
Dim btr As BlockTableRecord = TryCast(trans.GetObject(thisBR.BlockTableRecord, OpenMode.ForRead), BlockTableRecord)
For Each entId As ObjectId In btr
Dim ent As Entity = TryCast(trans.GetObject(entId, OpenMode.ForRead), Entity)
Dim aLine As Line = TryCast(ent, Line)
If aLine IsNot Nothing Then
'Calc additional transformation to push so circle is
' scaled to line dimensions
Dim ECS_OriginPt As Point3d = aLine.StartPoint
Dim ECS_XVec As Vector3d = aLine.Delta.GetNormal
Dim ECS_ZVec As Vector3d = aLine.Normal
Dim ECS_YVec As Vector3d = ECS_ZVec.CrossProduct(ECS_XVec)
' We don't want text to scale with the line length, so we calculate an 'unscaled' ECS for the text
Dim unscaledECS_Mat As Matrix3d = Matrix3d.AlignCoordinateSystem(Point3d.Origin, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, ECS_OriginPt, ECS_XVec, ECS_YVec, ECS_ZVec)
' We do want the circle and arc to scale with the line, so we calculate a 'full' (corrctly scaled) ECS
Dim ECS_Mat As Matrix3d = Matrix3d.Scaling(aLine.Length, aLine.StartPoint) * unscaledECS_Mat
' Push our scaled transform
Wd.Geometry.PushModelTransform(ECS_Mat)
' Draw the arc and circle
Wd.Geometry.Draw(_circle)
Wd.Geometry.PopModelTransform()
Else
If Not TypeOf ent Is AttributeDefinition Then
Wd.Geometry.Draw(ent)
End If
End If
Next
Wd.Geometry.PopModelTransform()
If thisBR.AttributeCollection.Count <> 0 Then
For Each id As ObjectId In thisBR.AttributeCollection
Dim obj As DBObject = trans.GetObject(id, OpenMode.ForRead)
Dim ar As AttributeReference = TryCast(obj, AttributeReference)
Wd.Geometry.Draw(ar)
Next
End If
trans.Commit()
End Using
Return True
End Function
End Class
End Class
I've also edited the code to use a single instance of _circle that lives for the lifetime of the overrule (instead of constantly creating a new one and displosing it), and to apply an additional model transformation to scale it to the location of the line its replacing. (I haven't added a destructor to the class to correctly Dispose _circle when the overrule is destroyed - which should be done). I've also not set any subentitytraits in the code (such as layer, color, etc).
Hopefully that covers what you need for your own implementation.
Cheers,
Stephen Preston
Autodesk Developer Network