Author Topic: Cannot set MdiActiveDocument  (Read 24784 times)

0 Members and 1 Guest are viewing this topic.

Mike Leslie

  • Guest
Cannot set MdiActiveDocument
« on: August 22, 2013, 04:32:16 PM »
I cannot seem to set the MdiActiveDocument synchronously.

I have code inside a <CommandMethod> that creates a drawing and then writes any error information to the command line.  Since this is started in one document, if  a fatal error occurs and the drawing does not get created, that message goes to the original document's command line.

In the case where a drawing gets created with errors (say partial success), I would like the errors to appear in the new drawing (new active document's) command line.

The behavior when setting Core.Application.DocumentManager.MdiActiveDocument is peculiar.  The application can hang for a long time if you do not click anything.  If you click the document (from the taskbar or clicking on the window), it breaks out of the hang and continues to execute, but the active document is not changed.  The MdiActiveDocument still points to the original document.  You can also see that it does not change because doc.IsActive = False.  This state could be because when you clicked, you really did make the original document active (again? still?).  To break the hang, I think the click has to be on the original document.

On an example like http://www.theswamp.org/index.php?topic=44476.msg497357#msg497357 there is no action taken after MdiActiveDocument is set, so I assume that it is actually set when the command is completed, not synchronously.  I am not absolutely certain of this, though.

Code: [Select]

    <CommandMethod("AUTODRAWPN")> _
    Public Sub DrawPartNumber()
        Dim ed As Editor = Core.Application.DocumentManager.MdiActiveDocument.Editor

        If IsNothing(drwr) Then
            Try
                InitalizeAutodraw()
            Catch ex As System.Exception
                'exit quietly if it is cancelled by the user
                'print the error if an exception happened
                If ex.GetType <> GetType(OperationCanceledException) Then
                    ed.WriteMessage("Error: " & ex.Message)
                End If
                Exit Sub
            End Try
        End If

        Try
            Dim pr As PromptResult = ed.GetString("Part number to draw: ")
            If pr.Status <> PromptStatus.OK Then Exit Sub

            Dim doc As Document = drwr.CreateByPartNumber(pr.StringResult)
            'Core.Application.DocumentManager.MdiActiveDocument = doc       'does not work

            If drwr.Errors.Count > 0 Then
                ed = Core.Application.DocumentManager.MdiActiveDocument.Editor
                ed.WriteMessage("Autodraw Error(s):" & vbCrLf & String.Join(vbCrLf, drwr.Errors))
                ed.WriteMessage(vbCrLf)
            End If

        Catch ex As System.Exception
            ed.WriteMessage("Error: " & ex.Message)
        End Try

    End Sub


Is there a way to set the MDIActiveDocument?  Should it be hanging like this?  Should I be looking at an altogether different way to handle this?

Trying to use doc.Editor without setting the active causes a eNotApplicable error, so that is not a way out.

I am using AutoCAD 2013.  The following link implies that this could be a 2013 specific problem, but I do not know that for sure.
http://forums.autodesk.com/t5/NET/MDIActiveDocument-and-DocumentActivated/td-p/3629886

Thanks for whatever you guys can tell me!!

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: Cannot set MdiActiveDocument
« Reply #1 on: August 22, 2013, 04:41:20 PM »
I ran into issues with existing code when I migrated it to 2013 that stem from this exact issue. In prior versions, MdiActiveDocument becomes active much earlier in the process than it does in 2013+. I don't know what or why it was changed, but I had to do a lot of rewriting in order to get all of my code working properly.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Cannot set MdiActiveDocument
« Reply #2 on: August 22, 2013, 06:23:50 PM »
Have you tried setting or checking DocumentCollection.DocumentActivationEnabled property?
Code - C#: [Select]
  1.             DocumentCollection docMgr = Application.DocumentManager;
  2.             Document doc = docMgr.Add("gjghjghjghjghjgjhgjhgj");
  3.             if (!docMgr.DocumentActivationEnabled)
  4.             {
  5.                 docMgr.DocumentActivationEnabled = true;
  6.             }
  7.             docMgr.MdiActiveDocument = doc;
  8.  

BlackBox

  • King Gator
  • Posts: 3770
Re: Cannot set MdiActiveDocument
« Reply #3 on: August 22, 2013, 07:48:24 PM »
... You two (Jeff & Jeff respectively  :-P), are endless sources of API knowledge; it's pretty schnazzy.  :mrgreen:
"How we think determines what we do, and what we do determines what we get."

Mike Leslie

  • Guest
Re: Cannot set MdiActiveDocument
« Reply #4 on: August 23, 2013, 08:20:53 AM »


DocumentActivationEnabled is already true in my code, but thanks for the idea.

Jeff_M

  • King Gator
  • Posts: 4087
  • C3D user & customizer
Re: Cannot set MdiActiveDocument
« Reply #5 on: August 23, 2013, 09:45:44 AM »
Jeff, a simple example. In versions prior to 2013 this DocumentActivated event handler would return the same values for the 2 string variables:
Code - C#: [Select]
  1. static void DocumentManager_DocumentCreated(object sender, DocumentCollectionEventArgs e)
  2.         {
  3.             Document doc = e.Document;
  4.             string docname = doc.Name;
  5.             string activedocname = Application.DocumentManager.MdiActiveDocument.Name;
  6.          }
  7.  
But in 2013 & 2014 this shows docname  as the new document but the ActiveDocument name is still the name of the drawing the command was invoked from.
Code - C#: [Select]
  1. static void DocumentManager_DocumentCreated(object sender, DocumentCollectionEventArgs e)
  2.         {
  3.             Document doc = e.Document;
  4.             string docname = doc.Name;
  5.             string activedocname = AcCore.Application.DocumentManager.MdiActiveDocument.Name;
  6.          }
  7.  

Mike Leslie

  • Guest
Re: Cannot set MdiActiveDocument
« Reply #6 on: August 23, 2013, 03:29:02 PM »
I got it !!   :kewl:

The key was to declare my function as

 <CommandMethod("AUTODRAWPN", CommandFlags.Session)>

rather than

 <CommandMethod("AUTODRAWPN")>

This indicates that that the context is the entire AutoCAD session rather than running in only a specific document.  Now when I set MdiActiveDocument it takes and I can send my results to the correct Editor.

In fact, if I want, I don't even have to set the active document, since I now can write to doc.Editor without getting an eNotApplicable error.  This attribute definately opens up more cross-document abilities.

« Last Edit: August 23, 2013, 03:33:57 PM by Mike Leslie »

mohnston

  • Bull Frog
  • Posts: 305
  • CAD Programmer
Re: Cannot set MdiActiveDocument
« Reply #7 on: October 03, 2013, 02:57:18 PM »
I ran into issues with existing code when I migrated it to 2013 that stem from this exact issue. In prior versions, MdiActiveDocument becomes active much earlier in the process than it does in 2013+. I don't know what or why it was changed, but I had to do a lot of rewriting in order to get all of my code working properly.
I just hit this land mine on a project. Was there no other way to set the active document to the . . um . . active document?
It worked properly prior to 2013.
I also tried Autodesk.AutoCAD.Internal.Utils.ActivateDocument(mydoc.Window.Handle) but that did not make it the active document either.
I'm facing the "a lot of rewriting" option if not and that's not good.
It's amazing what you can do when you don't know what you can't do.
CAD Programming Solutions

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Cannot set MdiActiveDocument
« Reply #8 on: October 03, 2013, 04:01:05 PM »
It's strange the way it works now, but it seems you have to kill your thread and let the system do it's work.  I've found one way to achieve this is to set the active document in a function, end it, then continue work on a callback from the Application.Idle event  :ugly:

Bryco

  • Water Moccasin
  • Posts: 1882
Re: Cannot set MdiActiveDocument
« Reply #9 on: October 08, 2013, 09:19:27 PM »
Will 
Code: [Select]
callback from the Application.Idle event  :ugly: I'm having a bit of trouble with.

Had some simple code that worked fine and now doesn't.
Basically 1) browse to a Library folder
2) open a drawing (calling zoomextents and a messagebox asking if you want to insert the dwg).
3) Close and discard
4) If no return  if yes insert the dwg  into the blocks.
5) Make a call to idle events and use a jig to insert the block.

