Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - (gile)

Pages: 1 2 [3] 4 5 6
31
.NET newbies / Re: Links to web ressources
« on: February 26, 2012, 10:24:06 PM »
From Stephen Preston announcement at TheSwamp:

Quote
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.

32
.NET newbies / Re: Links to web ressources
« on: February 11, 2012, 11:24:58 AM »
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.

33
Tables / Re: Create simple table
« on: January 14, 2012, 11:22:24 PM »
Thanks for sharing, Oleg.

34
Windows forms / NumerixBox and IntegerBox
« on: January 08, 2012, 01:14:26 PM »
NumericBox and IntegerBox. (EDIT: added an AngleBox)

These two three little classes can be added to a project to add new controls.
They inhertit from TextBox and have some specfic properties and overload methods to insure valid values.
An ErrorProvider is used in case of non valid entry.
Specific properties are available in the Visual Studio Properties window for the control instance.

IntegerBox
Specific properties:
- ErrorMsg: the message displayed by the ErrorProvider for incorrect value (default: "Incorrect number").
- Maximum: the maximum allowed value (default: 2147483647)
- Minimum: the minimum allowed value (default: -2147483648)
- Value: the value as integer (default 0). Setting this value overwrite the Text property.

Code: [Select]
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace ControlLibrary
{
    /// <summary>
    /// Defines a control that can be used to display or edit an integer.
    /// </summary>
    public class IntegerBox : TextBox
    {
        private ErrorProvider _errorProvider;
        private int _value;

        /// <summary>
        /// Set default values.
        /// </summary>
        public IntegerBox()
        {
            _errorProvider = new ErrorProvider();
            ErrorMsg = "Incorrect number";
            Minimum = -2147483648;
            Maximum = 2147483647;
            _value = 0;
        }

        /// <summary>
        /// Get or set the error provider message.
        /// </summary>
        public string ErrorMsg { get; set; }

        /// <summary>
        /// Get or set the minimum allowed value.
        /// </summary>
        public int Minimum { get; set; }

        /// <summary>
        /// Get or set the maximum allowed value.
        /// </summary>
        public int Maximum { get; set; }

        /// <summary>
        /// Get or set the value as integer.
        /// </summary>
        public int Value
        {
            get { return _value; }
            set
            {
                _value = value;
                this.Text = _value.ToString();
                this.OnValidating(new CancelEventArgs());
            }
        }

        /// <summary>
        /// Evaluates if the value is a valid integer according to MinValue and MaxValue.
        /// If not, cancels the validation and displayd an error provider.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnValidating(System.ComponentModel.CancelEventArgs e)
        {
            base.OnValidating(e);
            int i;
            if (!int.TryParse(this.Text, out i) || i < Minimum || i > Maximum)
            {
                e.Cancel = true;
                this.Select(0, this.Text.Length);
                _errorProvider.SetError(this, ErrorMsg);
            }
        }

        /// <summary>
        /// Updates Value.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnValidated(EventArgs e)
        {
            base.OnValidated(e);
            _value = Convert.ToInt32(this.Text);
        }

        /// <summary>
        /// Hide the error provider.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            _errorProvider.SetError(this, "");
        }
    }
}

NumericBox
Specific properties:
- DecimalPlaces: the number of digits displayed in the box after validation (default 0)
- ErrorMsg: the message displayed by the ErrorProvider for incorrect value (default: "Incorrect number").
- Value: the value as double (default 0.0). Setting this value overwrite the Text property. This value may be more accurate than the displayed one.

