C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your...

16
November 30 – December 3, 2004 Las Vegas, Nevada C-Sharpen your VB/VBA Applications Roy Pereira – Senior Software Developer - Harris Corporation CP24-3 Over the last two years, there has been lots of talk of C# and AutoCAD® development in C#. However, very little information exists on this unless you know whom to talk to. How do you effectively use C# to develop AutoCAD applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to avoid the pitfalls and make this transition a breeze. About the Speaker: Roy is a senior software developer for a research and development initiative within in the Harris Corporation. Roy has previously worked as the development lead for Siemens Research and Development Engineering tools, where his focus was to develop the next generation AutoCAD® integrations to ERP and PDM systems. Roy has a bachelor's degree in Computer Science from Hope College and over 7 years in the software development industry, with the last 4 years focusing on AutoCAD development. Prior to joining Siemens, Roy was an officer in the Singapore Armed Forces. [email protected] CP24-3: C-Sharpen your VB / VBA Applications

Transcript of C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your...

Page 1: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

November 30 – December 3, 2004 ◊ Las Vegas, Nevada

C-Sharpen your VB/VBA Applications Roy Pereira – Senior Software Developer - Harris Corporation

CP24-3 Over the last two years, there has been lots of talk of C# and AutoCAD® development in C#. However, very little information exists on this unless you know whom to talk to. How do you effectively use C# to develop AutoCAD applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to avoid the pitfalls and make this transition a breeze.

About the Speaker: Roy is a senior software developer for a research and development initiative within in the Harris Corporation. Roy has previously worked as the development lead for Siemens Research and Development Engineering tools, where his focus was to develop the next generation AutoCAD® integrations to ERP and PDM systems. Roy has a bachelor's degree in Computer Science from Hope College and over 7 years in the software development industry, with the last 4 years focusing on AutoCAD development. Prior to joining Siemens, Roy was an officer in the Singapore Armed Forces.

[email protected]

CP24-3: C-Sharpen your VB / VBA Applications

Page 2: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