If I use CommandFlags.Session I cannot get the jig to work at all,
if not, everything works but on closing cad the autocad has stopped working error comes up.

As you can see I have used Tony's
Idle events helper class

Code: [Select]
       [CommandMethod("Library")]
       // [CommandMethod("Library", CommandFlags.Session)]
        public void Library()
        {
            if(Library2())
                IdleEvents.Add(acadApp_Idle);
        }

        public bool Library2()
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            ObjectId BlockId = ObjectId.Null;
          // using (doc.LockDocument())
          // {
                string sPath = Util.Get.LibraryPath();
                OpenFileDialog openFileDia = new OpenFileDialog();
                string sFile = "";
                openFileDia.InitialDirectory = sPath + "Hardware\\";
                openFileDia.Filter = "Drawing (*.dwg)|*.dwg|All files (*.*)|*.*";
                openFileDia.Multiselect = false;
                openFileDia.RestoreDirectory = true;
                if (openFileDia.ShowDialog() == DialogResult.OK)
                {
                    sFile = openFileDia.FileName;
                }

                if (string.IsNullOrEmpty(sFile)) return false;
                string sBlock = Path.GetFileNameWithoutExtension(sFile);

                //if (!Openit(sFile, sBlock))
                //    return;
                bool isT = false;
                DocumentCollection docs = acadApp.DocumentManager;
                Document docBlock = docs.Open(sFile, true);
                string msg = "Would you like to insert the drawing " + sBlock + " as a block?";
                DialogResult res = MessageBox.Show(msg, "Find block", MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
                if (res == DialogResult.Yes) isT = true;
                docBlock.CloseAndDiscard();
                docs.MdiActiveDocument = doc;
                if (!isT) return false;
               
                Database db = doc.Database;               
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                    if (bt.Has(sBlock))
                    {
                        BlockId = bt[sBlock];
                        tr.Commit();
                        goto Insert;
                    }
                }

                using (Database dbase = new Database(false, true))
                {
                    try
                    {
                        dbase.ReadDwgFile(sFile, System.IO.FileShare.Read, false, "");
                        BlockId = db.Insert(sBlock, dbase, false);
                        dbase.CloseInput(true);
                    }
                    catch (System.Exception EX)
                    {
                        dbase.CloseInput(true);
                        Util.Debug.Print(EX.Message);
                        acadApp.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nThe path is incorrect.");
                        return false;
                        //throw;
                    }
                }
           //}
            Insert:
            libBlockid = BlockId;
            return true;
        }



        void acadApp_Idle(object sender, EventArgs e)
        {
            Document doc = acadApp.DocumentManager.MdiActiveDocument;
            using (doc.LockDocument())
            {
                if (libBlockid != ObjectId.Null) JigNew.InsertBlockJiggy.Insert(libBlockid, false, "", scalefactor);
            }
                //throw new NotImplementedException();
                IdleEvents.Remove(acadApp_Idle);
        }//end Library






        //Tony http://www.theswamp.org/index.php?topic=41536.msg466400#msg466400
    public static class IdleEvents
    {
        static List<EventHandler> queue = new List<EventHandler>();
        static bool idleHandled = false;

        static void onIdle( object sender, EventArgs e )
        {
          SetHandled( false );
          EventHandler[] array = queue.ToArray();
          queue.Clear();
          try
            {
                foreach( EventHandler handler in array )
                  handler( sender, e );
            }
        finally
          {
            SetHandled( queue.Count > 0 );
         }
        }

 
        static void SetHandled( bool handle )
        {
          if( handle ^ idleHandled )
          {
            if( handle )
            {
             idleHandled = true;
              acadApp.Idle += onIdle;
           }
           else
            {
              idleHandled = false;
             acadApp.Idle -= onIdle;
           }
          }
    }

 

    public static void Add( EventHandler handler )
    {
      if( handler == null )
       throw new ArgumentNullException( "handler" );
      if( ! queue.Contains( handler ) )
      {
       queue.Add( handler );
       SetHandled( queue.Count > 0 );
     }
   }

    public static void Remove( EventHandler handler )

   {
      queue.Remove( handler );

      SetHandled( queue.Count > 0 );
    }

  }





        public static bool Openit(string sFile, string sBlock)
        {
            DocumentCollection docs = acadApp.DocumentManager;
            Document docBlock = docs.Open(sFile, true);
            bool isT = false;
            using (docBlock.LockDocument())
            {
               
                string msg = "Would you like to insert the drawing " + sBlock + " as a block?";
                DialogResult res = MessageBox.Show(msg, "Find block", MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
                if (res == DialogResult.Yes) isT = true;
                //docBlock.CloseAndDiscard();
            }
             DocumentExtension.CloseAndDiscard(docBlock);
         
            return isT;

        } // end Openit


JigNew.InsertBlockJiggy.Insert(libBlockid, false, "", scalefactor);  is a call to  a jig that works fine but uses the editor like all jigs.
« Last Edit: October 08, 2013, 09:22:43 PM by Bryco »

Jeff H

  • Needs a day job
  • Posts: 6144
Re: Cannot set MdiActiveDocument
« Reply #10 on: October 09, 2013, 11:33:37 AM »
I started this last week and never finished and forgot about it.
 
Wrote some test commands that would add new a document and prompt for a string with Session flag set or not, from new and original document's editor, delegating it to DocumentManager.ExecuteInApplicationContext or not.
 
So I got different result for combinations of the following.
 
   
  • If CommandFlags.Session is set
  • If Adding the new document and setting active document is delegated using DocumentManager.ExecuteInApplicationContext
  • The editor of the document used to prompt for the string I got different results.
The comments above each method should explain its behavior.
 
All the commands
   1.) Add a new document(Used a named that would fail so would revert back to using default template)
   2.) Prompt user for a string from using either the
        a.) Editor of the document that issued the command
             or
        b.) Editor of the newly added document
 
 
 
 