Code: [Select]
using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace ControlLibrary
{
    /// <summary>
    /// Defines a control that can be used to display or edit a real number (double).
    /// </summary>
    public class NumericBox : TextBox
    {
        private double _value;
        private ErrorProvider _errorProvider;
        private int _decimalPlaces;
        protected string _stringFormat;

        /// <summary>
        /// Set default values.
        /// </summary>
        public NumericBox()
        {
            _value = 0;
            _errorProvider = new ErrorProvider();
            ErrorMsg = "Incorrect number";
            SetFormat();
        }

        /// <summary>
        /// Get or set the number of digits diplayed in the box.
        /// </summary>
        public int DecimalPlaces
        {
            get { return _decimalPlaces; }
            set { _decimalPlaces = value; SetFormat(); }
        }

        /// <summary>
        /// Get or set the ErrorProvider message.
        /// </summary>
        public string ErrorMsg { get; set; }

        /// <summary>
        /// Get or set the number value as double (may be more accurate than the displayed one).
        /// Updates the Text according to DecimalPlaces.
        /// </summary>
        public virtual double Value
        {
            get { return _value; }
            set {  _value = value;  this.Text = _value.ToString(_stringFormat); }
        }

        /// <summary>
        /// Evaluates if the value is a valid real number.
        /// If not, cancels the validation and displayd the ErrorProvider icon.
        /// </summary>
        /// <param name="e">The event data</param>
        protected override void OnValidating(CancelEventArgs e)
        {
            double d;
            if (!double.TryParse(this.Text, out d))
            {
                e.Cancel = true;
                this.Select(0, this.Text.Length);
                _errorProvider.SetError(this, ErrorMsg);
            }
            base.OnValidating(e);
        }

        /// <summary>
        /// Updates Text and Value.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnValidated(EventArgs e)
        {
            _value = Convert.ToDouble(this.Text);
            this.Text = _value.ToString(_stringFormat);
            base.OnValidated(e);
        }

        /// <summary>
        /// Hide the ErrorProvider icon.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnTextChanged(EventArgs e)
        {
            _errorProvider.SetError(this, "");
            base.OnTextChanged(e);
        }

        /// <summary>
        /// Creates a format string according to DecimalPlaces value.
        /// Updates the Format property.
        /// </summary>
        private void SetFormat()
        {
            if (DecimalPlaces < 1)
                _stringFormat = "0";
            else
            {
                _stringFormat = "0.";
                for (int i = 0; i < DecimalPlaces; i++) _stringFormat += "0";
            }
        }
    }
}

AngleBox (inherits from NumericBox)
Specific Property:
- UnitFormat: the unit format for the Text displayed. The Value property is always expressed in radians.

Code: [Select]
using System;

namespace ControlLibrary
{
    /// <summary>
    /// Defines a control that can be used to display or edit an angular value (double).
    /// </summary>
    public class AngleBox : NumericBox
    {
        private double _value;

        /// <summary>
        /// Angular units enumeration.
        /// </summary>
        public enum Unit
        {
            Degree,
            Grade,
            Radian
        }

        /// <summary>
        /// Define the default angular unit.
        /// </summary>
        public AngleBox()
        {
            this.UnitFormat = Unit.Degree;
        }

        /// <summary>
        /// Get or set the angular format (unit).
        /// </summary>
        public Unit UnitFormat { get; set; }

        /// <summary>
        /// Get or set the angle value in radians.
        /// Updates the Text property according to UnitFormat and DecimalPlaces.
        /// </summary>
        public override double Value
        {
            get { return _value; }
            set { _value = value; this.Text = AngleToString(_value); }
        }

        /// <summary>
        /// Updates Text and Value properties.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnValidated(EventArgs e)
        {
            _value = StringToAngle(this.Text);
            this.Text = AngleToString(_value);
            base.OnValidated(e);
        }

        /// <summary>
        /// Converts a string into an angle value in radians.
        /// </summary>
        /// <param name="txt">The angle expressed according to UnitFormat.</param>
        /// <returns>The angle value in radians.</returns>
        private double StringToAngle(string txt)
        {
            switch (UnitFormat)
            {
                case Unit.Degree:
                    return Convert.ToDouble(txt) * Math.PI / 180.0;
                case Unit.Grade:
                    return Convert.ToDouble(txt) * Math.PI / 200.0;
                default: //Radian
                    return Convert.ToDouble(txt);
            }
        }

        /// <summary>
        /// Converts an angle value in radians into a string.
        /// </summary>
        /// <param name="val">The angle value in radians..</param>
        /// <returns>The angle expressed according to UnitFormat</returns>
        private string AngleToString(double val)
        {
            switch (UnitFormat)
            {
                case Unit.Degree:
                    return (val * 180.0 / Math.PI).ToString(_stringFormat);
                case Unit.Grade:
                    return (val * 200.0 / Math.PI).ToString(_stringFormat);
                default: // Radian
                    return val.ToString(_stringFormat);
            }
        }
    }
}

35
.NET newbies / Re: Links to web ressources
« on: January 05, 2012, 07:41:28 AM »
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.

36
.NET newbies / Re: Links to web ressources
« on: January 01, 2012, 07:09:06 PM »
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.

37
.NET newbies / Re: Links to web ressources
« on: January 01, 2012, 06:26:30 PM »
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.

Code: [Select]
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;
        }
    }
}

