Author Topic: Bricscad && .NET  (Read 62028 times)

0 Members and 1 Guest are viewing this topic.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Bricscad && .NET
« on: June 09, 2009, 11:44:21 PM »
This is is a continuation if this thread http://www.theswamp.org/index.php?topic=21601.0 , but since the changes are significant,
I thought I might start a new thread. RxNet is compiled against BRX instead of SDS/DRX, this means you will need Bricscad pro for
these modules to work. As of now the lisp functions only work with 9.3.10 or newer,

This project is not an attempt to wrap the BRX sdk, the goal is to provide an in process .NET interface to Bricscad's com API.
The ODA has already wrapped DWGDirect so I'm sure it wont be too long before there is a more complete .NET SDK to party with.

Instructions,

1.  Run the installer
2.  When Starting a New project, reference all three DLLs.
3.  Also It is *very important* to set the property, 'Copy Local' to 'False'  or your app could *fail*.

netload or (lspnetload "path") your dll

I have put a few sample functions/methods in a c# project.
note the name spaces

enjoy

This project is now dead
« Last Edit: April 20, 2011, 03:21:04 AM by __assume »

Helios

  • Guest
Re: Bricscad && .NET
« Reply #1 on: June 11, 2009, 12:58:00 PM »
Hi Daniel,

I've been trying to NETLOAD your new stuff into Bricscad Pro 9.2.15, but it doesn't seem to like it.

I get folowing output on Netloading the RxNetSample.dll:

: netload

Failed RETLIST , 1000
Failed RETTV , 1001
Failed RETINT , 1002
Failed RETREAL , 1003
Failed RETSTR , 1004
Failed RETPT , 1005
Failed TOBASE64 , 1006
Failed FROMBASE64 , 1007
Failed LISPFORM , 1008

Any clues?

Helios

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Re: Bricscad && .NET
« Reply #2 on: June 11, 2009, 07:15:04 PM »
Right, that's the module trying to load functions with the [LispFunction] attribute, which only works with 9.3.5(currently in beta) or newer,
you can ignore those errors, or comment out those attributes.

The Command methods, should work.  :-)

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Re: Bricscad && .NET
« Reply #3 on: July 28, 2009, 10:57:17 PM »
I finally figured out how to hide a .Net form and give control to the editor, a must for the getXXX functions like GetDistance

the form

Code: [Select]
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using BricscadApp;

namespace RxNetSample
{
 public partial class FormHide : Form
 {
  //native methods we need to invoke
  [DllImport("user32.dll")]
  static extern IntPtr SetFocus(IntPtr hWnd);

  [DllImport("user32.dll")]
  static extern bool EnableWindow(IntPtr hWnd, bool bEnable);

  [DllImport("Brx.DLL", CallingConvention = CallingConvention.Cdecl)]
  private extern static IntPtr adsw_acadMainWnd();

  //
  AcadApplication application;
  AcadDocument document;

  public FormHide()
  {
   InitializeComponent();
   application = RxNet.ApplicationServices.Application.AcadApplication as AcadApplication;
   if (application == null) {throw new System.Exception("Could Not Get Application"); }
   document = application.ActiveDocument;
  }

  private void button1_Click(object sender, EventArgs e)
  {
   //use this to hide your form and give control to Bricscad
   IntPtr wndMain = adsw_acadMainWnd();
   this.Hide();
   EnableWindow(wndMain, true);
   SetFocus(wndMain);

   try
   {
    double[] pt1 = (double[])document.Utility.GetPoint(null, "\nGetPoint");
    double dist = document.Utility.GetDistance(pt1, "\nGet Next Point");
    System.Windows.Forms.MessageBox.Show(dist.ToString());
   }
   catch (System.Exception ex)
   {
    System.Windows.Forms.MessageBox.Show(ex.Message);
   }

   //show our form
   EnableWindow(wndMain, false);
   this.Show();
  }
 }
}

showing the form

Code: [Select]
[CommandMethod("doit")]
  public static void doit()
  {
   try
   {
    // Note Application.ShowModalDialog(..)
    // will set the owner, the Icon for you and the following to false
    // ShowInTaskbar, MinimizeBox and MaximizeBox;
    FormHide form = new FormHide();
    Application.ShowModalDialog(form);
   }
   catch (Exception ex)
   {
    System.Windows.Forms.MessageBox.Show(ex.Message);
   }
  }

I updated dlls in the fisrt post

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Re: Bricscad && .NET
« Reply #4 on: July 29, 2009, 05:19:10 AM »
It seems that p/invoking the native getXXX functions give a little more control than the ActiveX versions. here is a sample


