Hello,
I have a sub that gets a page number and a collection of layer ID's to freeze. The sub will freeze the selected layers in all of the viewports except for the new one.
After running the program, the layers in the specific viewport are still visible, but when you go into Model mode in the viewport and check the layer status, it shows the selected layers are set to Freeze in the viewport.
If I save the drawing, exit,and re-open it, the layers are now not visible. I believe I have the "Regen" in the correct spot.
The code is attached.
' Freezes the selected layers in all other existing viewport layouts Public Sub freezeOtherLayouts(ByVal pageNumber As Integer, ByVal layersToFreezeLayerIds As ObjectIdCollection) Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim detailLayer As String = "DETAIL_" & pageNumber Dim vp As Viewport = Nothing Dim viewPortFound As Boolean Dim vpIDs As ObjectIdCollection = Nothing Dim allLayerIDs As New ObjectIdCollection, detailLayerID As New ObjectIdCollection Dim freezeVPtrans As Transaction = Nothing Try freezeVPtrans = db.TransactionManager.StartTransaction() Dim myBT As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead) For Each btrID As ObjectId In myBT Dim myBTR As BlockTableRecord = btrID.GetObject(OpenMode.ForRead) ' If the block table record is a layout If myBTR.IsLayout Then viewPortFound = False If Not myBTR.Name = "*Model_Space" Then Dim layOut As Layout = myBTR.LayoutId.GetObject(OpenMode.ForRead) ' If the layout is the new layout If layOut.TabOrder <> pageNumber Then For Each id As ObjectId In myBTR Dim obj As DBObject = id.GetObject(OpenMode.ForWrite) ' If the object is a viewport (there is a model viewport which is found first, we want the second one) If TypeOf obj Is Viewport And viewPortFound = True Then Dim vpref As Viewport = DirectCast(obj, Viewport) ' Selected Viewport for write. vp = freezeVPtrans.GetObject(vpref.ObjectId, OpenMode.ForWrite) Dim lt As LayerTable = freezeVPtrans.GetObject(db.LayerTableId, OpenMode.ForRead) ' Freeze the selected layers in the viewports vp.FreezeLayersInViewport(layersToFreezeLayerIds.GetEnumerator()) lt.Dispose() End If If TypeOf obj Is Viewport Then viewPortFound = True End If Next End If End If End If Next Catch ed.WriteMessage("Error!") Finally freezeVPtrans.Commit() freezeVPtrans.Dispose() ed.Regen() End Try End Sub
Thanks,
Mark
Try add at the end of code:
ed.UpdateTiledViewportsInDatabase()
~'J'~
My viewport is in paperspace on layout P1 (I have Model, P1, and P2 layouts). In order to see what layers are frozen in that particular viewport, I double picked in the viewport, which put me in Model mode.
Hi Jeff,
Can you explain more in regards to "Might try iterating Database.GetViewports() passing in false". I'm kinda new to VB.Net and I'm still learning.
Thanks,
Mark
This might work ok if your trying to not freeze the layers in new viewport and has never been Intialized, but would need to intialize any layouts that have never been.
<CommandMethod("FreezeLayers")> _ Public Sub MyGroupFreezeLayers() ' This method can have any name Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Using trx As Transaction = db.TransactionManager.StartTransaction For Each id As ObjectId In db.GetViewports(False) Dim vp As Viewport = id.GetObject(OpenMode.ForWrite) vp.FreezeLayersInViewport(LayerIds(db).GetEnumerator) Next trx.Commit() End Using End Sub Private Function LayerIds(ByVal db As Database) As ObjectIdCollection Dim layIds As New ObjectIdCollection() layIds.Add(db.LayerZero) Return layIds End Function
Hi Jeff,
I tried using your code but it didn't freeze the selected layer or any layers in the existing viewport in the P1 layout. I'm still trying to understand the whole "db.GetViewports(False)" thing, maybe that's where my problem is.
How do I initialize a layout? Is it layout.initialize() ?
I'm ready to post my entire program if it would help. It's driving me crazy already.
I have only one layout in the drawing. When the code runs, it adds a new layout to the drawing from a template. A dialog pops up and asks which layers they want to see in the new layouts viewport. It also asks which layers they do not want to see in all the other layouts viewports (because a new layer was added and if there are many more layouts it will freeze the selected layers in all the other viewports). When the program is done running, the new layout looks great. It shows the layers I want to see, but, the existing layout still looks lthe same. The layers are all still visible, even though the layer manager says that the layers I told to freeze are frozen. It's like it's just not finishing up and ending the last part.
Here's the code that's supposed to freeze all the selected layers in all the other layouts viewports:
' Freezes the selected layers in all other existing viewport layouts Public Sub freezeOtherLayouts(ByVal pageNumber As Integer, ByVal layersToFreezeLayerIds As ObjectIdCollection) Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim vp As Viewport = Nothing Dim viewPortFound As Boolean Dim freezeVPtrans As Transaction = db.TransactionManager.StartTransaction() Try Dim myBT As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead) For Each btrID As ObjectId In myBT Dim myBTR As BlockTableRecord = btrID.GetObject(OpenMode.ForRead) ' If the block table record is a layout If myBTR.IsLayout Then viewPortFound = False If Not myBTR.Name = "*Model_Space" Then Dim layOut As Layout = myBTR.LayoutId.GetObject(OpenMode.ForRead) ' If the layout is not the new layout If layOut.TabOrder <> pageNumber Then For Each id As ObjectId In myBTR Dim obj As DBObject = id.GetObject(OpenMode.ForWrite) ' If the object is a viewport (there is a model viewport which is found first, we want the second one) If TypeOf obj Is Viewport And viewPortFound = True Then Dim vpref As Viewport = DirectCast(obj, Viewport) ' Selected Viewport for write. vp = freezeVPtrans.GetObject(vpref.ObjectId, OpenMode.ForWrite) Dim lt As LayerTable = freezeVPtrans.GetObject(db.LayerTableId, OpenMode.ForRead) ' Freeze the selected layers in the viewports vp.FreezeLayersInViewport(layersToFreezeLayerIds.GetEnumerator()) ed.Regen() lt.Dispose() End If If TypeOf obj Is Viewport Then viewPortFound = True End If Next End If End If End If Next Catch ed.WriteMessage("Error!") Finally freezeVPtrans.Commit() freezeVPtrans.Dispose() End Try End Sub
Help!
I changed my code to use GetViewports, so it now looks like this:
' Freezes the selected layers in all other existing viewport layouts Public Sub freezeOtherLayouts(ByVal pageNumber As Integer, ByVal layersToFreezeLayerIds As ObjectIdCollection) Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor 'Dim vp As Viewport = Nothing Dim viewPortFound As Boolean Dim freezeVPtrans As Transaction = db.TransactionManager.StartTransaction() Try Dim myBT As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead) For Each btrID As ObjectId In myBT Dim myBTR As BlockTableRecord = btrID.GetObject(OpenMode.ForRead) ' If the block table record is a layout If myBTR.IsLayout Then viewPortFound = False If Not myBTR.Name = "*Model_Space" Then Dim layOut As Layout = myBTR.LayoutId.GetObject(OpenMode.ForRead) ' If the layout is not the new layout If layOut.TabOrder <> pageNumber Then For Each id As ObjectId In db.GetViewports(False) Dim vp As Viewport = id.GetObject(OpenMode.ForWrite) vp.FreezeLayersInViewport(layersToFreezeLayerIds.GetEnumerator) Next End If End If End If Next Catch ed.WriteMessage("Error!") Finally freezeVPtrans.Commit() freezeVPtrans.Dispose() End Try End Sub
It still leaves the layers visible in the first layout, even though according to the layer manager for that viewport, the layer is frozen.
Hi,
I think I've found a solution. I had exactly the same problem. After many hours of serch and try (very frustrating), I found that I have to activate the layout before freezing the layers. So I add this sub to my function:
Public Sub SetCurrentLayoutTab(ByVal LayoutName As String)
Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
Dim acCurDb As Database = acDoc.Database
Using doclock As DocumentLock = acDoc.LockDocument
Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
Try
Dim acLayoutMgr As LayoutManager
acLayoutMgr = LayoutManager.Current
acLayoutMgr.CurrentLayout = LayoutName
acTrans.Commit()
Catch ex As Autodesk.AutoCAD.Runtime.Exception
Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog(ex.Message & vbCr & ex.StackTrace)
acTrans.Abort()
End Try
End Using
End Using
End Sub
Also, this is important to do a regen at the end of your function. Here you will find my complete function (sub). It is different from yours, so give it a try and give me some feedbacks.
Public Sub FreezeLayerInOtherViewport(ByVal LayerName As String)
Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
Dim acCurDb As Database = acDoc.Database
Using doclock As DocumentLock = acDoc.LockDocument
'' Start a transaction
Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
Dim blockIDs As ObjectIdCollection = New ObjectIdCollection()
Dim acLyrTbl As LayerTable
Dim sLayerNames As String = ""
Dim CVPort As Viewport
acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForRead)
For Each acObjId As ObjectId In acLyrTbl
Dim acLyrTblRec As LayerTableRecord
acLyrTblRec = acTrans.GetObject(acObjId, OpenMode.ForRead)
If acLyrTblRec.Name.ToUpper = LayerName.ToUpper Then
blockIDs.Add(acLyrTblRec.ObjectId)
Exit For
End If
Next
CVPort = DirectCast(acTrans.GetObject(acDoc.Editor.CurrentViewportObjectId, OpenMode.ForRead), Viewport)
Dim layoutDict As DBDictionary = CType(acTrans.GetObject(acCurDb.LayoutDictionaryId, OpenMode.ForRead), DBDictionary)
Dim strCurrentLayoutName As String = LayoutManager.Current.CurrentLayout
For Each entry As DBDictionaryEntry In layoutDict
If entry.Key <> "Model" Then
Dim lay As Layout = CType(acTrans.GetObject(entry.Value, OpenMode.ForRead), Layout)
If lay.LayoutName.ToUpper <> strCurrentLayoutName Then
SetCurrentLayoutTab(lay.LayoutName)
Dim nCount As Integer = 0
For Each vpid As ObjectId In lay.GetViewports
nCount = nCount + 1
Dim vp As Viewport = CType(acTrans.GetObject(vpid, OpenMode.ForWrite), Viewport)
If vp.Handle <> CVPort.Handle Then
If nCount > 1 Then
vp.FreezeLayersInViewport(blockIDs.GetEnumerator)
End If
End If
Next
End If
End If
Next
acTrans.Commit()
SetCurrentLayoutTab(strCurrentLayoutName)
acDoc.Editor.Regen()
End Using
End Using
End Sub
Regards,
André
@Jeff wrote:That example should only freeze entites only on layer 0 and only in viewports that have been intialized.
Sorry I was not very clear but thought I put in early reply and guess not but to call Layout.Initialize() for any un-intialized viewports before setting properties.
Going from memory but I believe that will do it.
Hello Andre,
Thank you for your input. I was able to take some of what you did and integrate it into mine.
' Freezes the selected layers in all other existing viewport layouts Public Sub freezeOtherLayouts(ByVal pageNumber As Integer, ByVal layersToFreezeLayerIds As ObjectIdCollection) Dim doc As Document = Application.DocumentManager.MdiActiveDocument Dim db As Database = doc.Database Dim ed As Editor = doc.Editor Dim vp As Viewport = Nothing Dim viewPortFound As Boolean Dim freezeVPtrans As Transaction = Nothing Try freezeVPtrans = db.TransactionManager.StartTransaction() Dim myBT As BlockTable = db.BlockTableId.GetObject(OpenMode.ForRead) For Each btrID As ObjectId In myBT Dim myBTR As BlockTableRecord = btrID.GetObject(OpenMode.ForRead) ' If the block table record is a layout If myBTR.IsLayout Then viewPortFound = False If Not myBTR.Name = "*Model_Space" Then Dim layOut As Layout = myBTR.LayoutId.GetObject(OpenMode.ForRead) 'Dim initId As ObjectId = Nothing 'initId = layOut.Initialize() ' If the layout is not the new layout If layOut.TabOrder <> pageNumber Then SetCurrentLayoutTab(layOut.LayoutName) For Each id As ObjectId In myBTR Dim obj As DBObject = id.GetObject(OpenMode.ForWrite) ' If the object is a viewport (there is a model viewport which is found first, we want the second one) If TypeOf obj Is Viewport And viewPortFound = True Then Dim vpref As Viewport = DirectCast(obj, Viewport) ' Selected Viewport for write. vp = freezeVPtrans.GetObject(vpref.ObjectId, OpenMode.ForWrite) Dim layerTable As LayerTable = freezeVPtrans.GetObject(db.LayerTableId, OpenMode.ForRead) ' Freeze the selected layers in the viewports vp.FreezeLayersInViewport(layersToFreezeLayerIds.GetEnumerator()) 'vp.UpdateDisplay() ed.Regen() layerTable.Dispose() End If If TypeOf obj Is Viewport Then viewPortFound = True End If Next End If End If End If Next Catch ed.WriteMessage("Error!") Finally freezeVPtrans.Commit() ed.Regen() freezeVPtrans.Dispose() End Try End Sub Public Sub SetCurrentLayoutTab(ByVal LayoutName As String) Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument Dim acCurDb As Database = acDoc.Database Using doclock As DocumentLock = acDoc.LockDocument Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction() Try Dim acLayoutMgr As LayoutManager acLayoutMgr = LayoutManager.Current acLayoutMgr.CurrentLayout = LayoutName acTrans.Commit() Catch ex As Autodesk.AutoCAD.Runtime.Exception Application.ShowAlertDialog(ex.Message & vbCr & ex.StackTrace) acTrans.Abort() End Try End Using End Using End Sub
I used your SetCurrentLayoutTab sub, and referenced it inside of the layout loop. That did the trick and allowed the selected layers to be frozen in the other layout viewports.
Thank you very much!
Mark
Hello Mark,
I'm glad to help you, the only annoying thing is you can see layout change, so the screen is flipping but it is very fast on my computer.
Regards,
André
I have the same problem and despite trolling the forums and trying all the suggestions here, no success. I am generating a series of Layouts, then iterating all Layouts to set current (to initialise), then VP Freezing layers. The layers are correctly frozen in the layer dialog box, but continue to display. Regen/Regenall has no effect. Save, Close and re-Open the drawing and the display is correct. I haven't included code as it is mostly as per this thread. Is there something else? Regards, Dale
Dale, I wrote wrong expression in my first post on this thread,
Try add at the end of code instead
ed.UpdateTiledViewportsFromDatabase()
Hi Dale,
Another thing I found was that AutoCad 2010 is a bit buggy. Make sure you have the latest service pack. I downloaded service pack 2 and it fixed the layer visibility issue. You can tell the service pack you have by going to Help > About. In the top left mine says version 3 (which in AutoCad land means service pack 2).
Thanks for the replies. I tried ed.UpdateTiledViewportsFromDatabase(); everywhere but it resulted in errors. As it refers to TiledViewports, it seems that it is not applicable to floating viewports, but I am not sure. I am using AutoCAD 2013 SP1 so it is not an old bug. As I say, it is all correct, and re-opens with the correct display, but needs to be refreshed somehow. Regards, Dale
Hi
Though you have mentioned that code is all most same, I would like to request you to provide non confidential code sample with using which we can reproduce the issue at our end. Also, attach a simple non confidential drawing file against which we can reproduce the issue.