38
.NET newbies / Re: Links to web ressources
« on: January 01, 2012, 06:24:33 PM »
Hi

Stephen Preston may add C# versions (see here).

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).

Code: [Select]
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

Code: [Select]
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);


Code: [Select]
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

Code: [Select]
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;
        }
    }
}

39
.NET newbies / Re: Links to web ressources
« on: December 29, 2011, 01:23:43 PM »
Hi,

A new tutorial from Autodesk: My First Plug-in Training

40
Events / Re: Query for EventHandlers
« on: November 21, 2011, 01:08:37 PM »
Hi,

Good catch, the try/catch statement is unuseful.
Thanks.

So it' possible to systematically remove the handler befor adding it.

Code: [Select]
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

namespace EventHandlerHandling
{
    public class Commands
    {
        [CommandMethod("UnsafeCmd")]
        public void UnsafeCmd()
        {
            LayoutManager layMgr = LayoutManager.Current;
            layMgr.LayoutSwitched += new LayoutEventHandler(OnLayoutSwitched);
        }

        [CommandMethod("SafeCmd")]
        public void SafeCmd()
        {
            LayoutManager layMgr = LayoutManager.Current;
            layMgr.LayoutSwitched -= new LayoutEventHandler(OnLayoutSwitched);
            layMgr.LayoutSwitched += new LayoutEventHandler(OnLayoutSwitched);
        }

        void OnLayoutSwitched(object sender, LayoutEventArgs e)
        {
            Application.ShowAlertDialog("Layout switched");
        }
    }
}

41
Events / Re: Query for EventHandlers
« on: November 17, 2011, 09:29:06 PM »
I don't think it is possible.
By my side, I sometimes do it like this:
Code: [Select]
try
{
     LayoutManager.Current.LayoutSwitched -= new Autodesk.AutoCAD.DatabaseServices.LayoutEventHandler(OnLayoutSwitched);
}
catch{}
LayoutManager.Current.LayoutSwitched += new Autodesk.AutoCAD.DatabaseServices.LayoutEventHandler(OnLayoutSwitched);

42
Selection sets / Re: Selection Set Filters
« on: November 15, 2011, 10:32:57 PM »
Nice.

Another way is to use the Editor.Selectionadded event
Here's a little example with an extension method for Editor which select only entities derived from Curve.

Code: [Select]
        public static PromptSelectionResult GetCurveSelection(this Editor ed, params TypedValue[] filter)
        {
            ed.SelectionAdded += new SelectionAddedEventHandler(OnCurveSelectionAdded);
            PromptSelectionResult psr = ed.GetSelection(new SelectionFilter(filter));
            ed.SelectionAdded -= new SelectionAddedEventHandler(OnCurveSelectionAdded);
            return psr;
        }

        static void OnCurveSelectionAdded(object sender, SelectionAddedEventArgs e)
        {
            ObjectId[] ids = e.AddedObjects.GetObjectIds();
            for (int i = 0; i < ids.Length; i++)
            {
                if (!ids[i].ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(Curve))))
                    e.Remove(i);
            }
        }

43
Math and Geometry / Re: Geometry extensions
« on: November 15, 2011, 09:15:45 PM »
Hi,

As you say the matrix multiplication is not comutative.
When multiplying two matrices, the resulting matrix can be considered as the combination of the right hand matrix transformation first and then, the left hand one.
This is the way the * operator works (as in maths).

So to transform from paper space coordinates to model space coordinates, you have to write:
Code: [Select]
Matrix3d ps2wcs = pvp2.DCS2WCS() * pvp2.PSDCS2DCS();The Matrix3d class provides a method which (perhaps) allows more 'readable' code: PreMultiplyBy.
Code: [Select]
Matrix3d ps2wcs = pvp2.PSDCS2DCS().PreMultiplyBy(pvp2.DCS2WCS());
You can see this message.

44
Math and Geometry / Re: Geometry extensions
« on: November 14, 2011, 09:17:21 PM »
New version of GeometryExtensions (1.3).
Download updated in the first message.
Corrected some bugs with the GetProjectedPolyline and GetOrthoProjectedPolyline methods.

45
This site / Re: Welcome on the AutoCAD .NET developpers forums
« on: November 08, 2011, 06:09:28 PM »
Hi Cedric,

Why C++ if you prefer managed code ?
C# was build for DotNET.

Pourquoi C++ si tu préfère le code "managé" ?
C# a été fait pour DotNET.

Pages: 1 2 [3] 4 5 6