TheSwamp
Code Red => .NET => Topic started by: mkweaver on May 28, 2008, 12:47:15 AM
-
I have programmed for years with lisp, visual lisp, and vba for years, but am just now getting started using vb.net in autocad (as will be obvious by the code and the question).
I am trying to find the annotation scale of all viewports in the drawing. The code below selects all viewports in the drawing and cycles through them, allowing me to get the properties of each one, however, I'm having a hard time excluding the paperspace viewport. I thought I could identify it as the viewport with the blockname property = "*Paper_Space", but that didn't work.
Suggestions are appreciated.
Mike
<CommandMethod("SSVP")> _
Public Sub SSVP()
Dim myDB As DatabaseServices.Database
Dim myDWG As ApplicationServices.Document
Dim myEd As EditorInput.Editor
Dim myPSR As EditorInput.PromptSelectionResult
Dim mySS As EditorInput.SelectionSet
Dim mySelectedObject As EditorInput.SelectedObject
Dim myFilter(0) As DatabaseServices.TypedValue
Dim iIndex As Integer
Dim myTransMan As TransactionManager
Dim myTrans As Transaction
Dim myViewport As Viewport
myFilter(0) = New DatabaseServices.TypedValue( _
DatabaseServices.DxfCode.Start, "VIEWPORT")
Dim mySF As New EditorInput.SelectionFilter(myFilter)
Dim myAcadEnt As DatabaseServices.Entity
myDWG = ApplicationServices.Application.DocumentManager.MdiActiveDocument
myDB = myDWG.Database
myEd = myDWG.Editor
myPSR = myEd.SelectAll(mySF)
mySS = myPSR.Value
iIndex = mySS.Count - 1
myTransMan = myDWG.TransactionManager
myTrans = myTransMan.StartTransaction
For iIndex = 0 To mySS.Count - 1
mySelectedObject = myPSR.Value.Item(iIndex)
myAcadEnt = mySelectedObject.ObjectId.GetObject(DatabaseServices.OpenMode.ForRead)
myViewport = mySelectedObject.ObjectId.GetObject(OpenMode.ForRead)
If myViewport.BlockName = "*Paper_Space" Then
Debug.Print("Paperspace viewport")
Else
Debug.Print(myViewport.AnnotationScale.Scale)
End If
Next
myTrans.Dispose()
myTransMan.Dispose()
MsgBox(mySS.Count)
End Sub
-
Wow, that’s a dang good question. I really don’t know how to differentiate between the two.
Suggestions, assume that the first viewport that is owned by each layout is not the one you want.
Put all the viewports that you want to test on specific layer. Here is an example of the former you can test.
sorry it's in C#... Maybe someone else has a better idea. :mrgreen:
#region #Using delarations
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Threading;
using System.Globalization;
using System.Reflection;
using System.Drawing.Imaging;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.LayerManager;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Colors;
//using AcExtensions; mine
using AcAp = Autodesk.AutoCAD.ApplicationServices;
using AcEd = Autodesk.AutoCAD.EditorInput;
using AcGe = Autodesk.AutoCAD.Geometry;
using AcRx = Autodesk.AutoCAD.Runtime;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcWd = Autodesk.AutoCAD.Windows;
#endregion
[assembly: CommandClass(typeof(ExecMethod.Commands))]
namespace ExecMethod
{
public class Commands
{
[CommandMethod("doit")]
public static void doit()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
try
{
foreach (AcDb.Viewport vp in doitsub())
{
ed.WriteMessage("\n" + vp.AnnotationScale.Scale.ToString());
}
}
catch (SystemException ex)
{
ed.WriteMessage("\n" + ex.Message);
ed.WriteMessage("\n" + ex.StackTrace);
}
}
public static IEnumerable<AcDb.Viewport> doitsub()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
List<AcDb.Viewport> head = new List<AcDb.Viewport>();
List<AcDb.Viewport> tail = new List<AcDb.Viewport>();
try
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
ObjectId ldid = db.LayoutDictionaryId;
DBDictionary ld = tr.GetObject(ldid, OpenMode.ForRead, false) as DBDictionary;
foreach (DBDictionaryEntry de in ld)
{
Layout layout = tr.GetObject(de.Value, OpenMode.ForRead, false) as Layout;
BlockTableRecord bt = tr.GetObject
(layout.BlockTableRecordId, OpenMode.ForRead, false) as BlockTableRecord;
foreach (ObjectId eid in bt)
{
DBObject dbo = tr.GetObject(eid, OpenMode.ForRead, false);
if (dbo is AcDb.Viewport)
{
AcDb.Viewport vp = dbo as AcDb.Viewport;
if (vp.BlockName != "*Model_Space")
tail.Add(vp);
}
}
if (tail.Count != 0)
{
tail.RemoveAt(0);
head.AddRange(tail);
tail.Clear();
}
}
tr.Commit();
}
}
catch (SystemException ex)
{
ed.WriteMessage("\n" + ex.Message);
ed.WriteMessage("\n" + ex.StackTrace);
}
return head;
}
-
To see if the current viewport is the paperspace viewport itself (ie in paperspace and not in a viewport):
Document doc = acadApp.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
if (db.PaperSpaceVportId != ed.CurrentViewportObjectId)
// not in paperspace viewport
You can also look up the help on AcDbLayout::getViewportArray and note what it says about the first element.
This is wrapped by the GetViewports() method of the Layout object.
Cheers,
Glenn.
-
...You can also look up the help on AcDbLayout::getViewportArray and note what it says about the first element.
This is wrapped by the GetViewports() method of the Layout object...
Thanks Glenn :kewl:
my assumption was right. “The first ID in the list will be the paperspace viewport.”
A version using Layout::GetViewports())
[assembly: CommandClass(typeof(ExecMethod.Commands))]
namespace ExecMethod
{
public class Commands
{
[CommandMethod("doit")]
public static void doit()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
try
{
foreach (AcDb.Viewport vp in doitsub())
{
ed.WriteMessage("\n" + vp.AnnotationScale.Scale.ToString());
}
}
catch (SystemException ex)
{
ed.WriteMessage("\n" + ex.Message);
ed.WriteMessage("\n" + ex.StackTrace);
}
}
public static IEnumerable<AcDb.Viewport> doitsub()
{
Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;
List<AcDb.Viewport> head = new List<AcDb.Viewport>();
List<AcDb.Viewport> tail = new List<AcDb.Viewport>();
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
ObjectId ldid = db.LayoutDictionaryId;
DBDictionary ld = tr.GetObject(ldid, OpenMode.ForRead, false) as DBDictionary;
foreach (DBDictionaryEntry de in ld)
{
Layout layout = tr.GetObject(de.Value, OpenMode.ForRead, false) as Layout;
foreach (ObjectId eid in layout.GetViewports())
{
AcDb.Viewport vp = tr.GetObject(eid, OpenMode.ForRead, false) as AcDb.Viewport;
if (vp.BlockName != "*Model_Space")
tail.Add(vp);
}
if (tail.Count != 0)
{
tail.RemoveAt(0);
head.AddRange(tail);
tail.Clear();
}
}
tr.Commit();
}
return head;
}
}
}
-
Dan,
There is also a Database::GetViewports(bool)...try that as it would allow you to ditch cycling the layouts and opening each one looking for modelspace...
-
Dan,
There is also a Database::GetViewports(bool)...try that as it would allow you to ditch cycling the layouts and opening each one looking for modelspace...
Ha! Where did that come from :lol:
new code
[assembly: CommandClass(typeof(ExecMethod.Commands))]
namespace ExecMethod
{
public class Commands
{
[CommandMethod("doit")]
public static void doit()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
try
{
foreach (AcDb.Viewport vp in doitsub())
{
ed.WriteMessage("\n" + vp.AnnotationScale.Scale.ToString());
}
}
catch (SystemException ex)
{
ed.WriteMessage("\n" + ex.Message);
ed.WriteMessage("\n" + ex.StackTrace);
}
}
public static IEnumerable<AcDb.Viewport> doitsub()
{
Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;
List<AcDb.Viewport> head = new List<AcDb.Viewport>();
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
ObjectIdCollection vpids = db.GetViewports(false);
foreach (ObjectId vpid in vpids)
{
head.Add((AcDb.Viewport)tr.GetObject(vpid, OpenMode.ForRead, false));
}
tr.Commit();
}
return head;
}
}
}
-
Mike, any chance we can get you to convert to C#? :-D
-
Maybe a better way...
[assembly: CommandClass(typeof(ExecMethod.Commands))]
namespace ExecMethod
{
public class Commands
{
[CommandMethod("doit")]
public static void doit()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
try
{
foreach (AnnotationScale annoScale in doitsub())
{
StringBuilder sb = new StringBuilder();
sb.Append("\n");
sb.Append("(");
sb.Append(annoScale.Name);
sb.Append(" , ");
sb.Append(annoScale.Scale.ToString());
sb.Append(")");
ed.WriteMessage(sb.ToString());
}
}
catch (SystemException ex)
{
ed.WriteMessage("\n" + ex.Message);
ed.WriteMessage("\n" + ex.StackTrace);
}
}
public static IEnumerable<AnnotationScale> doitsub()
{
Editor editor = Application.DocumentManager.MdiActiveDocument.Editor;
List<AnnotationScale> head = new List<AnnotationScale>();
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (ObjectId vpid in db.GetViewports(false))
{
AcDb.Viewport vp = tr.GetObject(vpid, OpenMode.ForRead, false) as AcDb.Viewport;
if (vp.AnnotationScale != null)
head.Add(vp.AnnotationScale);
}
}
return head;
}
}
}
-
Much tighter :)
-
First, thanks for all the help. It is really helpful.
This is what I have now, and it works, as far as it goes.
Public Shared Function doitsub() As IEnumerable(Of Autodesk.AutoCAD.DatabaseServices.Viewport)
Dim Editor As Autodesk.AutoCAD.EditorInput.Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
Dim head As New List(Of Autodesk.AutoCAD.DatabaseServices.Viewport)()
Dim db As Database = HostApplicationServices.WorkingDatabase
Using tr As Transaction = db.TransactionManager.StartTransaction()
Dim vpids As ObjectIdCollection = db.GetViewports(False)
For Each vpid As ObjectId In vpids
head.Add(DirectCast(tr.GetObject(vpid, OpenMode.ForRead, False), Autodesk.AutoCAD.DatabaseServices.Viewport))
Next
tr.Commit()
End Using
Return head
End Function
<CommandMethod("doit")> _
Public Shared Sub doit()
Dim Editor As Autodesk.AutoCAD.EditorInput.Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
Try
For Each vp As Autodesk.AutoCAD.DatabaseServices.Viewport In doitsub()
Editor.WriteMessage("" & Chr(10) & "" + vp.AnnotationScale.Scale.ToString())
Next
Catch ex As SystemException
Editor.WriteMessage("" & Chr(10) & "" + ex.Message)
Editor.WriteMessage("" & Chr(10) & "" + ex.StackTrace)
End Try
End Sub
Now a couple of questions. I know that to open an object for read I must wrap the read in a transaction. So, I see that we've done that in DoitSub, but then when we get to Doit, I don't have to wrap that (the code that gets the viewport properties) in a transaction? I mean, I can see that I don't - it works, but I would have expected a transaction here:-/
If I now want to modify the annotation scale for the viewport, it looks to me like I must:
- Start another transaction
- cycle through the viewports in Head
- re-opening each for write
- make the modification
- and commit the transaction
Again, thanks for all the examples. I'm seeing "slight of code" here that I didn't imagine possible.
Testing continues...
-
Mike, any chance we can get you to convert to C#? :-D
I spent some time with C and C++ years ago (turbo C 3, I think) and was, shall we say, overwhelmed. I generated a couple of simple console apps, but didn't ever really get proficient. Because of this, and the time I have with VB/VBA I assumed that I would come up to speed more quickly with VB.net than I would with C#.
Are there things I could do with C# that I won't be able to do with VB?
-
And now another question.
I'm now trying to syncronize the viewport annotation scale with the viewport zoom scale factor. I have the following code:
<CommandMethod("Doit2")> Public Shared Sub Doit2()
Dim Editor As Autodesk.AutoCAD.EditorInput.Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim vp As Autodesk.AutoCAD.DatabaseServices.Viewport
Using tr As Transaction = db.TransactionManager.StartTransaction()
Try
For Each vpid As ObjectId In db.GetViewports(False)
vp = tr.GetObject(vpid, OpenMode.ForWrite, False, True)
[color=red]vp.AnnotationScale.Scale = vp.CustomScale[/color]
Editor.WriteMessage("" & Chr(10) & "" + vp.AnnotationScale.Scale.ToString())
Next
Catch ex As SystemException
Editor.WriteMessage("" & Chr(10) & "" + ex.Message)
Editor.WriteMessage("" & Chr(10) & "" + ex.StackTrace)
End Try
tr.commit
End Using
End Sub
But it fails, telling me the scale property of the annotationscale is read only. The documentation (objectarx for acad 2009) says otherwise:
Autodesk.AutoCAD.DatabaseServices Namespace > Viewport Class > Viewport Properties > Viewport.AnnotationScale Property
Viewport.AnnotationScale Property
C#
public Autodesk.AutoCAD.DatabaseServices.AnnotationScale AnnotationScale;
Visual Basic
Public Property AnnotationScale() As Autodesk.AutoCAD.DatabaseServices.AnnotationScale
Description
Accesses the AnnotationScale associated with the viewport
Conditions
Read / Write
I know that Acad 2009 has a scale syncronize button, but when working with drawings created prior to 2008 (the advent of annotation scaling) the viewport scale factor will be correct while it's annotation scale defaults to 1. The scale sync button changes the zoom scale factor for the viewport :x Not the desired behavior.
-
A suggestion:
In autocad, I generally won't pass around a container of opened objects like you're returning from doitsub.
Instead, pass around an ObjectIdCollection, as this has less overhead and means that you only open objects for read or write when you need them.
-
A suggestion:
In autocad, I generally won't pass around a container of opened objects like you're returning from doitsub.
Instead, pass around an ObjectIdCollection, as this has less overhead and means that you only open objects for read or write when you need them.
I hadn't considered that the viewport objects returned by doitsub remained open, I thought committing the transaction would close them. In this case, then, is there any clean-up that needs to be done with those open objects?
In this case, where I am first reading the scale then modifying it, it sounds like a good idea to use a collection of objectid.
-
...
If I now want to modify the annotation scale for the viewport, it looks to me like I must:
- Start another transaction
- cycle through the viewports in Head
- re-opening each for write
- make the modification
- and commit the transaction
Again, thanks for all the examples. I'm seeing "slight of code" here that I didn't imagine possible.
Testing continues...
Exactly, You could write a class to handle all the methods you need to get/modify the properties.
You could even write a custom struct or class to store your data.
Here are some very quickly thrown together methods that dont necessarily represent best programming practices, but might give you a few ideas.
#region #Using delarations
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using System.Threading;
using System.Globalization;
using System.Reflection;
using System.Drawing.Imaging;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Windows;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.LayerManager;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Colors;
//using AcExtensions; mine
using AcAp = Autodesk.AutoCAD.ApplicationServices;
using AcEd = Autodesk.AutoCAD.EditorInput;
using AcGe = Autodesk.AutoCAD.Geometry;
using AcRx = Autodesk.AutoCAD.Runtime;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcWd = Autodesk.AutoCAD.Windows;
#endregion
[assembly: CommandClass(typeof(ExecMethod.Commands))]
namespace ExecMethod
{
public class Commands
{
[CommandMethod("doitOnce")]
public static void doitOnce()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
try
{
List<AnnotationScale> scalelist = (List<AnnotationScale>)getScaleList();
AnnotationScale current = scalelist[1];
Set("Layout1", current);
}
catch (SystemException ex)
{
ed.WriteMessage("\n" + ex.Message);
ed.WriteMessage("\n" + ex.StackTrace);
}
}
[CommandMethod("doitAll")]
public static void doitAll()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
try
{
AnnoDataList annoList = (AnnoDataList)Get();
List<AnnotationScale> scalelist = (List<AnnotationScale>)getScaleList();
AnnotationScale current = scalelist[1];
for (int i = 0; i < annoList.Count; i++)
ed.WriteMessage("\nold" + annoList[i].ToString());
for (int i = 0; i < annoList.Count; i++)
annoList[i].AnnotationScale = current;
Set(annoList);
annoList = (AnnoDataList)Get();
for (int i = 0; i < annoList.Count; i++)
ed.WriteMessage("\nnew" + annoList[i].ToString());
}
catch (SystemException ex)
{
ed.WriteMessage("\n" + ex.Message);
ed.WriteMessage("\n" + ex.StackTrace);
}
}
public static void Set(string LayoutName, AnnotationScale annoScale)
{
LayoutManager manager = LayoutManager.Current;
Database db = HostApplicationServices.WorkingDatabase;
ObjectId layoutId = manager.GetLayoutId(LayoutName);
if (layoutId.IsNull)
return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
AcDb.Layout layout = tr.GetObject(layoutId, OpenMode.ForRead, false) as AcDb.Layout;
ObjectIdCollection ids = layout.GetViewports();
if (ids.Count > 0)
{
ids.RemoveAt(0);
for (int i = 0; i < ids.Count; i++)
{
AcDb.Viewport vp = tr.GetObject(ids[i], OpenMode.ForWrite, false) as AcDb.Viewport;
vp.AnnotationScale = annoScale;
}
}
tr.Commit();
}
}
public static void Set(AnnoData annoData)
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
AcDb.Viewport vp = tr.GetObject(annoData.m_viewPortId, OpenMode.ForWrite, false) as AcDb.Viewport;
vp.AnnotationScale = annoData.m_AnnotationScale;
tr.Commit();
}
}
public static void Set(IEnumerable<AnnoData> annoDataList)
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (AnnoData data in annoDataList)
{
AcDb.Viewport vp = tr.GetObject(data.m_viewPortId, OpenMode.ForWrite, false) as AcDb.Viewport;
vp.AnnotationScale = data.m_AnnotationScale;
}
tr.Commit();
}
}
public static IEnumerable<AnnoData> Get()
{
AnnoDataList head = new AnnoDataList();
AnnoDataList tail = new AnnoDataList();
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
ObjectId ldid = db.LayoutDictionaryId;
DBDictionary ld = tr.GetObject(ldid, OpenMode.ForRead, false) as DBDictionary;
foreach (DBDictionaryEntry de in ld)
{
Layout layout = tr.GetObject(de.Value, OpenMode.ForRead, false) as Layout;
if (layout.LayoutName != "Model")
{
foreach (ObjectId eid in layout.GetViewports())
{
AcDb.Viewport vp = tr.GetObject(eid, OpenMode.ForRead, false) as AcDb.Viewport;
if (vp.BlockName != "*Model_Space")
tail.Add(new AnnoData(layout.LayoutName, vp.ObjectId, vp.AnnotationScale));
}
if (tail.Count != 0)
{
tail.RemoveAt(0);
head.AddRange(tail);
tail.Clear();
}
}
}
tr.Commit();
}
return head;
}
//KWB
static public IEnumerable<AnnotationScale> getScaleList()
{
List<AnnotationScale> annolist = new List<AnnotationScale>();
ObjectContextCollection occ = HostApplicationServices.WorkingDatabase.
ObjectContextManager.GetContextCollection("ACDB_ANNOTATIONSCALES");
foreach (AnnotationScale a in occ)
annolist.Add(a);
return annolist;
}
}
//
public class AnnoDataList : List<AnnoData>
{
public AnnoDataList() { }
}
public class AnnoData
{
internal string m_LayoutName;
internal ObjectId m_viewPortId;
internal AnnotationScale m_AnnotationScale;
public AnnoData(string layout, ObjectId viewPortId, AnnotationScale annotationScale)
{
m_LayoutName = layout;
m_viewPortId = viewPortId;
m_AnnotationScale = annotationScale;
}
public string LayoutName
{
get { return this.m_LayoutName; }
set { this.m_LayoutName = value; }
}
public ObjectId ViewPortId
{
get { return this.m_viewPortId; }
set { this.m_viewPortId = value; }
}
public AnnotationScale AnnotationScale
{
get { return this.m_AnnotationScale; }
set { this.m_AnnotationScale = value; }
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append("(");
sb.Append(this.m_LayoutName);
sb.Append(" , ");
sb.Append(this.m_viewPortId.ToString());
sb.Append(" , ");
sb.Append(this.AnnotationScale.Scale.ToString());
sb.Append(")");
return sb.ToString();
}
}
}
-
Mike, any chance we can get you to convert to C#? :-D
I spent some time with C and C++ years ago (turbo C 3, I think) and was, shall we say, overwhelmed. I generated a couple of simple console apps, but didn't ever really get proficient. Because of this, and the time I have with VB/VBA I assumed that I would come up to speed more quickly with VB.net than I would with C#.
Are there things I could do with C# that I won't be able to do with VB?
It’s just my personal attempt to convert .NETers over to a C style language, because I can’t read VB.
-
Ditto that.
-
nice example Daniel.
[< .. >
It’s just my personal attempt to convert .NETers over to a C style language, because I can’t read VB.
:-D
I can read it, but my therapist has advised me not to. :angel:
-
I am trying (desperately) to build a collection of viewports from a layout...
Why do I get a "FileNotFoundException was unhandled" alert when I try to execute this code?
I put "Public Shared Function doitsub" and "Public Shared Sub doit" into my form as a function and public sub respectively...and get the previously described File Not Found Error.
This problem is plaguing me, I think I may be at a breakthrough point in my programming if I can get this problem figured out.
First, thanks for all the help. It is really helpful.
This is what I have now, and it works, as far as it goes.
Public Shared Function doitsub() As IEnumerable(Of Autodesk.AutoCAD.DatabaseServices.Viewport)
Dim Editor As Autodesk.AutoCAD.EditorInput.Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
Dim head As New List(Of Autodesk.AutoCAD.DatabaseServices.Viewport)()
Dim db As Database = HostApplicationServices.WorkingDatabase
Using tr As Transaction = db.TransactionManager.StartTransaction()
Dim vpids As ObjectIdCollection = db.GetViewports(False)
For Each vpid As ObjectId In vpids
head.Add(DirectCast(tr.GetObject(vpid, OpenMode.ForRead, False), Autodesk.AutoCAD.DatabaseServices.Viewport))
Next
tr.Commit()
End Using
Return head
End Function
<CommandMethod("doit")> _
Public Shared Sub doit()
Dim Editor As Autodesk.AutoCAD.EditorInput.Editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor
Try
For Each vp As Autodesk.AutoCAD.DatabaseServices.Viewport In doitsub()
Editor.WriteMessage("" & Chr(10) & "" + vp.AnnotationScale.Scale.ToString())
Next
Catch ex As SystemException
Editor.WriteMessage("" & Chr(10) & "" + ex.Message)
Editor.WriteMessage("" & Chr(10) & "" + ex.StackTrace)
End Try
End Sub
Now a couple of questions. I know that to open an object for read I must wrap the read in a transaction. So, I see that we've done that in DoitSub, but then when we get to Doit, I don't have to wrap that (the code that gets the viewport properties) in a transaction? I mean, I can see that I don't - it works, but I would have expected a transaction here:-/
If I now want to modify the annotation scale for the viewport, it looks to me like I must:
- Start another transaction
- cycle through the viewports in Head
- re-opening each for write
- make the modification
- and commit the transaction
Again, thanks for all the examples. I'm seeing "slight of code" here that I didn't imagine possible.
Testing continues...
-
I can't see anything in that code that would cause that error
maybe you can post your solution so we can take a look?
-
Hows my VB :lol:
<CommandMethod("doit")> _
Public Shared Sub doit()
Dim editor As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim db As Database = HostApplicationServices.WorkingDatabase
Try
Using tr As Transaction = db.TransactionManager.StartTransaction
Dim ldid As ObjectId = db.LayoutDictionaryId
Dim ld As DBDictionary = TryCast(tr.GetObject(ldid, OpenMode.ForRead, False),DBDictionary)
Dim de As DBDictionaryEntry
For Each de In ld
Dim layout As Layout = TryCast(tr.GetObject(de.Value, OpenMode.ForRead, False),Layout)
Dim ids As ObjectIdCollection = layout.GetViewports
If (ids.Count > 0) Then
Dim i As Integer
For i = 1 To ids.Count - 1
Dim vp As Viewport = TryCast(tr.GetObject(ids.Item(i), OpenMode.ForRead, False),Viewport)
If (Not vp Is Nothing) Then
editor.WriteMessage(ChrW(10) & "Layout {0} , VP#{1} Width = {2}",
New Object() { layout.LayoutName, i, vp.Width })
End If
Next i
End If
Next
tr.Commit
End Using
Catch ex As Exception
editor.WriteMessage(ex.StackTrace)
End Try
End Sub
-
I agree with Dan - the FileNotFoundException is being thrown from somewhere else in your code.
-
Hows my VB :lol:
<CommandMethod("doit")> _
Public Shared Sub doit()
Dim editor As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim db As Database = HostApplicationServices.WorkingDatabase
// ..>>
<<..//
End Sub
Dim humour ??
-
I've been known to dim on occasion