I'm searching for sample code for highlighting blocks within Xrefs. I've written a "Find Block" program that works well for regular blocks within a drawing, but I'm having trouble modifiying to include blocks within Xrefs. I've found code for nested blocks, but that doesn't seems to work for Xrefs. Can you provide an example for Xrefs? Thanks very much. Pete Elliott
Solved! Go to Solution.
Solved by elliottpd11. Go to Solution.
Finding an item in an xref should be exactly the same as finding a nested item in a block. Basically an xref is a block in your current drawing. You need to dig down into that block and find the items that you want. Below is a code snippet that I use to display custom tooltips. It will find a tooltip in the main drawing or in an xref. It uses the point monitor callback method to determine the object under the aperature and then return its objectID. The code will continually dig into a block reference until it stops finding block references and instead finds one of the objects that I am searching for.
public static void PointMonitor(object sender, PointMonitorEventArgs e) { toolTipObjectId = ObjectId.Null; if (Application.GetSystemVariable("RollOverTips").ToString() != "1" || !SuperToolTipSettings.EnableSuperToolTips) return; if ((e.Context.History & PointHistoryBits.FromKeyboard) == PointHistoryBits.FromKeyboard) return; FullSubentityPath[] paths = e.Context.GetPickedEntities(); if (paths == null || paths.Length == 0) return; ObjectId[] ids = paths[0].GetObjectIds(); if (ids == null || ids.Length == 0) return; var i = 0; if (!ids[i].IsValid) return; GetClass(ids, i) ; } private static void GetClass(ObjectId[] ids, int i) {
// Here you would check the ObjectID and see if it is an object you are interested in.
// If so then return the objectID, if not check to see if it is a block reference and then
// Dig into that block reference and start again. if ((ids[i].ObjectClass.Name == "AecbDbDuct" && SuperToolTipSettings.DisplayDuct)) { toolTipObjectId = ids[i]; } if (ids[i].ObjectClass.Name == "AcDbBlockReference") { GetClass(ids, i + 1); } }
In my application, there is no direct user selection, other than to select a block name from a list. So I am assembling the id path using the xref id and the block reference id. But this is not working. Can you suggest what I may be doing wrong?
''' <summary>
''' Highlights or unhighlights an xref-nested block
''' </summary>
''' <param name="myTrans">Transaction object</param>
''' <param name="myBT">BlockTable object for main drawing</param>
''' <param name="myID">ObjectID for the block reference within xref</param>
''' <param name="BlockName">Block name of the block reference</param>
''' <param name="IsHighlighted">True to highlight, False to unhighlight</param>
''' <version>v12.1.1.0 09/02/14 PDE: Initial program</version>
SubHighlightXrefBlock(ByRef myTrans As Transaction, ByRef myBT As BlockTable, ByVal myID As ObjectId,
ByVal BlockName As String, ByVal IsHighlighted As Boolean)
If BlockName.Contains("|") Then
Dim XrefName As String = BlockName.Substring(0, BlockName.IndexOf("|"))
If XrefName <> String.Empty Then
If myBT.Has(XrefName) Then
Dim myXrefBTR As BlockTableRecord = CType(myTrans.GetObject(myBT(XrefName), OpenMode.ForRead), BlockTableRecord)
Dim xrefInstances As ObjectIdCollection = myXrefBTR.GetBlockReferenceIds(True, False)
If xrefInstances.Count > 0 Then
Dimpathids(1) As ObjectId
pathids(0) = xrefInstances(0)
pathids(1) = myID
Dim subEntID As SubentityId = New SubentityId(SubentityType.Null, IntPtr.Zero)
Dim SubEntPath As FullSubentityPath = New FullSubentityPath(pathids, subEntID)
Dim xrefblock As Entity = CType(myTrans.GetObject(xrefInstances(0), OpenMode.ForRead, False, True), Entity)
If IsHighlighted Then
xrefblock.Highlight(SubEntPath, False)
Else
xrefblock.Unhighlight(SubEntPath, False)
EndIf
EndIf
EndIf
EndIf
EndIf
EndSub
Well there are some things that you left out that you need to think about. How deep are you going to go with finding the block? What if the block is nested in a block that is nested in a block that is inside of an xref?
To find ALL of the blocks you should take the approach that I showed. Get the block name from the user. Then get all blocks and cycle through them getting nested entities until you find the blockname that you want. Then get the object ID of the block reference and then highlight it. That is the approach that I would take. I believe that it is the only way to get ALL of the blocks in one operation without picking. If you only care about one level deep or two levels deep or ..... then you can take a different approach.
Again there is no need to specifically look for an xref. The xref is just a block reference in your current drawing so just look for the block name inside of nested entities. Keep going until you find your block reference or there are no more block references. Recursion works great in this instance. Just keep a running total of all objectids that equal your block name.
I have only briefly looked at the code in this thread, but I'm wondering, are you SURE it's not finding the blocks, or is it just not highlighting them?
I have a bit of Lisp code I wrote a very long time ago, the display the grips of object(s) nested in xref(s), by user selection. this was intended to be able to better see the object in question when working in 3d and looking at things from the side, or front, trying to figure out if there are collisions. I still find the routine to be useful to this day, but it always had a problem, it would highlight and display grips for objects in the current drawing, but the nested objects would only display grips, they would not show the highlight.
Hi
I believe "myID" is the bref Object Id , you can get Bref entity and use
refblock.Highlight(); for highlighting. Is this not working at your end ?
Hi
Is it possible for your share your project , I will research at my end. I don't have readymade sample to work out.
Hi ,
Sorry , I couldn't offer a better solution at the moment ,besides this
Thanks,
So then, would it be correct to say that there is no way to highlight blocks contained within an Xref, using the .net API? - Pete Elliott
Hi Pete ,
There is way as I discussed with you in my earlier comments using overrule ,besides that I don't have better solution , may be others can provide.
Thanks
Madhu.
I've been playing with transient graphics, and am not very knowledgable in this area. This code will highlight a block nested within an Xref. But I'm wondering, does this code leave anything behind in memory that can cause issues later?
[The variable myBR is a BlockReference opened for read within a transaction.] Regen seems to remove the highlight.
Dim thisDrawable As GraphicsInterface.Drawable = myBR
Dim col As New IntegerCollection
GraphicsInterface.TransientManager.CurrentTransientManager.AddTransient(thisDrawable,
GraphicsInterface.TransientDrawingMode.Highlight, 128, col)
Thanks, Pete Elliott
Hi Pete ,
That's a good idea to solve your case !
But clone your Bref and add as transient and make sure you remove transient using erase transient api.
Benefit of cloning is to avoid unexpected memory chaos :), clone is not a DBR object ,so you can play as you wish.