Author Topic: Tool palette, Object selection and Event  (Read 36581 times)

0 Members and 1 Guest are viewing this topic.

TonyT

  • Guest
Re: Tool palette, Object selection and Event
« Reply #30 on: June 05, 2007, 07:39:57 PM »
Okay so putting in the command and lisp checks are not as easy as I would have hoped.  I think it won't be until tomorrow or later until I figure them out.  :oops:

That's probably the easiest part.   :wink:

There's the CMDACTIVE system variable,
and there's the CommandInProgress property
of the Document.

I'm not sure if they indicate if LISP is running
(I think CMDACTIVE might), but all you need
to do is check that before your Selection-
related event handlers do anything, and exit
if not.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Tool palette, Object selection and Event
« Reply #31 on: June 05, 2007, 07:41:55 PM »
Okay so putting in the command and lisp checks are not as easy as I would have hoped.  I think it won't be until tomorrow or later until I figure them out.  :oops:

That's probably the easiest part.   :wink:

There's the CMDACTIVE system variable,
and there's the CommandInProgress property
of the Document.

I'm not sure if they indicate if LISP is running
(I think CMDACTIVE might), but all you need
to do is check that before your Selection-
related event handlers do anything, and exit
if not.

Oh man!  Events have clouded my mind!  Thanks Tony I will see about these tomorrow, as it's time to go home, and I can't code there now.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Tool palette, Object selection and Event
« Reply #32 on: June 06, 2007, 12:22:02 PM »
Okay, here is the final code as I see it.  The event will fire, but nothing will happen when the palette is closed (not visible) or when there is a command/lisp active.  It will change the palette when the drawing is changed.  If anyone tries it, let me know how it works for you.  I'm adding it to my standard C# files that I load into Acad.

Thanks everyone for you help, it is very much appreciated.


Edit:  Removed old code.
« Last Edit: June 14, 2007, 01:08:21 PM by T.Willey »
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

FengK

  • Guest
Re: Tool palette, Object selection and Event
« Reply #33 on: June 06, 2007, 12:38:17 PM »
I'm adding it to my standard C# files that I load into Acad.

Tim, how do you do that? Do you mean compile the code into .dll and netload? thanks.

LE

  • Guest
Re: Tool palette, Object selection and Event
« Reply #34 on: June 06, 2007, 01:07:58 PM »
Tim;

It is working here, in the small testing I did, I like it!

minor stuff: once it is not docked, you can't docked again... if you select other entities and one block it will let you fill the data in the palette ...

Good one!

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Tool palette, Object selection and Event
« Reply #35 on: June 06, 2007, 01:17:48 PM »
I'm adding it to my standard C# files that I load into Acad.

Tim, how do you do that? Do you mean compile the code into .dll and netload? thanks.

Kelie,

I put all my real code into one project (combine) and compile it into one dll.  I then load that one dll in acad with the registry.  Thanks to Glenns's post here.  This doesn't really get loaded until one of the commands is issued.  Kind of like the autoload feature in lisp.

Hope that makes sense Kelie.

Tim;

It is working here, in the small testing I did, I like it!
Thanks for testing it Luis.  Glad someone besides me likes it.  :-)

minor stuff: once it is not docked, you can't docked again...
I think that is because I tell it not to dock here.
Code: [Select]
ps.DockEnabled = Autodesk.AutoCAD.Windows.DockSides.None;
ps.Dock = Autodesk.AutoCAD.Windows.DockSides.None;
but I was really trying to get it to float when first opened, but couldn't figure it out.  I think comment these out, then it would allow you to dock it again.  I will do some research on this, and get back to you.

if you select other entities and one block it will let you fill the data in the palette ...
I wanted it like this incase you just select a bunch of things.  It's just easier, IMO.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

LE

  • Guest
Re: Tool palette, Object selection and Event
« Reply #36 on: June 06, 2007, 03:39:44 PM »
 but I was really trying to get it to float when first opened, but couldn't figure it out.

You can add the following on your code in your CreateMyPalette():