I needed to come up with better naming scheme but never got around to changing to them.
 
The name of the commands follow this scheme
AddDoc_(Document or Application depending on context)_(Initial or New depending on which document the editor prompts for string)
So
AddDoc_Application_Initial - has CommandFlags.Session and prompts from the Editor of document the command started in.
 
There are another set of commands that are follow same naming scheme but start with
AddDoc_Delegated which uses DocumentManager.ExecuteInApplicationContext to call function to add a document set the active document.
 
Code - C#: [Select]
  1.  
  2.          ////// - Switches to new Document
  3.         ////// - Switches back to initial Document
  4.         ////// - Prompted for string
  5.         [CommandMethod("AddDoc_Document_Initial")]
  6.         public void AddDoc_Document_Initial()
  7.         {
  8.             Document doc = Application.DocumentManager.MdiActiveDocument;
  9.             Application.DocumentManager.Add("ButtFart.dwt");
  10.             var s = doc.Editor.GetString("\n").StringResult;
  11.         }
  12.  
  13.         ////////error
  14.         [CommandMethod("AddDoc_Application_Initial", CommandFlags.Session)]
  15.         public void AddDoc_Application_Initial()
  16.         {
  17.             Document doc = Application.DocumentManager.MdiActiveDocument;
  18.            Application.DocumentManager.Add("ButtFart.dwt");
  19.            var s = doc.Editor.GetString("\n").StringResult;
  20.         }
  21.         ////// - Switches to new Document
  22.         ////// - If you manually switch back to initial document you will be prompted for string
  23.         [CommandMethod("AddDoc_Delegated_Document_Initial")]
  24.         public void AddDoc_Delegated_Document_Initial()
  25.         {
  26.             Document doc = Application.DocumentManager.MdiActiveDocument;
  27.             Application.DocumentManager.ExecuteInApplicationContext(createNewDoc, null);
  28.             var s = doc.Editor.GetString("\n").StringResult;
  29.         }
  30.         ////// - Prompted for string
  31.         ////// - Switches to new Document
  32.         [CommandMethod("AddDoc_Delegated_Application_Initial", CommandFlags.Session)]
  33.         public void AddDoc_Delegated_Application_Initial()
  34.         {
  35.             Document doc = Application.DocumentManager.MdiActiveDocument;
  36.             Application.DocumentManager.ExecuteInApplicationContext(createNewDoc, null);
  37.             var s = doc.Editor.GetString("\n").StringResult;
  38.         }
  39.  
  40.  
  41.         ////////error
  42.         [CommandMethod("AddDoc_Document_New")]
  43.         public void AddDoc_Document_New()
  44.         {
  45.             Document doc = Application.DocumentManager.Add("ButtFart.dwt");
  46.             var s = doc.Editor.GetString("\n").StringResult;
  47.         }
  48.         ////// - Switches to new Document
  49.         ////// - Prompted for string
  50.         [CommandMethod("AddDoc_Application_New", CommandFlags.Session)]
  51.         public void AddDoc_Application_New()
  52.         {
  53.             Document doc = Application.DocumentManager.Add("ButtFart.dwt");
  54.             var s = doc.Editor.GetString("\n").StringResult;
  55.         }
  56.         ////// - Switches to new Document
  57.         ////// - ERROR If you manually switch back to initial document you will be prompted for string
  58.         [CommandMethod("AddDoc_Delegated_Document_New")]
  59.         public void AddDoc_Delegated_Document_New()
  60.         {
  61.             Application.DocumentManager.ExecuteInApplicationContext(createNewDoc, null);
  62.             var s = newDoc.Editor.GetString("\n").StringResult;
  63.         }
  64.         [CommandMethod("AddDoc_Delegated_Application_New", CommandFlags.Session)]
  65.         public void AddDoc_Delegated_Application_New()
  66.         {
  67.             Application.DocumentManager.ExecuteInApplicationContext(createNewDoc, null);
  68.             var s = newDoc.Editor.GetString("\n").StringResult;
  69.         }
  70.  
  71.         private Document newDoc = null;
  72.         private void createNewDoc(object userdata)
  73.         {
  74.             newDoc = Application.DocumentManager.Add("ButtFart.dwt");
  75.             Application.DocumentManager.MdiActiveDocument = newDoc;
  76.         }
  77.  

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: Cannot set MdiActiveDocument
« Reply #11 on: October 09, 2013, 03:08:55 PM »
Jeff H, was your post a question or a statement?  I hesitate to assume your asking a question since its rare that I would know the answer and you wouldn't.  :-)
Revit 2019, AMEP 2019 64bit Win 10

