Author Topic: ObjectDBX and Attributes  (Read 27352 times)

0 Members and 1 Guest are viewing this topic.

T.Willey

  • Needs a day job
  • Posts: 5251
ObjectDBX and Attributes
« on: August 24, 2006, 03:49:28 PM »
I know in lisp, and VBA if the alignment of attributes is anything but left, then they do not update correctly.  Is this true for .Net also?  I hope not.  I haven't done any testing yet, as this is above my level right now, but if the alignment issue is a non-issue, then I will be looking into this for some routines that I have now.

Thanks.

Edit:  In my searchs of the net I haven't found an answer yet.
Tim

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

Please think about donating if this post helped you.

Cathy

  • Guest
Re: ObjectDBX and Attributes
« Reply #1 on: August 24, 2006, 05:06:44 PM »
I just feel certain that .net will not help this -- it's not the language that you use to change the attribute, it's the way Autocad handles the change. 

If you use the ATTSYNC command after you open the drawing, Autocad will rejustify the attributes correctly. 

T.Willey

  • Needs a day job
  • Posts: 5251
Re: ObjectDBX and Attributes
« Reply #2 on: August 24, 2006, 05:16:48 PM »
I just feel certain that .net will not help this -- it's not the language that you use to change the attribute, it's the way Autocad handles the change. 

If you use the ATTSYNC command after you open the drawing, Autocad will rejustify the attributes correctly. 
I thought so, but was hoping.  Oh well, I guess I won't update those routines then.  Thanks.
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: ObjectDBX and Attributes
« Reply #3 on: August 25, 2006, 12:33:49 PM »
I just feel certain that .net will not help this -- it's not the language that you use to change the attribute, it's the way Autocad handles the change. 

If you use the ATTSYNC command after you open the drawing, Autocad will rejustify the attributes correctly. 

No need for that. The solution is quite simple in managed or unmanaged ObjectARX.

You temporarily set the WorkingDatabase property of the HostApplicationServices object to the database that contains the text/attribute, and then do the mods. Make sure that you save the curent value of WorkingDatabase before you change it, and then restore that after you're done (this part is absolutely critical, to prevent AutoCAD from crashing)

Here is a class that you can use to automate the switching:

Code: [Select]
using System;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;

namespace CaddZone.DatabaseServices
{
   class WorkingDatabase : IDisposable
   {
      public WorkingDatabase(Database db)
      {
         Database current = HostApplicationServices.WorkingDatabase;
         if (db != current)
         {
            m_Previous = current;
            HostApplicationServices.WorkingDatabase = db;
         }
         else
            GC.SuppressFinalize(this);
      }

      ~WorkingDatabase()
      {
         Dispose(false);
      }

      #region IDisposable Members

      public void Dispose()
      {
         Dispose(true);
      }

      #endregion

      private bool disposed = false;
      private void Dispose(bool p)
      {
         if (!disposed)
         {
            Database current = HostApplicationServices.WorkingDatabase;
            if ( m_Previous != null && current != m_Previous)
               HostApplicationServices.WorkingDatabase = m_Previous;
            disposed = true;
            GC.SuppressFinalize(this);
         }
      }

      private Database m_Previous = null;

   }

   // Example usage:

   public class Example
   {
      public Example()
      {
         Database db = new Database(true, true);

         using (WorkingDatabase wdb = new WorkingDatabase(db))
         {
            // Do stuff here that requires db to be the WorkingDatabase
         }
      }
   }
}

T.Willey

  • Needs a day job
  • Posts: 5251
Re: ObjectDBX and Attributes
« Reply #4 on: August 25, 2006, 01:01:20 PM »
Thanks for posting Tony!!

This seems a little over my head right now, but let me take a stab at what you are saying.

So I would open the drawing as and ODBX document (IAxDbDocument ?) and then use your function to grab the database, and make my changes? and this will take care of the problem with attributes?

