Author Topic: Bricscad: Help with WBlockCloneObjects  (Read 2524 times)

0 Members and 1 Guest are viewing this topic.

Keith Brown

  • Swamp Rat
  • Posts: 601
Bricscad: Help with WBlockCloneObjects
« on: April 28, 2017, 03:52:24 PM »
I have some code that I am trying to port over to Bricscad.  The code is supposed to create a new drawing and then xref the current drawing into it.  It will copy some views from the current drawing into the new drawing and then save and exit the new drawing.  The code that I have is working just fine in AutoCAD but when I run it in Bricscad it gives me the dreaded EInvalidOwnerObject when i use the WBlockCloneObject command.


Here is the stripped down code that I am using.  Any ideas?


Code - C#: [Select]
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using System.IO;    
  5. using System.Windows.Forms;
  6.  
  7. #if BricsCAD
  8.     using System.Runtime.InteropServices;
  9.     using BricscadApp;
  10.     using Teigha.Runtime;
  11.     using Teigha.DatabaseServices;
  12.     using Teigha.GraphicsInterface;
  13.     using Teigha.Geometry;
  14.     using Bricscad.ApplicationServices;
  15.     using Bricscad.EditorInput;
  16.     using Bricscad.Runtime;
  17.     using CadRx = Teigha.Runtime;
  18.     using CadAs = Bricscad.ApplicationServices;
  19.     using CadApp = Bricscad.ApplicationServices.Application;
  20.     using CadBr = Teigha.BoundaryRepresentation;
  21.     using CadDb = Teigha.DatabaseServices;
  22.     using CadGe = Teigha.Geometry;
  23.     using CadEd = Bricscad.EditorInput;
  24.     using CadGi = Teigha.GraphicsInterface;
  25.     using CadClr = Teigha.Colors;
  26.     using CadWnd = Bricscad.Windows;
  27.  
  28. #elif AutoCAD
  29.     using Autodesk.AutoCAD.Runtime;
  30.     using Autodesk.AutoCAD.ApplicationServices;
  31.     using Autodesk.AutoCAD.DatabaseServices;
  32.     using Autodesk.AutoCAD.Geometry;
  33.     using Autodesk.AutoCAD.EditorInput;
  34.     using Autodesk.AutoCAD.GraphicsInterface;
  35.     using Autodesk.AutoCAD.Colors;
  36.     using Autodesk.AutoCAD.Windows;
  37.     using Autodesk.AutoCAD.Internal;
  38.     using CadRx = Autodesk.AutoCAD.Runtime;
  39.     using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;
  40.     using CadAs = Autodesk.AutoCAD.ApplicationServices;    
  41.     using CadDb = Autodesk.AutoCAD.DatabaseServices;
  42.     using CadGe = Autodesk.AutoCAD.Geometry;
  43.     using CadEd = Autodesk.AutoCAD.EditorInput;
  44.     using CadGi = Autodesk.AutoCAD.GraphicsInterface;
  45.     using CadClr = Autodesk.AutoCAD.Colors;
  46.     using CadWnd = Autodesk.AutoCAD.Windows;
  47. #endif
  48.  
  49. [assembly: CommandClass(typeof(CsBrxMgd.Commands))]
  50. [assembly: ExtensionApplication(typeof(CsBrxMgd.Commands))]
  51.  
  52. namespace CsBrxMgd
  53. {
  54.     /// <summary>
  55.     /// Class Commands.
  56.     /// </summary>
  57.     /// <seealso cref="IExtensionApplication" />
  58.     public class Commands : IExtensionApplication
  59.     {
  60.         #region Public Methods
  61.  
  62.         /// <summary>
  63.         /// this is initialized when the application is loaded
  64.         /// </summary>
  65.         public void Initialize()
  66.         {
  67.             Document doc = CadApp.DocumentManager.MdiActiveDocument;
  68.             Editor ed = doc.Editor;
  69.             Database db = doc.Database;
  70.             ed.WriteMessage("\nCsBrxMgd sample is loaded...");
  71.         }
  72.  
  73.         /// <summary>
  74.         /// this is initialized when the application is terminated
  75.         /// </summary>
  76.         public void Terminate()
  77.         {
  78.             CadApp.ShowAlertDialog("The commands class is Terminated");
  79.         }
  80.  
  81.         [CommandMethod("CopyObjectsBetweenDatabases", CommandFlags.Session)]
  82.         public static void CopyObjectsBetweenDatabases()
  83.         {
  84.             string filePath = @"c:\users\kbrown\desktop\New Drawing.dwg";
  85.             Database destDb = new Database(false, true);
  86.             Database sourceDb = CadApp.DocumentManager.MdiActiveDocument.Database;
  87.             destDb.ReadDwgFile(@"c:\users\kbrown\desktop\CopyViews.dwt", FileOpenMode.OpenForReadAndWriteNoShare, false, null);
  88.             destDb.CloseInput(true);
  89.             string myFileName = (string)CadApp.GetSystemVariable("DWGNAME");
  90.             string myFilePath = (string)CadApp.GetSystemVariable("DWGPREFIX");
  91.             string _originalFile = Path.Combine(myFilePath, myFileName);
  92.             string blockName = Path.GetFileNameWithoutExtension(_originalFile);
  93.             ObjectId xrefId = destDb.AttachXref(_originalFile, blockName);
  94.             HostApplicationServices.WorkingDatabase = destDb;
  95.             BlockTableRecord destModelSpace;
  96.             ObjectIdCollection idCollection = new ObjectIdCollection();
  97.             using (Transaction tr = destDb.TransactionManager.StartTransaction())
  98.             {
  99.                 using (BlockReference br = new BlockReference(Point3d.Origin, xrefId))
  100.                 {
  101.                     br.SetDatabaseDefaults();
  102.                     br.Layer = "0";
  103.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
  104.                     string relativePath = MakeRelativePath(filePath, _originalFile);
  105.                     btr.PathName = relativePath;
  106.  
  107.                     BlockTable bt = (BlockTable)tr.GetObject(destDb.BlockTableId, OpenMode.ForRead);
  108.                     destModelSpace = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  109.                     destModelSpace.AppendEntity(br);
  110.                     tr.AddNewlyCreatedDBObject(br, true);
  111.                 }
  112.                
  113.                 tr.Commit();
  114.             }
  115.  
  116.             HostApplicationServices.WorkingDatabase = sourceDb;
  117.  
  118.             using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
  119.             {
  120.                 ViewTable vt = (ViewTable)tr.GetObject(sourceDb.ViewTableId, OpenMode.ForRead);
  121.                 foreach (ObjectId id in vt)
  122.                 {
  123.                     idCollection.Add(id);
  124.                 }
  125.  
  126.                 tr.Commit();
  127.             }
  128.  
  129.             using (Transaction tr = destDb.TransactionManager.StartTransaction())
  130.             {
  131.                 try
  132.                 {
  133.                     BlockTable destBt = (BlockTable)tr.GetObject(destDb.BlockTableId, OpenMode.ForRead);
  134.                     destModelSpace = (BlockTableRecord)tr.GetObject(destBt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
  135.                     IdMapping mapping = new IdMapping();
  136.                     destDb.WblockCloneObjects(idCollection, destModelSpace.ObjectId, mapping, DuplicateRecordCloning.Ignore, false);
  137.                 }
  138.                 catch (Exception ex)
  139.                 {
  140.                     MessageBox.Show($"Error in wblockclone:\n{ex.Message}");
  141.                 }
  142.  
  143.                 tr.Commit();
  144.             }
  145.  
  146.             destDb.SaveAs(filePath, DwgVersion.Current);
  147.  
  148.         }
  149.  
  150.         public static string MakeRelativePath(string fromPath, string toPath)
  151.         {
  152.             string relativePath = toPath;
  153.             try
  154.             {
  155.                 Uri fromUri = new Uri(fromPath);
  156.                 Uri toUri = new Uri(toPath);
  157.                 if (fromUri.Scheme != toUri.Scheme)
  158.                 {
  159.                     return toPath;
  160.                 } // path can't be made relative.
  161.  
  162.                 Uri relativeUri = fromUri.MakeRelativeUri(toUri);
  163.                 relativePath = Uri.UnescapeDataString(relativeUri.ToString());
  164.                 if (toUri.Scheme.ToUpperInvariant() == "FILE")
  165.                 {
  166.                     relativePath = relativePath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
  167.                 }
  168.             }
  169.             catch
  170.             {
  171.                
  172.             }
  173.  
  174.             return relativePath;
  175.         }
  176.  
  177.         #endregion Public Methods
  178.     }
  179. }
  180.  
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: Bricscad: Help with WBlockCloneObjects
« Reply #1 on: May 03, 2017, 09:48:39 AM »
So the issue with this code is in the WBlockCloneObjects call.  If you notice the source container is the modelspace objectId of the new drawing.   The views being copied into the new drawing should actually be copied into the viewtable and not modelspace.  So passing in the ViewTableId of the new drawing fixed the issue.


As I am porting over all of our apps into Bricscad I am finding that Autocad is very forgiving in its Managed code.  It will allow you to do things that you should not necessarily do.  This is a prime example of that. 


Thank you to Owen Wengerd for pointing me in the right direction and giving me the answer.  I need to pay better attention to the error messages as it told me directly to my face that i had passed in the wrong owner container.  I just refused to believe it.
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

Atook

  • Swamp Rat
  • Posts: 1027
  • AKA Tim
Re: Bricscad: Help with WBlockCloneObjects
« Reply #2 on: May 03, 2017, 10:42:38 PM »
Keith, thanks for the follow up.

I'm hoping to port my apps to Bricscad as well, any information will be helpful in the future.

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2122
  • class keyThumper<T>:ILazy<T>
Re: Bricscad: Help with WBlockCloneObjects
« Reply #3 on: May 03, 2017, 11:03:11 PM »

Thanks Keith,

I like that you have prefixed the topic title with ' Bricscad: '
Perhaps we should encourage that ..

Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.