Bryco

  • Water Moccasin
  • Posts: 1882
Re: Cannot set MdiActiveDocument
« Reply #12 on: October 09, 2013, 04:33:42 PM »
I think the hard part is using the editor of the original dwg,
the comparisons you have made are cool though

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Cannot set MdiActiveDocument
« Reply #13 on: October 09, 2013, 10:10:14 PM »
Bryco, I haven't had a chance to compile but at first glance I noticed that you aren't using tony's class properly. It automatically removes the event handler for you.
I have run into a similar error when creating overrule classes that weren't properly disposed, it is a very tricky error to track down.

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: Cannot set MdiActiveDocument
« Reply #14 on: October 10, 2013, 01:47:04 AM »
Bryco,

I played with your code.  Since you didn't include your jig I borrowed one from Kean at through the interface to play with your problem.

I could not get the newly opened document to display properly without commandflags.session set so I packaged the whole thing into a single function and had no issues running the jig or any issues closing autocad afterwards.  I suspect the issue you're running into is buried in one of your other classes.  Here's what I ended up with and it works fairly well:

Code - C#: [Select]
  1.     public class testing
  2.     {
  3.         [CommandMethod("Library", CommandFlags.Session)]
  4.         public void Library()
  5.         {
  6.             string sBlock;
  7.             string sFile;
  8.             Document doc;
  9.             Document docBlock;
  10.             ObjectId libBlockid;
  11.             doc = acadApp.DocumentManager.MdiActiveDocument;
  12.             string sPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
  13.             OpenFileDialog openFileDia = new OpenFileDialog();
  14.             openFileDia.InitialDirectory = sPath;
  15.             openFileDia.Filter = "Drawing (*.dwg)|*.dwg|All files (*.*)|*.*";
  16.             openFileDia.Multiselect = false;
  17.             openFileDia.RestoreDirectory = true;
  18.             if (openFileDia.ShowDialog() != DialogResult.OK) return;
  19.             sFile = openFileDia.FileName;
  20.             sBlock = Path.GetFileNameWithoutExtension(sFile);
  21.             docBlock = acadApp.DocumentManager.Open(sFile, true);
  22.             acadApp.DocumentManager.MdiActiveDocument = docBlock;
  23.             //Using a keyword prompt leaves the user free to zoom around the drawing and inspect it further if the initial view isn't enough
  24.             PromptKeywordOptions pko = new PromptKeywordOptions("\nPress ENTER to insert the drawing " + sBlock + " as a block?\nPress ESCAPE to cancel");
  25.             pko.AllowNone = true;
  26.             pko.AllowArbitraryInput = true;
  27.             if (docBlock.Editor.GetKeywords(pko).Status == PromptStatus.Cancel)
  28.             {
  29.                 docBlock.CloseAndDiscard();
  30.                 return;
  31.             }
  32.             using (doc.LockDocument())
  33.             {
  34.                 Database db = doc.Database;
  35.  
  36.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  37.                 {
  38.                     BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  39.                     if (bt.Has(sBlock))
  40.                         libBlockid = bt[sBlock];
  41.                     else
  42.                         libBlockid = db.Insert(sBlock, docBlock.Database, true);
  43.                     tr.Commit();
  44.                 }
  45.             }
  46.             acadApp.DocumentManager.MdiActiveDocument = doc;
  47.             docBlock.CloseAndDiscard();
  48.             using (doc.LockDocument())
  49.             {
  50.                 if (libBlockid == ObjectId.Null) return; // JigNew.InsertBlockJiggy.Insert(libBlockid, false, "", scalefactor);
  51.                 #region code to set up Keans jig
  52.                 using (Transaction tr = doc.TransactionManager.StartTransaction())
  53.                 {
  54.                     BlockTableRecord space = (BlockTableRecord)tr.GetObject(doc.Database.CurrentSpaceId, OpenMode.ForWrite);
  55.                     BlockReference br =
  56.                       new BlockReference(new Point3d(), libBlockid);
  57.                     space.AppendEntity(br);
  58.                     tr.AddNewlyCreatedDBObject(br, true);
  59.  
  60.                     Dictionary<ObjectId, AttInfo> attInfo =
  61.                       new Dictionary<ObjectId, AttInfo>();
  62.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(libBlockid, OpenMode.ForRead);
  63.                     if (btr.HasAttributeDefinitions)
  64.                     {
  65.                         foreach (ObjectId id in btr)
  66.                         {
  67.                             DBObject obj =
  68.                               tr.GetObject(id, OpenMode.ForRead);
  69.                             AttributeDefinition ad =
  70.                               obj as AttributeDefinition;
  71.  
  72.                             if (ad != null && !ad.Constant)
  73.                             {
  74.                                 AttributeReference ar =
  75.                                   new AttributeReference();
  76.  
  77.                                 ar.SetAttributeFromBlock(ad, br.BlockTransform);
  78.                                 ar.Position =
  79.                                   ad.Position.TransformBy(br.BlockTransform);
  80.  
  81.                                 if (ad.Justify != AttachmentPoint.BaseLeft)
  82.                                 {
  83.                                     ar.AlignmentPoint =
  84.                                       ad.AlignmentPoint.TransformBy(br.BlockTransform);
  85.                                 }
  86.                                 if (ar.IsMTextAttribute)
  87.                                 {
  88.                                     ar.UpdateMTextAttribute();
  89.                                 }
  90.  
  91.                                 ar.TextString = ad.TextString;
  92.  
  93.                                 ObjectId arId =
  94.                                   br.AttributeCollection.AppendAttribute(ar);
  95.                                 tr.AddNewlyCreatedDBObject(ar, true);
  96.  
  97.                                 // Initialize our dictionary with the ObjectId of
  98.                                 // the attribute reference + attribute definition info
  99.  
  100.                                 attInfo.Add(
  101.                                   arId,
  102.                                   new AttInfo(
  103.                                     ad.Position,
  104.                                     ad.AlignmentPoint,
  105.                                     ad.Justify != AttachmentPoint.BaseLeft
  106.                                   )
  107.                                 );
  108.                             }
  109.                         }
  110.                     }
  111.                 #endregion
  112.                     // Run the jig
  113.                     BlockJig myJig = new BlockJig(tr, br, attInfo);
  114.  
  115.                     if (myJig.Run() != PromptStatus.OK)
  116.                         return;
  117.                     tr.Commit();
  118.                 }
  119.             }
  120.             //throw new NotImplementedException();
  121.             //IdleEvents.Remove(acadApp_Idle); <------------- not neccessary, Tony's class takes care of this.
  122.         }//end Library
  123.         #region A jig borrowed from Kean for the purpose of playing here
  124.         class AttInfo
  125.         {
  126.             private Point3d _pos;
  127.             private Point3d _aln;
  128.             private bool _aligned;
  129.  
  130.             public AttInfo(Point3d pos, Point3d aln, bool aligned)
  131.             {
  132.                 _pos = pos;
  133.                 _aln = aln;
  134.                 _aligned = aligned;
  135.             }
  136.  
  137.             public Point3d Position
  138.             {
  139.                 set { _pos = value; }
  140.                 get { return _pos; }
  141.             }
  142.  
  143.             public Point3d Alignment
  144.             {
  145.                 set { _aln = value; }
  146.                 get { return _aln; }
  147.             }
  148.  
  149.             public bool IsAligned
  150.             {
  151.                 set { _aligned = value; }
  152.                 get { return _aligned; }
  153.             }
  154.         }
  155.  
  156.         class BlockJig : EntityJig
  157.         {
  158.             private Point3d _pos;
  159.             private Dictionary<ObjectId, AttInfo> _attInfo;
  160.             private Transaction _tr;
  161.  
  162.             public BlockJig(
  163.               Transaction tr,
  164.               BlockReference br,
  165.               Dictionary<ObjectId, AttInfo> attInfo
  166.             )
  167.                 : base(br)
  168.             {
  169.                 _pos = br.Position;
  170.                 _attInfo = attInfo;
  171.                 _tr = tr;
  172.             }
  173.  
  174.             protected override bool Update()
  175.             {
  176.                 BlockReference br = Entity as BlockReference;
  177.  
  178.                 br.Position = _pos;
  179.  
  180.                 if (br.AttributeCollection.Count != 0)
  181.                 {
  182.                     foreach (ObjectId id in br.AttributeCollection)
  183.                     {
  184.                         DBObject obj =
  185.                           _tr.GetObject(id, OpenMode.ForRead);
  186.                         AttributeReference ar =
  187.                           obj as AttributeReference;
  188.  
  189.                         // Apply block transform to att def position
  190.  
  191.                         if (ar != null)
  192.                         {
  193.                             ar.UpgradeOpen();
  194.                             AttInfo ai = _attInfo[ar.ObjectId];
  195.                             ar.Position =
  196.                               ai.Position.TransformBy(br.BlockTransform);
  197.                             if (ai.IsAligned)
  198.                             {
  199.                                 ar.AlignmentPoint =
  200.                                   ai.Alignment.TransformBy(br.BlockTransform);
  201.                             }
  202.                             if (ar.IsMTextAttribute)
  203.                             {
  204.                                 ar.UpdateMTextAttribute();
  205.                             }
  206.                         }
  207.                     }
  208.                 }
  209.                 return true;
  210.             }
  211.  
  212.             protected override SamplerStatus Sampler(JigPrompts prompts)
  213.             {
  214.                 JigPromptPointOptions opts =
  215.                   new JigPromptPointOptions("\nSelect insertion point:");
  216.                 opts.BasePoint = new Point3d(0, 0, 0);
  217.                 opts.UserInputControls =
  218.                   UserInputControls.NoZeroResponseAccepted;
  219.  
  220.                 PromptPointResult ppr = prompts.AcquirePoint(opts);
  221.  
  222.                 if (_pos == ppr.Value)
  223.                 {
  224.                     return SamplerStatus.NoChange;
  225.                 }
  226.  
  227.                 _pos = ppr.Value;
  228.  
  229.                 return SamplerStatus.OK;
  230.             }
  231.  
  232.             public PromptStatus Run()
  233.             {
  234.                 Document doc =
  235.                   acadApp.DocumentManager.MdiActiveDocument;
  236.                 Editor ed = doc.Editor;
  237.  
  238.                 PromptResult promptResult = ed.Drag(this);
  239.                 return promptResult.Status;
  240.             }
  241.         }
  242.         #endregion

If you want a closer look at your jig implementation let me know