Code: [Select]
            try { ps.AutoRollUp = true; }
            catch { }


            ps.Location = new System.Drawing.Point(0, 100); // i think this line is not needed
            ps.Dock = Autodesk.AutoCAD.Windows.DockSides.None;

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Tool palette, Object selection and Event
« Reply #37 on: June 06, 2007, 05:48:41 PM »
Thanks Luis.  Been busy today with 'real' work, so no time to play.  We see how this works when I get a minute.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

FengK

  • Guest
Re: Tool palette, Object selection and Event
« Reply #38 on: June 06, 2007, 06:56:14 PM »
Kelie,

I put all my real code into one project (combine) and compile it into one dll.  I then load that one dll in acad with the registry.  Thanks to Glenns's post here.  This doesn't really get loaded until one of the commands is issued.  Kind of like the autoload feature in lisp.

Hope that makes sense Kelie.

Thanks Tim. Do you know compared with using NETLOAD, what is the benefit of using registry to load dll?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Tool palette, Object selection and Event
« Reply #39 on: June 06, 2007, 06:58:57 PM »
Kelie,

I put all my real code into one project (combine) and compile it into one dll.  I then load that one dll in acad with the registry.  Thanks to Glenns's post here.  This doesn't really get loaded until one of the commands is issued.  Kind of like the autoload feature in lisp.

Hope that makes sense Kelie.

Thanks Tim. Do you know compared with using NETLOAD, what is the benefit of using registry to load dll?
The benefits I see is you don't have to use 'netload'.  All you do is type the command, and the command will work.  I now only use netload to load files I'm working on, so this program is now loaed when I type the command name (since I added it to my list of commands in my registry, any my main dll) without having to go through netload.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

TonyT

  • Guest
Re: Tool palette, Object selection and Event
« Reply #40 on: June 06, 2007, 07:08:16 PM »
Okay, here is the final code as I see it......

Tim - In the 20 or so years I've been doing this, if
there is one thing I've learned, it is that there is
no such thng as 'the final code'   :-)

So moving along, there are other problems that you
don't see yet. The first is that your UserControl class
uses a non-static command method.

When a command method is non-static, the AutoCAD
managed runtime creates a new instance of the class
that declares the method, for each document that the
coimmand is invoked in, and caches them.

When you invoke the commad a second time in the
same document, the cached instance of the class that's
associated with that document is the instance which
the method is invoked on.

Your "MyUcPalette" command method is a non-static
member of UserControl1. That means that to invoke
that method, there must be an instance of UserControl1
that already exists, which is the instance that AutoCAD
creates when you issue the command in a document the
first time.

Your command method is then creating another instance
of UserControl1, when the command is invoked. But the
problem (which is not easily seen), is that subsequent
invocations of the command, causes the non-static
command method to be invoked not on the instance of
UserControl1 that your command creates, but rather on
the cached instance AutoCAD createed for you, the first
time you issue the command in each document.

In otherwords, if you have 3 documents open, and you
issue the MyUcPalette command in each, there will be
3 instances of UserControl1 created, one for each open
document the command was issued in. Your code as it
is written doesn't even know about them.


T.Willey

  • Needs a day job
  • Posts: 5251
Re: Tool palette, Object selection and Event
« Reply #41 on: June 06, 2007, 07:35:20 PM »
Tony, thanks again for your input, I find it invaluable.

Some of what you say makes sense to me, but some has me scratching my head.  I knew I didn't know much about C#, but know I'm finding I know a whole lot less than I thought I did.  I will do some research and see if I can solve this problem, and maybe in doing so I will be able to see if there are any other problems.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

LE

  • Guest
Re: Tool palette, Object selection and Event
« Reply #42 on: June 06, 2007, 11:38:08 PM »
OK;

After following Tony advice, here is the code updated, hope that is right if not somebody else did it.