It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Re: Bricscad && .NET
« Reply #5 on: August 01, 2009, 07:20:33 AM »
I posted updated DLL's, compiled with the latest release of Bricscad, the lisp function attribute ought to work now

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Re: Bricscad && .NET
« Reply #6 on: September 03, 2009, 09:47:01 AM »
Here is an installer that will Auto-load the required DLLs for RxNet ( for versions of Bricscad that support auto-loading via the registry)
« Last Edit: September 18, 2009, 02:14:31 AM by Daniel »

Jerry J

  • Newt
  • Posts: 48
Re: Bricscad && .NET
« Reply #7 on: September 11, 2009, 07:45:38 PM »
 :-o RxNet doesn't load in Bricscad V10-Beta.  Wouldn't you know it, right after I decided to .Net some of old stuff from VBA & Lisp.
Hope your thinking of upgrading RxNet.  What I did complete in V9 worked great!! (except radiobuttons on forms). I sure appreciate
all the effort you must have put into providing this program along with DocTabs.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Re: Bricscad && .NET
« Reply #8 on: September 12, 2009, 12:16:47 AM »
Hi Jerry,

I'm working on getting all my goodies working with v10. shouldn't be too long :)

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Re: Bricscad && .NET
« Reply #9 on: September 12, 2009, 11:14:45 AM »
Ok I think I have this working.  :laugh:
Since the Type Libraries have not been renamed between V9 and V10, it's a little hard to explicitly reference these with a side by side install.
I think the solution is to preload the assemblies that may have versioning problems. This may prevent the need for recompiling.

I changed the paths, the V9 DLLs are now installed in RxNet\v9 and V10 in RxNet\v10 so you must uninstall any old versions first.
Again since the com assemblies are preloaded, it should not matter which one you reference in your project unless you are referencing a new feature.
Remember Copy Local to False!!!

Please let me know if this works ,  doesn't work.... I gotsta know!!
Chime in if you are using this project, If I know people are using it then I will be more inclined to add stuff to it.

Bricsys has renamed the Brx DLL, so if your p/invoking you will need to change Brx to Brx10 and recompile
« Last Edit: September 18, 2009, 02:14:55 AM by Daniel »

Jerry J

  • Newt
  • Posts: 48
Re: Bricscad && .NET
« Reply #10 on: September 12, 2009, 08:16:09 PM »
 :-D It works!! Thanks much.  Now back to trying to convert System.__ComObject to double or string, but that's another story.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Re: Bricscad && .NET
« Reply #11 on: September 12, 2009, 08:41:35 PM »
:-D It works!! Thanks much.

good deal!


Now back to trying to convert System.__ComObject to double or string, but that's another story.

post your function, so I can have a look!

Thanks a ton
Daniel

Jerry J

  • Newt
  • Posts: 48
Re: Bricscad && .NET
« Reply #12 on: September 13, 2009, 02:32:56 AM »
Here is my function as it now exists.  It has been in many forms, with somewhat the same results. As you see I'm using some data from
Excel to lookup values.  The result comes back as an object, which I can easily put into other cells of excel, but can't seem to do
anything with it in this application. (Exception from HRESULT:0x800A03EC)

