Extracting XML data from drawings using a new .NET API in AutoCAD 2009
This post is the latest in the series of closer looks at the new APIs in AutoCAD 2009. It covers the Data Extraction API, a new .NET API allowing you to drive the Data Extraction feature inside AutoCAD.
There is a very thorough C# sample included on the ObjectARX SDK (under samples/dotNet/DataExtraction), so I thought I'd focus on a much simpler example where we extract data from a single drawing.
Here's the C# code:
using System.Collections.Generic;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DataExtraction;
namespace DataExtraction
{
public class Commands
{
const string path =
@"c:\Program Files\Autodesk\AutoCAD 2009\Sample\";
const string fileName =
"Visualization - Aerial.dwg";
const string outputXmlFile =
@"c:\temp\data-extract.xml";
[CommandMethod("extd")]
public void extractData()
{
if (!System.IO.File.Exists(path + fileName))
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Editor ed =
doc.Editor;
ed.WriteMessage("\nFile does not exist.");
return;
}
// Create some settings for the extraction
IDxExtractionSettings es =
new DxExtractionSettings();
IDxDrawingDataExtractor de =
es.DrawingDataExtractor;
de.Settings.ExtractFlags =
ExtractFlags.ModelSpaceOnly |
ExtractFlags.XrefDependent |
ExtractFlags.Nested;
// Add a single file to the settings
IDxFileReference fr =
new DxFileReference(path, path + fileName);
de.Settings.DrawingList.AddFile(fr);
// Scan the drawing for object types & their properties
de.DiscoverTypesAndProperties(path);
List<IDxTypeDescriptor> types =
de.DiscoveredTypesAndProperties;
// Select all the types and properties for extraction
// by adding them one-by-one to these two lists
List<string> selTypes = new List<string>();
List<string> selProps = new List<string>();
foreach (IDxTypeDescriptor type in types)
{
selTypes.Add(type.GlobalName);
foreach (
IDxPropertyDescriptor pr in type.Properties
)
{
if (!selProps.Contains(pr.GlobalName))
selProps.Add(pr.GlobalName);
}
}
// Pass this information to the extractor
de.Settings.SetSelectedTypesAndProperties(
types,
selTypes,
selProps
);
// Now perform the extraction itself
de.ExtractData(path);
// Get the results of the extraction
System.Data.DataTable dataTable =
de.ExtractedData;
// Output the extracted data to an XML file
if (dataTable.Rows.Count > 0)
{
dataTable.TableName = "My_Data_Extract";
dataTable.WriteXml(outputXmlFile);
}
}
}
}
Here are the first few objects from the output file found in c:\temp\data-extract.xml after running the EXTD command:
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<My_Data_Extract>
<AcDxHandleData>183</AcDxHandleData>
<Layer>0</Layer>
<LinetypeScale>1</LinetypeScale>
<PlotStyleName>ByLayer</PlotStyleName>
<LineWeight>ByLayer</LineWeight>
<Material>Material 3</Material>
<Linetype>ByLayer</Linetype>
<Color>ByLayer</Color>
<AcDxObjectTypeName>3D Solid</AcDxObjectTypeName>
<AcDxObjectTypeGlobalName>
Autodesk.AutoCAD.DatabaseServices.Solid3d
</AcDxObjectTypeGlobalName>
<AcDxDwgSummaryDwgName>
Visualization - Aerial.dwg
</AcDxDwgSummaryDwgName>
<AcDxDwgSummaryDwgLocation>
c:\Program Files\Autodesk\AutoCAD 2009\Sample
</AcDxDwgSummaryDwgLocation>
<AcDxDwgSummaryDwgSize>472480</AcDxDwgSummaryDwgSize>
<AcDxDwgSummaryDwgCreated>
2007-01-03T00:44:20+01:00
</AcDxDwgSummaryDwgCreated>
<AcDxDwgSummaryDwgModified>
2007-01-03T00:44:20+01:00
</AcDxDwgSummaryDwgModified>
<AcDxDwgSummaryDwgAccessed>
2008-03-03T11:40:53.796875+01:00
</AcDxDwgSummaryDwgAccessed>
<AcDxDwgSummaryDwgTitle />
<AcDxDwgSummaryDwgSubject />
<AcDxDwgSummaryDwgAuthor />
<AcDxDwgSummaryDwgKeywords />
<AcDxDwgSummaryDwgComments />
<AcDxDwgSummaryDwgHyperLinkBase />
<AcDxDwgSummaryDwgLastSavedBy>
thompsl
</AcDxDwgSummaryDwgLastSavedBy>
<AcDxDwgSummaryDwgRevisionNumber />
<AcDxDwgSummaryDwgTotalEditingTime>
1179
</AcDxDwgSummaryDwgTotalEditingTime>
<AcDxEntityHyperlink />
</My_Data_Extract>
<My_Data_Extract>
<AcDxHandleData>191</AcDxHandleData>
<Layer>0</Layer>
<LinetypeScale>1</LinetypeScale>
<PlotStyleName>ByLayer</PlotStyleName>
<LineWeight>ByLayer</LineWeight>
<Material>Material 3</Material>
<Linetype>ByLayer</Linetype>
<Color>ByLayer</Color>
<AcDxObjectTypeName>3D Solid</AcDxObjectTypeName>
<AcDxObjectTypeGlobalName>
Autodesk.AutoCAD.DatabaseServices.Solid3d
</AcDxObjectTypeGlobalName>
<AcDxDwgSummaryDwgName>
Visualization - Aerial.dwg
</AcDxDwgSummaryDwgName>
<AcDxDwgSummaryDwgLocation>
c:\Program Files\Autodesk\AutoCAD 2009\Sample
</AcDxDwgSummaryDwgLocation>
<AcDxDwgSummaryDwgSize>472480</AcDxDwgSummaryDwgSize>
<AcDxDwgSummaryDwgCreated>
2007-01-03T00:44:20+01:00
</AcDxDwgSummaryDwgCreated>
<AcDxDwgSummaryDwgModified>
2007-01-03T00:44:20+01:00
</AcDxDwgSummaryDwgModified>
<AcDxDwgSummaryDwgAccessed>
2008-03-03T11:40:53.796875+01:00
</AcDxDwgSummaryDwgAccessed>
<AcDxDwgSummaryDwgTitle />
<AcDxDwgSummaryDwgSubject />
<AcDxDwgSummaryDwgAuthor />
<AcDxDwgSummaryDwgKeywords />
<AcDxDwgSummaryDwgComments />
<AcDxDwgSummaryDwgHyperLinkBase />
<AcDxDwgSummaryDwgLastSavedBy>
thompsl
</AcDxDwgSummaryDwgLastSavedBy>
<AcDxDwgSummaryDwgRevisionNumber />
<AcDxDwgSummaryDwgTotalEditingTime>
1179
</AcDxDwgSummaryDwgTotalEditingTime>
<AcDxEntityHyperlink />
</My_Data_Extract>
<!-- Stuff deleted from the XML output -->
<!-- ... -->
</DocumentElement>
April 7, 2008 in AutoCAD, AutoCAD .NET, Object properties | Permalink | Comments (7) | TrackBack
Modifying the color, linetype and lineweight of an AutoCAD entity using standard dialogs from .NET
In the last post we saw code to display and use AutoCAD's built-in colour, linetype and lineweight dialogs. In this post we extend that by using each of them in sequence to display various properties of an entity, allowing the user to modify them.
While this is slightly more "real world" than the last post, it doesn't really make sense to implement a command such as the one below (the property palette is much better, for instance :-). The main purpose is to show how to set the initial values in the various dialogs and afterwards to make use of the values the user selects.
Here's the C# code:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Windows;
namespace EntityProperties
{
public class Commands
{
[CommandMethod("SPE")]
public void SetPropertiesOnEntity()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityResult per =
ed.GetEntity(
"\nSelect entity to modify: "
);
if (per.Status != PromptStatus.OK)
return;
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
Entity ent =
(Entity)
tr.GetObject(
per.ObjectId,
OpenMode.ForRead
);
ColorDialog cd = new ColorDialog();
cd.Color = ent.Color;
System.Windows.Forms.DialogResult dr;
dr = cd.ShowDialog();
if (dr != System.Windows.Forms.DialogResult.OK)
return;
LinetypeDialog ltd = new LinetypeDialog();
ltd.Linetype = ent.LinetypeId;
dr = ltd.ShowDialog();
if (dr != System.Windows.Forms.DialogResult.OK)
return;
LineWeightDialog lwd = new LineWeightDialog();
lwd.LineWeight = ent.LineWeight;
dr = lwd.ShowDialog();
if (dr != System.Windows.Forms.DialogResult.OK)
return;
ent.UpgradeOpen();
if (ent.Color != cd.Color)
ent.Color = cd.Color;
if (ent.LinetypeId != ltd.Linetype)
ent.LinetypeId = ltd.Linetype;
if (ent.LineWeight != lwd.LineWeight)
ent.LineWeight = lwd.LineWeight;
tr.Commit();
}
}
}
}
Notice that we "return" from the code in a number of places, should the user cancel one of the dialogs. This is perfectly safe, as we're "using" the transaction object, and once it leaves scope it will automatically be disposed (and therefore aborted).
Running the SPE command will display in sequence the dialogs shown in the previous post, and use the user's input to change the state of the selected entity.
February 12, 2008 in AutoCAD, AutoCAD .NET, Object properties, User interface | Permalink | Comments (0) | TrackBack
Using standard AutoCAD dialogs to select colors, linetypes and lineweights with .NET
AutoCAD has a number of handy dialogs available in the "Autodesk.AutoCAD.Windows" namespace. The following code shows how to use three, in particular: ColorDialog, LinetypeDialog and LineWeightDialog. These three classes allow you to very easily implement user-interfaces selecting their corresponding properties.
Here's the C# code:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Windows;
namespace AutoCADDialogs
{
public class Commands
{
[CommandMethod("CDL")]
public void ShowColorDialog()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
ColorDialog cd = new ColorDialog();
System.Windows.Forms.DialogResult dr =
cd.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
ed.WriteMessage(
"\nColor selected: " +
cd.Color.ToString()
);
}
}
[CommandMethod("LTDL")]
public void ShowLinetypeDialog()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
LinetypeDialog ltd = new LinetypeDialog();
System.Windows.Forms.DialogResult dr =
ltd.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
ed.WriteMessage(
"\nLinetype selected: " +
ltd.Linetype.ToString()
);
}
}
[CommandMethod("LWDL")]
public void ShowLineWeightDialog()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
LineWeightDialog lwd = new LineWeightDialog();
System.Windows.Forms.DialogResult dr =
lwd.ShowDialog();
if (dr == System.Windows.Forms.DialogResult.OK)
{
ed.WriteMessage(
"\nLineweight selected: " +
lwd.LineWeight.ToString()
);
}
}
}
}
When we run the CDL command, we have three tabs available:
Here's the dialog shown by the LTDL command:
And the LWDL command:
And here is the command-line output for selecting each of the above items:
Command: CDL
Color selected: 91
Command: CDL
Color selected: 56,166,199
Command: CDL
Color selected: DIC 266
Command: LTDL
Linetype selected: (2130316464)
Command: LWDL
Lineweight selected: LineWeight009
In the next post we'll look at at how to use these dialogs in a more realistic way.
February 8, 2008 in AutoCAD, AutoCAD .NET, Object properties, User interface | Permalink | Comments (6) | TrackBack
Understanding the properties of textual linetype segments in AutoCAD
In the last post we looked at using .NET to define complex linetypes containing text segments. In the post I admitted to not knowing specifics about the properties used to create the text segment in the linetype, and, in the meantime, an old friend took pity on me and came to the rescue. :-)
Mike Kehoe, who I've known for many years since we worked together in the Guildford office of Autodesk UK, sent me some information that I've reproduced below. Mike now works for Micro Concepts Ltd., an Autodesk reseller, developer and training centre. He originally wrote the below description in the R12/12 timeframe, but apparently most of it remains valid; and while it refers to the text string used to define a linetype in a .lin file, these are also mostly properties that are exposed via the .NET interface.
Example: Using Text within a Linetype.
A,.5,-.2,["MK",STANDARD,S=.2,R=0.0,X=-0.1,Y=-.1],-.2The key elements for defining the TEXT are as follows:
"MK" - These are the letters that will be printed along the line.
STANDARD -This tells AutoCAD what text style to apply to the text. NB: This is optional. When no style is defined AutoCAD will use the current text style – TextStyle holds the setting for the current text style.
[Note from Kean: I found the text style to be mandatory when using the .NET interface.]
S=.2 - This is the text scaling factor. However, there are 2 options: (1) when the text style's height is 0, then S defines the height; in this case, 0.2 units; or (2) when the text style's height parameter is non-zero, the height is found by multiplying the text style's height by this number; in this case, the linetype would place the text at 20% of the height defined in the text style.
R=0.0 - This rotates the text relative to the direction of the line; e.g.: 0.0 means there is no rotation. NB: This is optional. When no rotation is defined AutoCAD will assume zero degrees. The default measurement is degrees; NB: you can use r to specify radians, g for grads, or d for degrees, such as R=150g.
[Note from Kean: just like ObjectARX, the .NET interface accepts radians for this value, in SetShapeRotationAt(). A quick reminder: 360 degrees = 2 x PI radians. So you can pass 90 degrees using "System.Math.PI / 2".]
A=0.0 - This rotates the text relative to the x-axis ("A" is short for Absolute); this ensures the text is always oriented in the same direction, no matter the direction of the line. The rotation is always performed within the text baseline and capital height. That's so that you don't get text rotated way off near the orbit of Pluto.
[Note from Kean: to use this style of rotation using .NET, you need to use SetShapeIsUcsOrientedAt() to make sure the rotation is calculated relative to the current UCS rather than the direction of the line.]
X=-0.1 - This setting moves the text just in the x-direction from the linetype definition vertex.
Y=-0.1 – This setting moves the text in the y-direction from the linetype definition vertex.
These 2 settings can be used to center the text in the line. The units are defined from the linetype scale factor, which is stored in system variable LtScale.
Thanks for the information, Mike!
January 11, 2008 in AutoCAD, AutoCAD .NET, Drawing structure, Object properties | Permalink | Comments (0) | TrackBack
Creating a complex AutoCAD linetype containing text using .NET
In my last post we saw some code to create a simple linetype using .NET. As a comment on that post, Mark said:
Kean, i tried you code and it works great and it also got me thinking... is it possible to programmitically add text in as well? I've tried using ltr.SetTextAt(1, "TEST") but so far i've had no luck, any suggestions???
It turned out to be quite a bit more complicated to make a linetype containing text than merely calling SetTextAt() on one of the segments. In order to understand what properties needed setting, I first loaded the HOT_WATER_SUPPLY linetype from acad.lin (using the LINETYPE command):
I then looked at the contents of the linetype table using ArxDbg (the ObjectARX SDK sample that is very helpful for understanding drawing structure). Here's what the SNOOPDB command - defined by the ArxDbg application - showed for the loaded linetype:
From there it was fairly straightforward to determine the code needed to create our own complex linetype containing text segments. I decided to call the new linetype "COLD_WATER_SUPPLY", and have it resemble the original in every way but placing "CW" in the middle segment, rather than "HW" (with the descriptions updated to match, of course). As I've simply copied the properties of an existing linetype, please don't ask me to explain what they all mean. :-)
Here's the C# code:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
namespace Linetype
{
public class Commands
{
[CommandMethod("CCL")]
public void CreateComplexLinetype()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
// We'll use the textstyle table to access
// the "Standard" textstyle for our text
// segment
TextStyleTable tt =
(TextStyleTable)tr.GetObject(
db.TextStyleTableId,
OpenMode.ForRead
);
// Get the linetype table from the drawing
LinetypeTable lt =
(LinetypeTable)tr.GetObject(
db.LinetypeTableId,
OpenMode.ForWrite
);
// Create our new linetype table record...
LinetypeTableRecord ltr =
new LinetypeTableRecord();
// ... and set its properties
ltr.Name = "COLD_WATER_SUPPLY";
ltr.AsciiDescription =
"Cold water supply ---- CW ---- CW ---- CW ----";
ltr.PatternLength = 0.9;
ltr.NumDashes = 3;
// Dash #1
ltr.SetDashLengthAt(0, 0.5);
// Dash #2
ltr.SetDashLengthAt(1, -0.2);
ltr.SetShapeStyleAt(1, tt["Standard"]);
ltr.SetShapeNumberAt(1, 0);
ltr.SetShapeOffsetAt(1, new Vector2d(-0.1,-0.05));
ltr.SetShapeScaleAt(1, 0.1);
ltr.SetShapeIsUcsOrientedAt(1, false);
ltr.SetShapeRotationAt(1, 0);
ltr.SetTextAt(1, "CW");
// Dash #3
ltr.SetDashLengthAt(2, -0.2);
// Add the new linetype to the linetype table
ObjectId ltId = lt.Add(ltr);
tr.AddNewlyCreatedDBObject(ltr, true);
// Create a test line with this linetype
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId,
OpenMode.ForRead
);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
Line ln =
new Line(
new Point3d(0, 0, 0),
new Point3d(10, 10, 0)
);
ln.SetDatabaseDefaults(db);
ln.LinetypeId = ltId;
btr.AppendEntity(ln);
tr.AddNewlyCreatedDBObject(ln, true);
tr.Commit();
}
}
}
}
And here's the result of calling the CCL command and zooming in on the created line:
January 9, 2008 in AutoCAD, AutoCAD .NET, Drawing structure, Object properties | Permalink | Comments (6) | TrackBack
Creating an AutoCAD linetype programmatically using .NET
Happy New Year, everyone!
I had a very relaxing break over the holiday period: during the better part of two weeks I managed to stay away from my PC and even my BlackBerry, which I admit I'm generally not very good at ignoring. So now I'm easing back into the swing of things, remembering how to type and open modelspaces, among other things. :-)
To save my brain from unnecessary stress during the first few weeks of 2008, I've decided to take inspiration from the ADN website. Today's post is based on this DevNote, which shows how to create a custom linetype using ObjectARX.
Here's some equivalent code in C#:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
namespace Linetype
{
public class Commands
{
[CommandMethod("CL")]
public void CreateLinetype()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
Transaction tr =
db.TransactionManager.StartTransaction();
using (tr)
{
// Get the linetype table from the drawing
LinetypeTable lt =
(LinetypeTable)tr.GetObject(
db.LinetypeTableId,
OpenMode.ForWrite
);
// Create our new linetype table record...
LinetypeTableRecord ltr =
new LinetypeTableRecord();
// ... and set its properties
ltr.AsciiDescription = "T E S T -";
ltr.PatternLength = 0.75;
ltr.NumDashes = 2;
ltr.SetDashLengthAt(0, 0.5);
ltr.SetDashLengthAt(1,-0.25);
ltr.Name = "TESTLINTEYPE";
// Add the new linetype to the linetype table
ObjectId ltId = lt.Add(ltr);
tr.AddNewlyCreatedDBObject(ltr,true);
// Create a test line with this linetype
BlockTable bt =
(BlockTable)tr.GetObject(
db.BlockTableId,
OpenMode.ForRead
);
BlockTableRecord btr =
(BlockTableRecord)tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
);
Line ln =
new Line(
new Point3d(0, 0, 0),
new Point3d(10, 10, 0)
);
ln.SetDatabaseDefaults(db);
ln.LinetypeId = ltId;
btr.AppendEntity(ln);
tr.AddNewlyCreatedDBObject(ln, true);
tr.Commit();
}
}
}
}
Once you've run the CL command, Zoom Extents to see a line that has been created with our new custom linetype.
January 7, 2008 in AutoCAD, AutoCAD .NET, Drawing structure, Object properties | Permalink | Comments (4) | TrackBack
Using a palette from .NET to display properties of multiple AutoCAD objects
After a brief interlude we're back on the series of posts showing how to implement basic user-interfaces inside AutoCAD using .NET. Here's the series so far:
- Using a modal .NET dialog to display AutoCAD object properties
- Using a modeless .NET dialog to display AutoCAD object properties
- Using a modeless .NET dialog to display properties of multiple AutoCAD objects
In this post we're going to swap out the modeless form we've been using in the last few posts in the series and replace it with an instance of AutoCAD's in-built palette class (Autodesk.AutoCAD.Windows.PaletteSet).
Firstly, why bother? Well, the PaletteSet class is realy cool: it provides docking, auto-hide, transparency and fixes the annoying focus-related issues we see with normal modeless dialogs.
And the best is that you get all this basically for free - the implementation work needed is really minimal. I started by copying liberal amounts of code from the DockingPalette sample on the ObjectARX SDK, and then deleted what wasn't needed for this project (which turned out to be most of it).
Here's the updated Command implementation. This really has very minor changes, as the palette implementation is all hidden inside the new TypeViewerPalette class.
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using CustomDialogs;
namespace CustomDialogs
{
public class Commands : IExtensionApplication
{
static TypeViewerPalette tvp;
public void Initialize()
{
tvp = new TypeViewerPalette();
DocumentCollection dm =
Application.DocumentManager;
dm.DocumentCreated +=
new DocumentCollectionEventHandler(OnDocumentCreated);
foreach (Document doc in dm)
{
doc.Editor.PointMonitor +=
new PointMonitorEventHandler(OnMonitorPoint);
}
}
public void Terminate()
{
try
{
DocumentCollection dm =
Application.DocumentManager;
if (dm != null)
{
Editor ed = dm.MdiActiveDocument.Editor;
ed.PointMonitor -=
new PointMonitorEventHandler(OnMonitorPoint);
}
}
catch (System.Exception)
{
// The editor may no longer
// be available on unload
}
}
private void OnDocumentCreated(
object sender,
DocumentCollectionEventArgs e
)
{
e.Document.Editor.PointMonitor +=
new PointMonitorEventHandler(OnMonitorPoint);
}
private void OnMonitorPoint(
object sender,
PointMonitorEventArgs e
)
{
FullSubentityPath[] paths =
e.Context.GetPickedEntities();
if (paths.Length <= 0)
{
tvp.SetObjectId(ObjectId.Null);
return;
};
ObjectIdCollection idc = new ObjectIdCollection();
foreach (FullSubentityPath path in paths)
{
// Just add the first ID in the list from each path
ObjectId[] ids = path.GetObjectIds();
idc.Add(ids[0]);
}
tvp.SetObjectIds(idc);
}
[CommandMethod("vt",CommandFlags.UsePickSet)]
public void ViewType()
{
tvp.Show();
}
}
}
As for the TypeViewerPalette class: I started by migrating the SetObjectId[s]()/SetObjectText() protocol across from the old TypeViewerForm class - the most complicated part of which involved exposing the contents of our palette (which we define and load as a User Control) via a member variable that can be accessed from SetObjectText(). Other than that it was all just copy & paste.
Here's the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
using Autodesk.AutoCAD.Windows;
using TypeViewer;
namespace CustomDialogs
{
public class TypeViewerPalette
{
// We cannot derive from PaletteSet
// so we contain it
static PaletteSet ps;
// We need to make the textbox available
// via a static member
static TypeViewerControl tvc;
public TypeViewerPalette()
{
tvc = new TypeViewerControl();
}
public void Show()
{
if (ps == null)
{
ps = new PaletteSet("Type Viewer");
ps.Style =
PaletteSetStyles.NameEditable |
PaletteSetStyles.ShowPropertiesMenu |
PaletteSetStyles.ShowAutoHideButton |
PaletteSetStyles.ShowCloseButton;
ps.MinimumSize =
new System.Drawing.Size(300, 300);
ps.Add("Type Viewer 1", tvc);
}
ps.Visible = true;
}
public void SetObjectText(string text)
{
tvc.typeTextBox.Text = text;
}
public void SetObjectIds(ObjectIdCollection ids)
{
if (ids.Count < 0)
{
SetObjectText("");
}
else
{
Document doc =
Autodesk.AutoCAD.ApplicationServices.
Application.DocumentManager.MdiActiveDocument;
DocumentLock loc =
doc.LockDocument();
using (loc)
{
string info =
"Number of objects: " +
ids.Count.ToString() + "\r\n";
Transaction tr =
doc.TransactionManager.StartTransaction();
using (tr)
{
foreach (ObjectId id in ids)
{
Entity ent =

Atom