What else would you need to do this with? (real quick off the top of you head, if you don't mind)

Thanks again!
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: ObjectDBX and Attributes
« Reply #5 on: August 25, 2006, 01:50:03 PM »
Thanks for posting Tony!!

This seems a little over my head right now, but let me take a stab at what you are saying.

So I would open the drawing as and ODBX document (IAxDbDocument ?) and then use your function to grab the database, and make my changes? and this will take care of the problem with attributes?

What else would you need to do this with? (real quick off the top of you head, if you don't mind)

Thanks again!

Hi Tim.  If you're using ObjectDBX ActiveX, then you can get the
managed Database from the AcadDatabase using this:

Code: [Select]
   AxDbDocument dbxDoc = // get your database open

   using( WorkingDatabase wdb = new WorkingDatabase(
                       Database.FromAcadDatabase(dbxDoc.Database)))
   {
          // Here you can modify text/attributes in the database
   }

You don't need to do the mods via managed code, you can use the ActiveX methods, the only requirement is that while you do the mods, HostApplicationServices.WorkingDatabase must be set to the Database containing the text/attributes. The WorkingDatabase class I posted automates the temporary switching of that property's value for you.



T.Willey

  • Needs a day job
  • Posts: 5251
Re: ObjectDBX and Attributes
« Reply #6 on: August 25, 2006, 01:57:16 PM »
Thanks for the clarification Tony!
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: ObjectDBX and Attributes
« Reply #7 on: August 30, 2006, 02:54:02 PM »
Tony (or anyone who knows),

  I can't seem to get this to work.  I was using what you posted as my guide, but it errors saying
Quote
ODBX-Test.cs(38,12): error CS0246: The type or namespace name 'WorkingDatabase' could not be found (are you missing a using directive or an assembly reference?)

Here is the code.  I'm just (trying to) printing out the names of all the blocks in a drawing opened with ObjectDBX.
Code: [Select]
using System;
using System.Collections;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Interop.Common;

using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

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

namespace Test
{
/// <summary>
/// Description of Working.
/// </summary>
public class odbxTest
{
[CommandMethod ("dbxTest")]
public void TestODBX() {
Document Doc = AcadApp.DocumentManager.MdiActiveDocument;
Editor DocEd = Doc.Editor;
Autodesk.AutoCAD.Windows.OpenFileDialog Dia = new Autodesk.AutoCAD.Windows.OpenFileDialog("Select drawings to update Cloud layer", "", "dwg", "", Autodesk.AutoCAD.Windows.OpenFileDialog.OpenFileDialogFlags.AllowMultiple);
Dia.ShowDialog();
string[] DwgList = Dia.GetFilenames();
AxDbDocument dbxDoc = new AxDbDocument();
foreach (string Str in DwgList) {
dbxDoc.Open (Str, null);
using (WorkingDatabase wdb = new WorkingDatabase (Database.FromAcadDatabase (dbxDoc.Database))) {
using (Transaction wdbTrans = wdb.TransactionManager.StartTransaction()) {
BlockTable bt = (BlockTable) wdbTrans.GetObject (wdb.BlockTableId, OpenMode.ForRead);
foreach (ObjectId id in bt) {
BlockTableRecord btr = (BlockTableRecord) wdb.Trans.GetObject (id, OpenMode.ForRead);
DocEd.WriteMessage ("\n Block name: {0}", btr.Name);
}
}
}
}
}
}
}
Thanks in advance.
Tim

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

Please think about donating if this post helped you.

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: ObjectDBX and Attributes
« Reply #8 on: August 30, 2006, 03:38:09 PM »
What about adding one line in your's code:
Code: [Select]
using CaddZone.DatabaseServices;

T.Willey

  • Needs a day job
  • Posts: 5251
Re: ObjectDBX and Attributes
« Reply #9 on: August 30, 2006, 03:42:23 PM »
I think I would have to have Tony's dll file, but I tried it anyway since I'm so lost here, and this is the error I got.
Quote
ODBX-Test.cs(17,7): error CS0246: The type or namespace name 'CaddZone' could not be found (are you missing a using directive or an assembly reference?)

Build complete -- 1 errors, 0 warnings
Tim

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

Please think about donating if this post helped you.

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: ObjectDBX and Attributes
« Reply #10 on: August 30, 2006, 03:46:11 PM »
I think I would have to have Tony's dll file, but I tried it anyway since I'm so lost here, and this is the error I got.
Include Tony's code (not dll) in your's cs-file and try again.
Your's code must looking like this:
Code: [Select]
using System;
using System.Collections;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Interop.Common;

using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

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

namespace CaddZone.DatabaseServices
{
  class WorkingDatabase : IDisposable
  {
    public WorkingDatabase(Database db)
    {
      Database current = HostApplicationServices.WorkingDatabase;
      if (db != current)
      {
        m_Previous = current;
        HostApplicationServices.WorkingDatabase = db;
      }
      else
        GC.SuppressFinalize(this);
    }
    public Database Database()
    {
      return HostApplicationServices.WorkingDatabase;
    }
    ~WorkingDatabase()
    {
      Dispose(false);
    }

      #region IDisposable Members

    public void Dispose()
    {
      Dispose(true);
    }

      #endregion

    private bool disposed = false;
    private void Dispose(bool p)
    {
      if (!disposed)
      {
        Database current = HostApplicationServices.WorkingDatabase;
        if ( m_Previous != null && current != m_Previous)
          HostApplicationServices.WorkingDatabase = m_Previous;
        disposed = true;
        GC.SuppressFinalize(this);
      }
    }

    private Database m_Previous = null;

  }
}

namespace Test
{
  /// <summary>
  /// Description of Working.
  /// </summary>
  public class odbxTest
  {
    [CommandMethod ("dbxTest")]
    public void TestODBX()
    {
      Document Doc = AcadApp.DocumentManager.MdiActiveDocument;
      Editor DocEd = Doc.Editor;
      Autodesk.AutoCAD.Windows.OpenFileDialog Dia = new Autodesk.AutoCAD.Windows.OpenFileDialog("Select drawings to update Cloud layer", "", "dwg", "", Autodesk.AutoCAD.Windows.OpenFileDialog.OpenFileDialogFlags.AllowMultiple);
      Dia.ShowDialog();
      string[] DwgList = Dia.GetFilenames();
      AxDbDocument dbxDoc = new AxDbDocument();
      foreach (string Str in DwgList)
      {
        dbxDoc.Open (Str, null);
        Database db = Database.FromAcadDatabase (dbxDoc.Database);
        using (CaddZone.DatabaseServices.WorkingDatabase wdb = new CaddZone.DatabaseServices.WorkingDatabase (db))
        {
          using (Transaction wdbTrans = db.TransactionManager.StartTransaction())
          {
            BlockTable bt = (BlockTable) wdbTrans.GetObject (db.BlockTableId, OpenMode.ForRead);
            foreach (ObjectId id in bt)
            {
              BlockTableRecord btr = (BlockTableRecord) wdbTrans.GetObject (id, OpenMode.ForRead);
              DocEd.WriteMessage ("\n Block name: {0}", btr.Name);
            }
          }
        }
      }
    }
  }
}
I've do not tested it but it was compiled without errors.
« Last Edit: August 30, 2006, 04:06:34 PM by Alexander Rivilis »

T.Willey

  • Needs a day job
  • Posts: 5251
Re: ObjectDBX and Attributes
« Reply #11 on: August 30, 2006, 04:16:09 PM »
Thank you very much Alexander!!  I tried it, and was about to post saying it didn't work, but I say you posted more, and after testing it works great!

Thank you so much for posting your code also Tony!
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: ObjectDBX and Attributes
« Reply #12 on: August 30, 2006, 05:54:52 PM »
I can't see to get this to work.

Question: When using the code provided, can I pass the database (db) to sub-functions? or do I have to try something else?

It looks like it might work, but I get an error when trying the command in Acad.  Here is the main part of the rouine.  If needs be I can post the whole code.

Thanks in advance for any help/tips on how to do this better.
Code: [Select]
public void UpdateRevStuff() {
      Document Doc = AcadApp.DocumentManager.MdiActiveDocument;
      Editor DocEd = Doc.Editor;
      Autodesk.AutoCAD.Windows.OpenFileDialog Dia = new Autodesk.AutoCAD.Windows.OpenFileDialog("Select drawings to update Cloud layer", "", "dwg", "", Autodesk.AutoCAD.Windows.OpenFileDialog.OpenFileDialogFlags.AllowMultiple);
      Dia.ShowDialog();
      string[] DwgList = Dia.GetFilenames();
      AxDbDocument dbxDoc = new AxDbDocument();
foreach (string Str in DwgList) {
      dbxDoc.Open (Str, null);
      Database db = Database.FromAcadDatabase (dbxDoc.Database);
      using (CaddZone.DatabaseServices.WorkingDatabase wdb = new CaddZone.DatabaseServices.WorkingDatabase (db)) {
      if (HasLayer (db, "Cloud-UNKNOWN")) {
string Rev = (GetHighestRev(db));
if (Rev != "") {
UpdateRevBlock (db, Rev);
UpdateCloudLayer (db, "Cloud-UNKNOWN", "Cloud-" + Rev);
dbxDoc.Save();
}
      }
      }
}
}
Tim

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

Please think about donating if this post helped you.

Alexander Rivilis

  • Bull Frog
  • Posts: 214
  • Programmer from Kyiv (Ukraine)
Re: ObjectDBX and Attributes
« Reply #13 on: August 30, 2006, 06:13:42 PM »
Question: When using the code provided, can I pass the database (db) to sub-functions? or do I have to try something else?
Yes. You can pass Database any function (really reference will be passed).
Quote
It looks like it might work, but I get an error when trying the command in Acad.  Here is the main part of the rouine.  If needs be I can post the whole code.
What error message? Are you trying to debug this code? Debugging maybe very usefull.

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
Re: ObjectDBX and Attributes
« Reply #14 on: August 30, 2006, 06:15:04 PM »
Just a quick guess, perhaps a Doclock may be required.
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.
- J.R.R. Tolkien