Code: [Select]
/*
 * Created by SharpDevelop.
 * User: Tim Willey
 * Date: 6/1/2007
 * Time: 2:55 PM
 *
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Collections;
using System.Data;
using System.Data.OleDb;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Windows.ToolPalette;

using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

[assembly: CommandClass(typeof(Test.UserControl1))]

namespace Test
{
    /// <summary>
    /// Description of UserControl1.
    /// </summary>
    public class UserControl1 : System.Windows.Forms.UserControl
    {
        public UserControl1()
        {
            //
            // The InitializeComponent() call is required for Windows Forms designer support.
            //
            InitializeComponent();

            //
            // TODO: Add constructor code after the InitializeComponent() call.
            //
        }

        #region Windows Forms Designer generated code
        /// <summary>
        /// This method is required for Windows Forms designer support.
        /// Do not change the method contents inside the source code editor. The Forms designer might
        /// not be able to load this method if it was changed manually.
        /// </summary>
        private void InitializeComponent()
        {
            //
            // BlankUserControl
            //
            this.Name = "BlankUserControl";
            this.Size = new System.Drawing.Size(232, 408);
        }
        #endregion

        private static int counter = 0; //test counter

        private static Autodesk.AutoCAD.Windows.PaletteSet ps;
        private static UserControl1 uc;
        private static System.Windows.Forms.Button OkBut;
        private static bool FirstLoad = true;
        private static bool cmdStart = false;
        private static bool lspStart = false;
        [CommandMethod("MyUcPalette")]
        public [color=blue]static [/color] void CreateMyPalette()
        {
            Document doc = AcadApp.DocumentManager.MdiActiveDocument;
            Editor Ed = doc.Editor;
            Ed.WriteMessage("\nCounter value is: " + counter++); //when switch to a new document or in the active it will continue with the next value not from 0


            if (ps == null)
            {
                ps = new Autodesk.AutoCAD.Windows.PaletteSet("My Attribute Palette");
                ps.Style = Autodesk.AutoCAD.Windows.PaletteSetStyles.ShowPropertiesMenu |
                    Autodesk.AutoCAD.Windows.PaletteSetStyles.ShowAutoHideButton |
                    Autodesk.AutoCAD.Windows.PaletteSetStyles.ShowCloseButton;
                ps.Opacity = 90;
                ps.Size = new System.Drawing.Size(250, 400);
                ps.MinimumSize = new System.Drawing.Size(225, 400);
                ps.DockEnabled = Autodesk.AutoCAD.Windows.DockSides.None;
                ps.Dock = Autodesk.AutoCAD.Windows.DockSides.None;
                ps.Text = "Edit attributes";
            }
            if (ps.Count > 0) ps.Remove(0);
            //ObjectId ObjId = SelectBlock();
            //if (!ObjId.IsNull) CreateControls(ObjId);
            ps.Visible = true;
            try { ps.AutoRollUp = true; }
            catch { }
            if (FirstLoad)
            {
                foreach (Document Doc in AcadApp.DocumentManager)
                {
                    Doc.Editor.SelectionAdded += new SelectionAddedEventHandler(SelectionMade);
                    //Doc.LispWillStart += new LispWillStartEventHandler(onLispStart);
                    //Doc.CommandWillStart += new CommandEventHandler(onCommandStart);
                    //Doc.CommandCancelled += new CommandEventHandler(onCommandDone);
                    //Doc.CommandEnded += new CommandEventHandler(onCommandDone);
                    //Doc.CommandFailed += new CommandEventHandler(onCommandDone);
                    //Doc.LispCancelled += new EventHandler(onLispDone);
                    //Doc.LispEnded += new EventHandler(onLispDone);
                }
                AcadApp.DocumentManager.DocumentCreated += new DocumentCollectionEventHandler(onDocCreated);
                AcadApp.DocumentManager.DocumentToBeDestroyed += new DocumentCollectionEventHandler(onDocToBeDestroyed);
                AcadApp.DocumentManager.DocumentBecameCurrent += new DocumentCollectionEventHandler(onDocBecameCurrent);
                FirstLoad = false;
            }
        }

        public [color=blue]static [/color] void CreateControls(ObjectId ObjId)
        {
            using (DocumentLock DocLock = AcadApp.DocumentManager.MdiActiveDocument.LockDocument())
            {
                AttributeDefinition AttDef = null;
                Document Doc = AcadApp.DocumentManager.MdiActiveDocument;
                Point StPt = new System.Drawing.Point(2, 30);
                uc = new UserControl1();
                using (Transaction Trans = AcadApp.DocumentManager.MdiActiveDocument.TransactionManager.StartTransaction())
                {
                    BlockTable BlkTbl = (BlockTable)Trans.GetObject(Doc.Database.BlockTableId, OpenMode.ForRead);
                    BlockReference BlkRef = (BlockReference)Trans.GetObject(ObjId, OpenMode.ForWrite);
                    BlockTableRecord BlkTblRec = (BlockTableRecord)Trans.GetObject(BlkRef.BlockTableRecord, OpenMode.ForRead);
                    Autodesk.AutoCAD.DatabaseServices.AttributeCollection AttCol = BlkRef.AttributeCollection;
                    foreach (ObjectId id in AttCol)
                    {
                        AttributeReference AttRef = (AttributeReference)Trans.GetObject(id, OpenMode.ForRead);
                        foreach (ObjectId tempId in BlkTblRec)
                        {
                            AttDef = Trans.GetObject(tempId, OpenMode.ForRead) as AttributeDefinition;
                            if (AttDef != null && string.Compare(AttDef.Tag, AttRef.Tag) == 0)
                            {
                                CreateComboBoxAndLabel(AttDef.Prompt, AttRef.TextString, AttRef.ObjectId, StPt, uc);
                                break;
                            }
                        }
                        if (AttDef == null) CreateComboBoxAndLabel(AttRef.Tag, AttRef.TextString, AttRef.ObjectId, StPt, uc);
                        AttDef = null;
                        StPt = new System.Drawing.Point(StPt.X, StPt.Y + 30);
                    }
                }
                OkBut = new System.Windows.Forms.Button();
                OkBut.Text = "Apply to block";
                OkBut.Name = "Okbutton";
                OkBut.BackColor = System.Drawing.Color.Silver;
                OkBut.ForeColor = System.Drawing.Color.Navy;
                OkBut.Location = new System.Drawing.Point(5, 0);
                OkBut.Size = new System.Drawing.Size(220, 25);
                OkBut.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right | System.Windows.Forms.AnchorStyles.Top)));
                OkBut.Click += new System.EventHandler(OkayButtonClick);
                uc.Controls.Add(OkBut);
                uc.Resize += new System.EventHandler(FormResized);
                uc.AutoScroll = true;
                uc.AutoScrollMinSize = new System.Drawing.Size(0, 400);
                uc.VScroll = true;
                uc.HScroll = false;
                if (ps.Count > 0) ps.Remove(0);
                ps.Add("Test", uc);
            }
        }

        public [color=blue]static [/color] void CreateComboBoxAndLabel(string cbName, string cbValue, object Obj, Point pt, UserControl1 uc)
        {
            ComboBox cb = new System.Windows.Forms.ComboBox();
            cb.BackColor = System.Drawing.Color.Silver;
            cb.ForeColor = System.Drawing.Color.Navy;
            cb.Name = cbName;
            cb.Text = cbValue;
            cb.Location = pt;
            cb.Size = new System.Drawing.Size(150, 25);
            cb.DropDownStyle = System.Windows.Forms.ComboBoxStyle.Simple;
            cb.Tag = Obj;

            Label lb = new System.Windows.Forms.Label();
            lb.Name = cbName;
            lb.Text = cbName;
            lb.Height = 20;
            lb.Size = new System.Drawing.Size(200, 25);
            lb.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
            lb.Location = new System.Drawing.Point(pt.X + 5 + cb.Size.Width, pt.Y);

            uc.Controls.Add(cb);
            uc.Controls.Add(lb);
        }

        public [color=blue]static [/color] void OkayButtonClick(object sender, System.EventArgs e)
        {
            Document Doc = AcadApp.DocumentManager.MdiActiveDocument;
            using (DocumentLock DocLock = Doc.LockDocument())
            {
                ControlCollection CtrlCol = uc.Controls;
                using (Transaction Trans = Doc.TransactionManager.StartTransaction())
                {
                    foreach (Control Ctrl in CtrlCol)
                    {
                        try
                        {
                            if (Ctrl.Tag != null)
                            {
                                ObjectId ObjId = (ObjectId)Ctrl.Tag;
                                AttributeReference AttRef = Trans.GetObject(ObjId, OpenMode.ForWrite) as AttributeReference;
                                if (string.Compare(AttRef.TextString, Ctrl.Text) != 0)
                                    AttRef.TextString = Ctrl.Text;
                            }
                        }
                        catch { MessageBox.Show("Could not update attribute value."); }
                    }
                    Trans.Commit();
                }
            }
        }

        public [color=blue]static [/color] void FormResized(object sender, System.EventArgs e)
        {
            OkBut.Size = new System.Drawing.Size(uc.Width - 15, 25);
        }

        // Not used.
        public ObjectId SelectBlock()
        {
            Document Doc = AcadApp.DocumentManager.MdiActiveDocument;
            Editor Ed = Doc.Editor;
            PromptEntityOptions Opts = new PromptEntityOptions("\n Select block: ");
            Opts.SetRejectMessage("\n Entity not a block.");
            Opts.AddAllowedClass(typeof(BlockReference), false);
            PromptEntityResult Rslt = Ed.GetEntity(Opts);
            return Rslt.ObjectId;
        }

        public [color=blue]static  [/color] void SelectionMade(object sender, SelectionAddedEventArgs e)
        {
            if (!ps.Visible || string.Compare(AcadApp.GetSystemVariable("CmdActive").ToString(), "0") != 0) return;
            if (e.Selection.Count == 0 && e.AddedObjects.Count != 0)
            {
                FillInControl(e.AddedObjects.GetObjectIds());
            }
            else if (ps.Count > 0) ps.Remove(0);
        }

        public [color=blue]static [/color] void FillInControl(ObjectId[] ObjIdArray)
        {
            ObjectId BlkId = ObjectId.Null;
            int BlkCnt = 0;
            using (Transaction Trans = AcadApp.DocumentManager.MdiActiveDocument.TransactionManager.StartTransaction())
            {
                foreach (ObjectId ObjId in ObjIdArray)
                {
                    BlockReference BlkRef = Trans.GetObject(ObjId, OpenMode.ForRead) as BlockReference;
                    if (BlkRef != null && BlkRef.AttributeCollection.Count > 0)
                    {
                        ++BlkCnt;
                        BlkId = ObjId;
                        if (BlkCnt > 1) break;
                    }
                }
            }
            if (BlkCnt == 1) CreateControls(BlkId);
            else if (ps.Count > 0 && BlkCnt != 1) ps.Remove(0);
        }

        public [color=blue]static [/color] void onDocCreated(object sender, DocumentCollectionEventArgs e)
        {
            Document newDoc = e.Document;
            newDoc.Editor.SelectionAdded += new SelectionAddedEventHandler(SelectionMade);
        }

        public [b]static [/b] void onDocToBeDestroyed(object sender, DocumentCollectionEventArgs e)
        {
            Document Doc = e.Document;
            Doc.Editor.SelectionAdded -= new SelectionAddedEventHandler(SelectionMade);
        }

        public [color=blue]static  [/color] void onDocBecameCurrent(object sender, DocumentCollectionEventArgs e)
        {
            if (!ps.Visible) return;
            PromptSelectionResult psr = e.Document.Editor.SelectImplied() as PromptSelectionResult;
            if (psr == null) return;
            SelectionSet ss = psr.Value as SelectionSet;
            if (ss != null && ss.Count > 0) FillInControl(ss.GetObjectIds());
            else if (ps.Count > 0) ps.Remove(0);
        }
    }
}
« Last Edit: June 06, 2007, 11:41:02 PM by LE »

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Tool palette, Object selection and Event
« Reply #43 on: June 07, 2007, 10:56:26 AM »
Thanks Luis!  I don't know how long it would have taken to try that.  I was trying to find a way to make the 'CommandMethod' static, in stead of the functions that are used within the CommandMethod.  Now to go back and reread Tony's comments.

This is getting more exciting.  :-)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Tool palette, Object selection and Event
« Reply #44 on: June 07, 2007, 12:39:59 PM »
Luis,

After putting the static modifier in the calls to the methods of the UserControl1 class, I had to change some of the calls within the calls.  In the book that Glenn referred to me "Pro C-sharp 2005 and the dotNet2.0 Platform" it states
Quote from: CHAPTER 3 ■ C# LANGUAGE FUNDAMENTALS, Page 84
■Note Allow me to repeat myself. Static members can operate only on static class members. If you attempt to
make use of nonstatic class members (also called instance data) within a static method, you receive a compiler error.

Edit:  Removed old code.
« Last Edit: June 14, 2007, 01:09:18 PM by T.Willey »
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.