Why .NET? The easiest answer is of course “why .NOT?” (Couldn’t resist). Microsoft announced that by March 31st 2005 VB6 mainstream support will end (http://msdn.microsoft.com/vbasic/support/vb6.aspx). Paid support will still be available until March 2008. In light of this, now may be a good opportunity to peruse other programming possibilities. The eventuality of .NET and consequently C# affecting your development environment in the near future is certain. C# is a new language that was designed from the ground up to be object oriented. As a result it carries less “baggage” with it that allows for a cleaner approach. Autodesk has put much time and effort into .NET compatibility and support in their AutoCAD 2005 release. This series of articles will introduce you to .NET through its flagship language C#. The first part will cover setting up your environment for creating a simple application in AutoCAD 2005 using C#. We will be using the COM API from Autodesk which any VB/VBA AutoCAD programmer should be familiar with. The last example will use a neat new feature from the slightly more complex Managed ObjectARX API which your C++ programmer buddies are always bragging about.

Your First C# CAD application.

1. Create the Solution

a. Open Visual Studio

b. Go to File->New Project

c. Select C# Projects and select Windows Application

d. Type in “HelloCAD” for the name of the application

e. Click OK

2. Rename the Form1.cs class file to HelloForm.cs (Save)

2

Page 3: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

3. Open the right-click on the references from the solution explorer

4. Add AutoCAD 2005 Type Library and AutoCAD /ObjectDBX Common Type Library

3

Page 4: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

5. Add a Button to the HelloCADForm (Name it “btnClickMe”, and change the text property to “Click Me!”)

6. Right Click on the form and select “View Code”

7. Add the following lines “using” statements to the top of the code.

8. Add the following method to the HelloCADForm

9. Go back to the design view of the form. Double Click the Button ( it will take you to the click event of that

button). Add the following lines of code in the click event.

10. Hit CTRL-F5.

4

Page 5: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

Hello CAD!!

What just happened? We just created an application that hooked into AutoCAD and called a couple CAD commands. That was really neat, but what really happened. If you are familiar with using VBA in AutoCAD, you might have noticed that the command used here are all very similar to those used in VBA.

The using statements in step 7 identify the namespaces of the AutoCAD type libraries. In Step 8, we create a simple function that tries to get any open instance of AutoCAD. If it fails, the catch statement is executed and it starts up AutoCAD. In step 9 we are adding the meat of this application. Let’s take a closer look at step 9.

The first line declares an object “myApp” to hold a reference to the ACADApplication returned by our GetCAD function. After executing this line, myApp should contain a reference to an existing AutoCAD Application. Once we are all hooked in to AutoCAD, we get the active document of the AutoCAD application. Next we create an array of doubles (centerPoint), as well as a double called “height”. We then populate these variables with some values.

Finally we call the “AddText” function to add the text to the current document’s modelspace.

Now that was simple enough, but not terribly exciting. Let’s move on and have some fun.

The CADLib Now we are going to create something useful. Start by creating a new Solution. This time, select “Class Library” instead of “Windows Application”. Name your solution CADLib.

The new solution should be created with two classes. One called AssemblyInfo.cs, and the other Class1.cs. Rename Class1.cs to CADHelper.cs. Open the class and make sure the class declaration and constructor match the new name. then add the following method:

5

Page 6: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

Notice that this method is declared as “static”. A static method on a class exists without the need for the class to be instantiated. So when we call this method, we won’t have to create a new instance of the CADHelper class.

Next add another class called “Circle.cs”. In C# a property is declared as follows:

public <Type> <Property name>

{

get

{

return <private variable>

}

set

{

<private variable> = value

}

}

In this class, we are going to create four properties named xValue, yValue, zValue, and radius (all of type double). Make sure that you create matching private variables to store the values.

Let’s also create a method called Draw. A method in c# is declared as follows:

Public <Return Type or void> <Name>(<parameters>)

Our Draw method should look like this:

6

Page 7: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

Now let’s add some meat to it. Add the following lines of code to the Draw function.

Line 89 declares an array of doubles called centerPoint. Line 90 instantiates an ACADApplication and uses our GetCAD function to fill it with the reference to the AutoCAD Application. Line 91 simply sets the application to visible. Line 92, creates an ACADDocument object and fills it with the current drawing of the AutoCAD application. This line will essentially set up myDoc to behave like “ThisDrawing” in VBA. Line 93-95 fills the contents of the centerpoint array with the x, y and z variables that were set by the xValue, yValue, and zValues we created earlier. The reason for filling this array is that the “AddCircle” method expects an array of points as its centerpoint. In line 96 we call the current document’s “AddCircle” method in ModelSpace. This command will create a Circle in Modelspace. Line 97 simply calls the AutoCAD Regen command on all viewports.

After you have added the code above, select Build-Rebuild Solution. This will compile your application and create an assembly.

Calling the CADLib from VBA Now comes the fun part. But before we begin, we are going to examine some fundamentals COM and .NET. COM is Microsoft’s Component Object Model. In VBA and VB6 it allows you to call ActiveX controls and reference functionality in Dynamic Link Libraries or DLLs. COM essentially provides the method in which pieces of Code can find other pieces of code installed on your system and give the illusion of a big happy family. A .NET assembly is similar to a COM DLL, it even shares the same DLL extension, but the inner workings are very different. By default you are unable to call a .NET assembly from VB6 or VBA unlike a normal COM DLL.. However, Microsoft understood the importance of playing nice with its legacy framework and gave .NET assemblies the ability to be called from COM compliant languages like VB6 and VBA. It just takes a little bit of extra work.

The first thing we are going to do is create what is known as a CCW or (COM Callable Wrapper). The CCW creates a proxy for .NET assemblies.

COM Client CCW Proxy

.NETAssembly

7

Page 8: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

This proxy is set up in 2 steps. The first step requires you to create what is known as a Strong Name Key. A Strong Name Key is a unique key that can be applied to an assembly to give it uniqueness and prevent someone from messing with your assembly. To create a Strong Name Key, open a Visual Studio Command Prompt. Next navigate to the directory that your project file is in. Now type “sn –k <assemblyname>.snk” and hit enter. The SN command you used will simply create a strong name key pair and store it in the specified file <assemblyname>.snk. OK now you have a Strong Name Key, but you have yet to associate it with your project. The next step is fairly simple, just right click on the project in the solution explorer and select properties. (NOTE make sure you select properties from the project and not the solution). The following window will appear:

Select Configuration Properties from the left hand tree view and hen select Build. Under Outputs, set the “Register for COM Interop” to true. OK we are half way there. Next we need to tell our assembly where to find our Strong Name Key file. Double click on the “AssemblyInfo.cs” class in the solution explorer. This class contains all the properties for this assembly. You can think of it like the “Project Properties” page in VB6 or the “ACADProject Properties” page VBA. Here we are going to fill in some info about our Project, for now we will fill in the following:

Line 9 simply defines a name for your assembly. Line 10, is the description which will also appear when you try to reference the object from VB or VBA. Now scroll to the end of the file and add the following:

8

Page 9: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

Line 57 tells our compiler where to find out Strong Name Key. Notice the @ symbol before the path, this just tells c# that the string doesn’t use any special formatting in the string and should be taken literally.

Now, let’s build the application. Now we have generated a COM compatible .NET assembly, but we need to still register the assembly so COM can find it. For this, we are going to open up our Visual Studio command prompt again and this time, use a command called RegASM. Regasm stands for Register Assembly which is pretty much what it does. In the command prompt navigate to your debug directory (the directory where the assembly dll is created. Type in “regasm CADLib.dll tlb:CADLib.tlb” and hit enter. This should register your dll. Anytime you recompile, you will have to unregister and re-register. To unregister – use “regasm CADLib.dl /unregister”.

Creating the VBA client. Now we have set-up the .NET assembly to “Play nice” with VB or VBA lets use it. Open up AutoCAD and type “VBAIDE” to open the VBA editor. Double-click “ThisDrawing” and create the following subroutine stub:

Next, click tools->references:

The following dialog will appear:

9

Page 10: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

You will notice that the Component description that you specified in the AssemblyInfo.cs class will be the name of the COM library. Make sure the checkbox is selected and click OK. You have just added the CCW proxy to your VBA project. You will now notice that when you open up the object browser (F2), you can see the .NET component listed as an available library. However, it only lists the class and not the public properties and methods within the class. This is not good, and makes it very difficult to code as intellisense is broken for .NET exposed component. However, we can fix this issue. One of the rules of creating a COM callable component includes creating an interface for all publicly viewable methods and properties. Let’s re-visit the CADLib project and do this. Open the CADLib project and add the following interface declaration(lines 11-18) before the class declaration, but after the namespace declaration.

10

Page 11: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

All we are doing here is declaring an Interface called ICircle. You can think of this as providing a contract of items that we are going to implement. Notice that in the declaration of the Circle class on line 22 we have added “ : ICircle”. This tells C# that we Circle is “signed” up for this contract. This means that Circle must fulfill the contract and provide the implementation for all properties and methods the interface has. Now recompile the application. Next open up the command prompt and unregister and reregister the assembly using Regasm.

Now we have created an Interface for our Circle class in the CADLib, we are going to see how this affects our VBA client. Open the VBA IDE in AutoCAD and go to the references again. The references list should indicate that we are missing the CADLib reference. This is because we created a new CADLib when we recompiled and re-registered the application. Uncheck the “missing” reference and click OK. Next re-open the reference dialog, and look for the “CAD Library” assembly again. Check the box and select OK. You must do this every time you re-compile and re-register the .NET assembly. OK, now let actually call our CADLib and Circle class. Add the following Code to the Sub Main procedure in “ThisDrawing”:

The first line simply, declares a variable that is of type ICircle. Notice that we are declaring the variable to be of the Interface type, but we set the object to equal the actual implementation class Circle. Next we just fill in the xValue, yValue, zValue and radius and call the draw method. Notice now that the intellisense works well, and you are able to see all the properties and methods exposed through the interface. Run the VBA App. It should add a circle at the points specified and using the radius specified.

Calling a VB6 App from .NET So far we have created a cool function library in .NET and called it from VBA, now we are going to call a VB6 dll from .NET. The good news is that this is considerably easier than our previous effort to call the .NET app from VBA. For this example, I have created a VB6 ActiveX dll, added the AutoCAD references, and added the following method:

11

Page 12: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

Go to Project properties and name the project “VBCADProject” and add the description “VB CAD Library”. Compile the project to create the VBCADProject.dll. Now we are going to call this dll from .NET. Open the CADLib application we created earlier. Right-click the references and add a new reference. On the reference window, select the COM tab, and then look for the VB CAD Library project. Select it and click OK.

That is it!! You are now ready to use the classes in the library. Note: When you add a COM reference to a .NET solution, the IDE actually creates a RCW or (Runtime Callable Wrapper) for the COM component. If you were to look in the c# project

12

Page 13: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

directory you would see a file called Interop.VBCADProject.dll, which is the RCW. OK, let’s call the draw function from this VB app. Create a new public void method called VBDraw, make sure to add it to the interface as well. Now add the following code to the VBDraw method implementation.

All we are doing here is creating an instance of the VB6 class and calling it. When you try to compile, you get an error telling you that your VB6 app does not have a strong name. NOTE: In our case this occurs because we have registered our CADLib application for COM interop and given it a strong name key. If our intent was not to expose our component to COM, the following steps would not be necessary. Well, let’s solve this by creating the Interop.VBCADProject.dll with a strong name key. Follow the steps above to create a new Strong Name key called VBCADProject.snk. Now we have to integrate this strong name key with our VB6 dll. This cannot be done from the IDE as VB6 has no clue what a strong name is. However, we can use another command line app from visual studio to do this. Open up a visual studio command prompt. Type in ILDASM. ILDASM stands for Intermediate Language DisAsSMbler. It will open up the following windows app.

Select File->Open and navigate to your bin\debug directory of CADLib. Open up the Interop.VBCADProject.dll. Next click File->Dump, accept the defaults and click OK. Next it will prompt you for a location to “dump” the file. Select the same bin\debug directory and enter the following name Interop.VBCADProject.il. Click OK. The ILDASM app will create the appropriate Intermediate language file for you. Now we are going to go back to the project and remove the Interop.VBCADProject.dll reference. Alright, so now we have a dump of the dll and a strong name key. Next, we are going to create a new strong named dll. Go back to the command prompt and type the following:

Ilasm /dll Interop.VBCADProject.il /key=Interop.VBCADProject.snk

ILASM (which is Intermediate Language Assembler), will now re-create the Interop.VBCDProject.dll with the specified strong name (Interop.VBCADProject.snk). Cool, now go back to the solution and add the reference. Make sure to browse and add the newly created Interop.VBCDProject.dll. Now build the solution.

Not too exciting, but in our next step we will see how this can turn allow your VB6 app to be called from the command line with relative ease.

Creating Command Line VB6 apps.

13

Page 14: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

OK so far we have seen how to hook up to AutoCAD’s COM API which is the same API you have been using in VBA and VB6. This allows you to write apps just as you did in VB and VBA using C#. Now we are going to take advantage of a new feature of AutoCAD 2005. We are going to use a little bit of the managed ObjectARX API. You will soon see how easy it is to take advantage of this new API set. First, as with the COM API, we need a couple references set up. Right-click on references in solutions explorer and click browse. Got to the directory AutoCAD is installed in an add the following two dlls – acmgd.dll and acdbmgd.dll. Next add the following using statement to your Circle Class – using Autodesk.AutoCAD.Runtime

What we have done here is reference the managed Object ARX API and include the namespace so we can reference it. The next step is really simple. All we have to do is tag the method that we want to expose as a command using special AutoCAD Object ARX attribute.

The attribute we added above in line 122, hooks up our VBDraw method to AutoCAD’s command line interpreter. Now comes the fun part. Compile the application and open up AutoCAD. Type “Netload”. The “Netload” command is new for AutoCAD 2005. It allows you to load a .NET Assembly into AutoCAD similar to the Appload command. Once loaded you can call the command using the string you specified in the attribute. Type “drawbox”. AutoCAD will call the VBDraw method, which is calling your wrapped VB6 app. Neat huh?

Creating a Shinny UI for VBA OK, so far we have gone from creating a simple CAD application in C# to calling C# assemblies VB/VBA and vice versa. Now we are going to take advantage of Windows Forms to really show off some .NET functionality. Let’s begin by opening up our favorite CADLib application. Next, we are going to add a new Windows Form to our CADLib. Right click on the project and select Add->Add Windows Form. A dialog will appear asking you to name your form. Name it “Config.cs” and click OK. A new form is created for you. Now add the following controls to the form and arrange them as shown. Also add labels as shown.

Control Type Name

TextBox txtXValue

TextBox txtYValue

TextBox txtZValue

TextBox txtRadius

Button btnOK

14

Page 15: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

Right click on the form and select “view code”. Next add the following private variable to the class

Go to the default constructor of the form and add the lines 36-40:

Line 36 simply instantiates our Circle class as the private variable we declared above. Lines 37-38 take advantage of control Data Binding. A lot of people think that data binding is only for ADO. This is not true. In fact, you can bind any UI element to and object property. So instead of the standard

Circle.xValue = txtXValue.Text;

We simply add a data binding to each of the controls. DataBindings.Add takes three parameters. The first is the name of property on the control we want to bind. The next parameter is the object we want to bind to and the last parameter is the property on the object we wish to bind our control property to.

Now we need to implement the button click. Double click the button on the form in design mode, this should create the button click event. Now let’s add the following code to the event

Because we bound the controls directly to the Circle object, we don’t need any messy value setting before we call the draw method. Now we need to create a method that calls our Config form. Let’s go back to our Circle class and add it there.

15

Page 16: C-Sharpen your VB/VBA Applications · applications? This class will explore how to move your existing applications in VB or VBA to C# using the same AutoCAD COM API. Learn how to

CP24-3: C-Sharpen your VB / VBA Applications

Notice the DrawCircle command method attribute, this will allow us to call the method from the AutoCAD command line. Compile the application and use netload to load it into AutoCAD. Type “DrawCircle”. The draw circle form is displayed – fill in the x, y, and z values plus radius and click OK.

Thanks for your time…I hope you had fun and learned a thing or two.

16