AcadNETwork
NET start => .NET newbies => Topic started by: Patriiick on November 20, 2010, 07:41:17 PM
-
Here is a list of interesting web adresses for helping you in .NET programming.
This list will be updated regularly by the webmaster.
- AutoCAD .NET Basics (http://augiru.augi.com/content/library/au07/data/paper/DE111-2.pdf), a PDF course from Autodesk University 2007
- A recording of AutoCAD .NET Basics (http://download.autodesk.com/media/adn/AutoCAD_DotNet_Basics/AutoCAD_DotNet_Basics.html), originally presented as DE205-4 in the ADN Developer track at AU 2008 by Stephen Preston
- A tutorial by Kean Walmsley (http://through-the-interface.typepad.com/through_the_interface/2006/07/getting_started.html) to get you started @keanw
- AutoCAD .NET developper guide (http://docs.autodesk.com/ACD/2010/ENU/AutoCAD%20.NET%20Developer%27s%20Guide/index.html) online
- Autodesk .NET forum (http://forums.autodesk.com/t5/NET/bd-p/152)
- Conversion tool (http://www.developerfusion.com/tools/convert/csharp-to-vb/) from C# to VB
- Google code search (http://www.google.com/codesearch)
If you want to suggest a new link please reply to this message.
There is also our specialised search engine (http://www.google.com/cse?cx=partner-pub-3297645841454436%3A6127304675&ie=UTF-8&q=&sa=Search) for searching only on .NET AutoCAD related sites. Give it a try.
-
Excellent Book with Sample/Source Code:
http://vbcad.com/
Started with VBA and now primarily VB.Net
-
Patriiick
You seem to have forgotten one of the better and longstanding forums
http://www.theswamp.org/index.php?board=27.0
-
That's right, thanks for the link.
-
Hi,
A new tutorial from Autodesk: My First Plug-in Training (http://usa.autodesk.com/adsk/servlet/index?id=18162650&siteID=123112)
-
A C# version would be welcome.
-
Hi
Stephen Preston may add C# versions (see here (http://www.theswamp.org/index.php?topic=40471.msg457794#msg457794)).
Waiting this, I purpose my conversion of the provided samples.
The two main differences between VB and C# are syntax and strictness (while VB option 'strict' is off which is the default).
C# is more strongly typed and allows less implicit casts.
KeepAttributesHorizontal - Lesson 1 Completed
Only syntax differences with the VB code.
Prefixing the class fields with an underscore is not requiered (it's only a convention as using 'my*' in VB languages).
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
namespace KeepAttributesHorizontalCs
{
public class Commands
{
private static KeepStraightOverrule _overrule;
[CommandMethod("KeepStraight")]
public static void ImplementOverrule()
{
// We only want to create our overrule instance once,
// so we check if it already exists before we create it
// (i.e. this may be the 2nd time we've run the command)
if (_overrule == null)
{
// Instantiate our overrule class
_overrule = new KeepStraightOverrule();
// Register the overrule
Overrule.AddOverrule
(RXClass.GetClass(typeof(AttributeReference)),
_overrule, false);
}
// Make sure overruling is turned on so our overrule works
Overrule.Overruling = true;
}
}
// Our custom overrule class derived from TransformOverrule
public class KeepStraightOverrule : TransformOverrule
{
// We want to change how an AttributeReference responds to being
// transformed (moved, rotated, etc.), so we override its
// standard TransformBy function.
public override void TransformBy(Entity entity, Matrix3d transform)
{
// Call the normal TransformBy function for the attribute
// reference we're overruling.
base.TransformBy(entity, transform);
// We know entity must be an AttributeReference because
// that is the only entity we registered the overrule for.
AttributeReference attRef = (AttributeReference)entity;
// Set rotation of attribute reference to 0 (horizontal)
attRef.Rotation = 0.0;
}
}
}
ObjectOrientedSample
using Autodesk.AutoCAD.Runtime;
namespace ObjectOrientedSampleCs
{
public class Commands
{
[CommandMethod("RunTest")]
public void Test()
{
Point pt1 = new Point();
// Use Step Into on the next line to step into SetLocation
pt1.SetLocation(10, 10);
int xVal1 = pt1.X;
pt1.X = 9;
int xVal2 = pt1.X;
NewPoint pt2 = new NewPoint();
pt2.SetLocation(20, 20);
int xVal3 = pt2.X;
pt2.X = 9;
// Z is new to the NewPoint class
pt2.Z = 12;
Point pt3 = pt2;
// pt3 is variable of type Point, but holds an object of type NewPoint
}
}
public class Point
{
private int _xCoord;
private int _yCoord;
public void SetLocation(int x, int y)
{
_xCoord = x;
_yCoord = y;
}
public int X
{
get { return _xCoord; }
set { _xCoord = value; }
}
public int Y
{
get { return _yCoord; }
set { _yCoord = value; }
}
}
public class NewPoint : Point
{
private int _zCoord;
public int Z
{
get { return _zCoord; }
set
{
// Don't accept negative Z values
if (value >= 0)
{
_zCoord = value;
}
}
}
}
}
KeepAttributesHorizontal - Lesson 5 Completed
Strictness difference:
VB = implicit cast from Entity to AttributeReference:
Dim attRef As AttributeReference = entity
C# = explicit cast from Entity to AttributeReference
AttributeReference attRef = (AttributeReference)entity;
Array size initialisation difference:
VB = upper bound
ReDim objIds(attRefColl.Count)
attRefColl.CopyTo(objIds, 0)
ReDim Preserve objIds(attRefColl.Count - 1)
C# = number of items
ObjectId[] objIds = new ObjectId[attRefColl.Count + 1];
attRefColl.CopyTo(objIds, 0);
System.Array.Resize(ref objIds, attRefColl.Count);
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput
Namespace HorizontalAttributes
Public Class Commands
' Class variable to store the instance of our overrule
Private Shared myOverrule As KeepStraightOverrule
<CommandMethod("KeepStraight")>
Public Shared Sub ImplementOverrule()
Dim doc As Document =
Application.DocumentManager.MdiActiveDocument
Dim ed As Editor = doc.Editor
' Select a block reference
Dim opts As New PromptEntityOptions(
vbLf & "Select a block reference:")
opts.SetRejectMessage(vbLf & "Must be block reference...")
opts.AddAllowedClass(GetType(BlockReference), True)
Dim res As PromptEntityResult = ed.GetEntity(opts)
If res.Status <> PromptStatus.OK Then
Exit Sub
End If
Dim objIds() As ObjectId
Dim db As Database = doc.Database
Using trans As Transaction =
db.TransactionManager.StartTransaction
' Open the BlockReference for read.
' We know its a BlockReference because we set a filter in
' our PromptEntityOptions
Dim blkRef As BlockReference =
trans.GetObject(res.ObjectId, OpenMode.ForRead)
' Record the ObjectIds of all AttributeReferences
' attached to the BlockReference.
Dim attRefColl As AttributeCollection =
blkRef.AttributeCollection
ReDim objIds(attRefColl.Count)
attRefColl.CopyTo(objIds, 0)
ReDim Preserve objIds(attRefColl.Count - 1)
End Using
'We only want to create our overrule instance once,
' so we check if it already exists before we create it
' (i.e. this may be the 2nd time we've run the command)
If myOverrule Is Nothing Then
'Instantiate our overrule class
myOverrule = New KeepStraightOverrule
'Register the overrule
Overrule.AddOverrule(
RXClass.GetClass(GetType(AttributeReference)),
myOverrule, False)
End If
'Specify which Attributes will be overruled
myOverrule.SetIdFilter(objIds)
'Make sure overruling is turned on so our overrule works
Overrule.Overruling = True
End Sub
End Class
'Our custom overrule class derived from TransformOverrule
Public Class KeepStraightOverrule
Inherits TransformOverrule
'We want to change how an AttributeReference responds to being
' transformed (moved, rotated, etc.), so we override its
' standard TransformBy function.
Public Overrides Sub TransformBy(ByVal entity As Entity,
ByVal transform As Matrix3d)
'Call the normal TransformBy function for the attribute
' reference we're overruling.
MyBase.TransformBy(entity, transform)
'We know entity must be an AttributeReference because
' that is the only entity we registered the overrule for.
Dim attRef As AttributeReference = entity
'Set rotation of attribute reference to 0 (horizontal)
attRef.Rotation = 0.0
End Sub
End Class
End Namespace
KeepAttributesHorizontal - Lesson 6 Completed
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
namespace KeepAttributesHorizontalCs
{
public class Commands
{
// Class variable to store the instance of our overrule
private static KeepStraightOverrule _overrule;
// Registered Application Id for Xdata
private const string _regAppName = "ADSK_ATTRIBUTE_ZERO_OVERRULE";
[CommandMethod("KeepStraight")]
public static void ImplementOverrule()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
// Select a block reference
PromptEntityOptions opts = new PromptEntityOptions("\nSelect a block reference: ");
opts.SetRejectMessage("\nMust be block reference...");
opts.AddAllowedClass(typeof(BlockReference), true);
PromptEntityResult res = ed.GetEntity(opts);
if (res.Status != PromptStatus.OK)
return;
Database db = doc.Database;
AddRegAppId(db);
using (Transaction trans = db.TransactionManager.StartTransaction())
{
// Open the BlockReference for read.
// We know its a BlockReference because we set a filter in
// our PromptEntityOptions.
BlockReference blkRef =
(BlockReference)trans.GetObject(res.ObjectId, OpenMode.ForRead);
// Record the ObjectIds of all AttributeReferences
// attached to the BlockReference.
AttributeCollection attRefColl = blkRef.AttributeCollection;
// Iterate through ObjectIds of all AttributeReferences
// attached to the BlockReference, opening each
// AttributeReference and adding xdata to it.
foreach (ObjectId objId in attRefColl)
{
AttributeReference attRef =
(AttributeReference)trans.GetObject(objId, OpenMode.ForWrite);
// Create new xdata containing the overrule filter name
using (ResultBuffer resBuf = new ResultBuffer(
new TypedValue((int)DxfCode.ExtendedDataRegAppName, _regAppName),
new TypedValue((int)DxfCode.ExtendedDataAsciiString, "Dummy text")))
{
// Add the xdata
attRef.XData = resBuf;
}
}
trans.Commit();
}
// Create and register our overrule and turn overruling on.
ActivateOverrule();
}
[CommandMethod("DontKeepStraight")]
public static void RemoveXdata()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
// Select a block reference
PromptEntityOptions opts = new PromptEntityOptions("\nSelect a block reference: ");
opts.SetRejectMessage("\nMust be block reference...");
opts.AddAllowedClass(typeof(BlockReference), true);
PromptEntityResult res = ed.GetEntity(opts);
if (res.Status != PromptStatus.OK)
return;
Database db = doc.Database;
AddRegAppId(db);
using (Transaction trans = db.TransactionManager.StartTransaction())
{
// Open the BlockReference for read.
// We know its a BlockReference because we set a filter in
// our PromptEntityOptions.
BlockReference blkRef =
(BlockReference)trans.GetObject(res.ObjectId, OpenMode.ForRead);
// Record the ObjectIds of all AttributeReferences
// attached to the BlockReference.
AttributeCollection attRefColl = blkRef.AttributeCollection;
// Iterate through ObjectIds of all AttributeReferences
// attached to the BlockReference, opening each
// AttributeReference and adding xdata to it.
foreach (ObjectId objId in attRefColl)
{
AttributeReference attRef =
(AttributeReference)trans.GetObject(objId, OpenMode.ForWrite);
// Create new xdata containing the overrule filter name
using (ResultBuffer resBuf = new ResultBuffer(
new TypedValue((int)DxfCode.ExtendedDataRegAppName, _regAppName)))
{
// Add the xdata
// Because we leave this blank except for the regappid,
// it erases any Xdata we previously added.
attRef.XData = resBuf;
}
}
trans.Commit();
}
}
[CommandMethod("ActivateOverrule")]
private static void ActivateOverrule()
{
// We only want to create our overrule instance once,
// so we check if it already exists before we create it
// (i.e. this may be the 2nd time we've run the command)
if (_overrule == null)
{
// Instantiate our overrule class
_overrule = new KeepStraightOverrule();
// Register the overrule
Overrule.AddOverrule
(RXClass.GetClass(typeof(AttributeReference)),
_overrule, false);
}
// Specify which Attributes will be overruled
_overrule.SetXDataFilter(_regAppName);
// Make sure overruling is turned on so our overrule works
Overrule.Overruling = true;
}
private static void AddRegAppId(Database db)
{
using (Transaction trans = db.TransactionManager.StartTransaction())
{
// First create our RegAppId (if it doesn't already exist)
RegAppTable appTbl =
(RegAppTable)trans.GetObject(db.RegAppTableId, OpenMode.ForRead);
if (!appTbl.Has(_regAppName))
{
RegAppTableRecord appTblRec = new RegAppTableRecord();
appTblRec.Name = _regAppName;
appTbl.UpgradeOpen();
appTbl.Add(appTblRec);
trans.AddNewlyCreatedDBObject(appTblRec, true);
}
trans.Commit();
}
}
}
// Our custom overrule class derived from TransformOverrule
public class KeepStraightOverrule : TransformOverrule
{
// We want to change how an AttributeReference responds to being
// transformed (moved, rotated, etc.), so we override its
// standard TransformBy function.
public override void TransformBy(Entity entity, Matrix3d transform)
{
// Call the normal TransformBy function for the attribute
// reference we're overruling.
base.TransformBy(entity, transform);
// We know entity must be an AttributeReference because
// that is the only entity we registered the overrule for.
AttributeReference attRef = (AttributeReference)entity;
// Set rotation of attribute reference to 0 (horizontal)
attRef.Rotation = 0.0;
}
}
}
-
Bonus Plugin
Refactorised code
Edit: the the matrix calculation in the BillboardAttributesOverrule.ViewportDraw() method have been re-written so that it works whatever the block insertion plane.
Edit 2: corrected code so that it works whatever the attribute text justificaion.
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
namespace BonusPluginCs
{
//public class ExtensionApplication : IExtensionApplication
//{
// public void Initialize()
// {
// Commands.ActivateOverrule();
// }
// public void Terminate() { }
//}
public class Commands
{
private static BillboardAttributesOverrule _overrule;
// Registered Application Id for Xdata
private const string regAppName = "ADSK_ATTRIBUTE_ZERO_OVERRULE";
[CommandMethod("BillboardAttributes")]
public static void ImplementOverrule()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
// Select a block reference
PromptEntityResult res = GetBlkRef(ed);
if (res.Status != PromptStatus.OK)
return;
// Create and register our overrule and turn overruling on.
ActivateOverrule();
// Create new xdata containing the overrule filter name
using (ResultBuffer resBuf = new ResultBuffer(
new TypedValue((int)DxfCode.ExtendedDataRegAppName, regAppName),
new TypedValue((int)DxfCode.ExtendedDataAsciiString, "Dummy text")))
{
// Add the xdata
AddXdata(res.ObjectId, resBuf, db);
}
}
[CommandMethod("DontBillboardAttributes")]
public static void RemoveXdata()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
// Select a block reference
PromptEntityResult res = GetBlkRef(ed);
if (res.Status != PromptStatus.OK)
return;
// Create new xdata containing the overrule filter name
using (ResultBuffer resBuf = new ResultBuffer(
new TypedValue((int)DxfCode.ExtendedDataRegAppName, regAppName)))
{
// Add the xdata
// Because we leave this blank except for the regappid,
// it erases any Xdata we previously added.
AddXdata(res.ObjectId, resBuf, db);
}
}
[CommandMethod("ActivateBillboardOverrule")]
public static void ActivateOverrule()
{
// We only want to create our overrule instance once,
// so we check if it already exists before we create it
// (i.e. this may be the 2nd time we've run the command)
if (_overrule == null)
{
// Instantiate our overrule class
_overrule = new BillboardAttributesOverrule();
// Register the overrule
Overrule.AddOverrule
(RXClass.GetClass(typeof(AttributeReference)),
_overrule, false);
}
// Specify which Attributes will be overruled
_overrule.SetXDataFilter(regAppName);
// Make sure overruling is turned on so our overrule works
Overrule.Overruling = true;
}
private static PromptEntityResult GetBlkRef(Editor ed)
{
PromptEntityOptions opts = new PromptEntityOptions("\nSelect a block reference: ");
opts.SetRejectMessage("\nMust be block reference...");
opts.AddAllowedClass(typeof(BlockReference), true);
return ed.GetEntity(opts);
}
private static void AddXdata(ObjectId id, ResultBuffer resBuf, Database db)
{
using (Transaction trans = db.TransactionManager.StartTransaction())
{
// First create our RegAppId (if it doesn't already exist)
RegAppTable appTbl =
(RegAppTable)trans.GetObject(db.RegAppTableId, OpenMode.ForRead);
if (!appTbl.Has(regAppName))
{
RegAppTableRecord appTblRec = new RegAppTableRecord();
appTblRec.Name = regAppName;
appTbl.UpgradeOpen();
appTbl.Add(appTblRec);
trans.AddNewlyCreatedDBObject(appTblRec, true);
}
// Open the BlockReference for read.
// We know its a BlockReference because we set a filter in
// our PromptEntityOptions.
BlockReference blkRef =
(BlockReference)trans.GetObject(id, OpenMode.ForRead);
// Record the ObjectIds of all AttributeReferences
// attached to the BlockReference.
AttributeCollection attRefColl = blkRef.AttributeCollection;
// Iterate through ObjectIds of all AttributeReferences
// attached to the BlockReference, opening each
// AttributeReference and adding xdata to it.
foreach (ObjectId objId in attRefColl)
{
AttributeReference attRef =
(AttributeReference)trans.GetObject(objId, OpenMode.ForWrite);
// Add the xdata
attRef.XData = resBuf;
}
trans.Commit();
}
}
}
// Our custom overrule class derived from TransformOverrule
public class BillboardAttributesOverrule : DrawableOverrule
{
// Returning False from WorldDraw tells AutoCAD this entity has
// viewport dependent graphics.
public override bool WorldDraw(Drawable drawable, WorldDraw wd)
{
return false;
}
// Called for each viewport so entity can draw itself differently
// depending on the view.
public override void ViewportDraw(Drawable drawable, ViewportDraw vd)
{
// Cast drawable to type AttributeReference (we know it's an
// AttributeReference because that's the only class we register our
// overrule for).
AttributeReference attRef = (AttributeReference)drawable;
// First calculate the transformation matrix to rotate from the
// BlockReference's current orientation to the view.
Point3d org = attRef.Justify == AttachmentPoint.BaseLeft ||
attRef.Justify == AttachmentPoint.BaseAlign ||
attRef.Justify == AttachmentPoint.BaseFit ?
attRef.Position : attRef.AlignmentPoint;
Matrix3d viewMat =
Matrix3d.PlaneToWorld(new Plane(org, vd.Viewport.ViewDirection)) *
Matrix3d.WorldToPlane(new Plane(org, attRef.Normal)) *
Matrix3d.Rotation(-attRef.Rotation, attRef.Normal, org);
// Apply the transformation
vd.Geometry.PushModelTransform(viewMat);
// Draw the 'per viewport geometry
base.ViewportDraw(drawable, vd);
// Remove the transformation - we don't want any other objects
// to draw themselves in the view plane.
vd.Geometry.PopModelTransform();
}
// This function tells AutoCAD to dynamically update the
// AttributeReference during view transitions (e.g. 3DORBIT).
// Comment it out to improve graphic update performance.
public override int SetAttributes(Drawable drawable, DrawableTraits traits)
{
return base.SetAttributes(drawable, traits) | (int)DrawableAttributes.ViewDependentViewportDraw;
}
}
}
-
Thanks Gille, did you used an automatic conversion tool?
-
Thanks Gille, did you used an automatic conversion tool?
No, not this time.
With automatic conversion tools, there're often issues from VB to C# when the VB code wasn't written with 'option strict'.
Doing these conversion was a nice way to learn a little about Overrules.
-
I updated the code of the 'Bonus Plugin'.
I re-write the the matrix calculation in the BillboardAttributesOverrule.ViewportDraw() method so that it works whatever the block insertion plane.
-
I updated the code of the 'Bonus Plugin'.
I re-write the origin point definition used in the transformation matrix calculation of the BillboardAttributesOverrule.ViewportDraw() method so that it works whatever the attribute text justification.
For those who are interested, I posted a F# implementation here (http://www.theswamp.org/index.php?topic=40471.msg458198#msg458198).
-
From Stephen Preston announcement at TheSwamp (http://www.theswamp.org/index.php?topic=41046.msg462509#msg462509):
The My First AutoCAD Plugin tutorial is now out of Beta, which means we've added the missing videos and fixed a few bugs. You'll find the tutorial here: http://www.autodesk.com/myfirstautocadplugin. And you can watch a (slightly tongue-in-cheek) promo video here: http://www.youtube.com/watch?v=5a50QULamuU.