If I use object as the return type, then Convert.toString, I end up with "System.__Object" as my label text in Bricscad.
Code: [Select]
public class findbeam
{
[ComVisibleAttribute(true)]
public string FindBeam(double dist2, double w, double V, double M,double wthick)
{
object missing = System.Reflection.Missing.Value;
//object newTemplate = false;
//object docType = 0;
//object isVisible = true;
Excel._Application ExcelApp = new Excel.ApplicationClass();
ExcelApp.Visible = false;
Workbook objBook = ExcelApp.Workbooks._Open("C:\\Beam Data\\Wood.xls", Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Worksheet objSheet = (Worksheet)objBook.Sheets["Sheet1"];
ExcelApp.Visible = true;
ExcelApp.WindowState = XlWindowState.xlMinimized;
objSheet.Cells[12, 15] = w;
Range rang;

int off;
if (wthick < 5.0)
{
rang = objSheet.get_Range("I5", "I10");
off = 5;
}
else
{
rang = objSheet.get_Range("I11", "I15");
off = 11;
}
int Vrow = (int) ExcelApp.WorksheetFunction.Match(V, rang, 1);
Range ranga = objSheet.get_Range(objSheet.Cells[Vrow + off, 3], missing);
//double b = (double)ranga.get_Value(missing);
double b = Convert.ToDouble(ranga.Value2);
objSheet.Cells[2, 1] = b;
ranga = objSheet.get_Range(objSheet.Cells[Vrow + off, 4], missing);
double d = Convert.ToDouble(ranga.Value2);
objSheet.Cells[3, 1] = d;
string dbeam = Convert.ToString(ranga.Value2);
objSheet.Cells[4, 1] = dbeam;
//dbeam = Convert.ToString(dbeam);
//objBook.Close("Save", "C:\\Beam Data\\Wood.xls", Type.Missing);
//-------------------------
//Form1 frm = new Form1();
//frm.txtbx1text = (dist2 / 12.0).ToString("F2");
//frm.ShowDialog(frm);

return dbeam;
}
}

Hope the code doesn't offend you too much.  It's pieces from here and there.
Thanks for looking.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7047
  • AKA Daniel
Re: Bricscad && .NET
« Reply #13 on: September 13, 2009, 10:20:53 AM »
Ok I think I see what's going on, you need to iterate through the range (a 2D array of rows and columns )
and append the values to a string, I like to use the StringBuilder class.

see if this sample give you any hints


Code: [Select]
using System;
using System.Runtime.InteropServices;
using System.Text;
using BricscadApp;
using Microsoft.Office.Interop.Excel;
using RxNet.Runtime;
using Excel = Microsoft.Office.Interop.Excel;

namespace RxNetTemplate
{
 public class ExecMethods
 {
  [CommandMethod("doit")]
  public static void doit()
  {
   AcadApplication application =
     RxNet.ApplicationServices.Application.AcadApplication as AcadApplication;

   if (application == null)
    throw new System.Exception("Could Not Get Application");
 
   AcadDocument document = application.ActiveDocument;


   object missing = System.Reflection.Missing.Value;
   Excel._Application ExcelApp = new Excel.ApplicationClass();
   ExcelApp.Visible = false;
   Workbook objBook = ExcelApp.Workbooks._Open("C:\\Wood.xls", Type.Missing, Type.Missing,
                                              Type.Missing, Type.Missing, Type.Missing,
                                              Type.Missing, Type.Missing, Type.Missing,
                                              Type.Missing, Type.Missing, Type.Missing, Type.Missing);

   Worksheet objSheet = objBook.Sheets["Sheet1"] as Worksheet;

   try
   {
    ExcelApp.Visible = true;
    ExcelApp.WindowState = XlWindowState.xlMinimized;
    Range range = objSheet.get_Range("I1", "I5");
    document.Utility.Prompt(string.Format("\n{0}", RangeToString(range)));
   }
   catch (System.Exception ex)
   {
    document.Utility.Prompt(ex.Message);
   }
   finally
   {
    ExcelApp.Quit();
    Marshal.ReleaseComObject(objSheet);
    Marshal.ReleaseComObject(objBook);
    Marshal.ReleaseComObject(ExcelApp);
   }
  }

  //
  public static string RangeToString(Range range)
  {
   object[,] values = range.get_Value
     (Excel.XlRangeValueDataType.xlRangeValueDefault) as object[,];

    StringBuilder sb = new StringBuilder();

    for (int i = 1; i <= values.GetUpperBound(0); i++)
    {
     sb.Append("\n"); // new line for each row
     for (int j = 1; j <= values.GetUpperBound(1); j++)
     {
      sb.Append(string.Format("{0} ", values[i, j]));
     }
    }
   return sb.ToString();
  }
 }
}


Jerry J

  • Newt
  • Posts: 48
Re: Bricscad && .NET
« Reply #14 on: September 13, 2009, 05:52:13 PM »
Tne iteration is really not part of the problem. I am really using the Match function to return a single cell and then wanting to use the cell value
as a label (AcadMText.Text) later.  I believe the problem is that Excel (V2002) returns a com.object (not System.Object)that .net does not support.
For example, the  (string) dbeam = objSheet.Cells[1,2].toString yields - "Cannot convert method group 'ToString' to non-delegate type 'string'.
Did you intend to invoke the method?" This Excel cell object value, which is "4x8", refuses to be converted to a string and Mtext is expecting a string type.

In a nutshell:
                  //Tried this
         //object dbeam = ranga.get_Value(Excel.XlRangeValueDataType.xlRangeValueDefault) as object;
         //and this
         object dbeam = ranga.Value2;
         StringBuilder sb = new StringBuilder();
         sb.Append(string.Format("{0} " ,dbeam));

yields--> HRESULT:0x800A03EC as before.  Probably need to upgrade Excel to get good interop (don't have the same as your's), but think I'll look OpenOffice first.

Thanks for the help. I did pickup some ideas for further down the road.