Using a VB ActiveX DLL from Visual LISP or VBA



Using a VB ActiveX DLL from Visual LISP or VBA

Published date: 2005-03-11 ID: TS15992

Applies to: AutoCAD® 2005 AutoCAD® 2004 AutoCAD® 2002

Issue

How can I create a user-interface module in Visual Basic that can also be easily called from Visual LISP or VBA?

Solution

The simplest and most efficient way is to write an in-process Automation client of AutoCAD, such as a VB ActiveX DLL. This DLL can then be loaded from Visual LISP, VBA, Java (via Automation) and ObjectARX. The DLL may be an Automation client of AutoCAD, or any other Automation server, or of multiple servers.

Using Visual Basic 6:

1. Start Visual Basic.

2. Select "ActiveX DLL" in the New Project Wizard.

3. Change the project's "name" property to "MyProject".

4. There is a default class module in the project, change its "name" property

to "MyClass1".

5. Add a function or sub-routine to the class module such as:

' This function takes three arguments, and will

' return an array of data to the calling function

Public Function MyFn(ByRef arg1 As Integer, ByRef arg2 As String, ByRef arg3 As Double) As Variant

    Dim MyForm1 As New MyForm1

    'Populate textboxes with passed-in values

    MyForm1.TextBox1.Text = arg1

    MyForm1.TextBox2.Text = arg2

    MyForm1.TextBox3.Text = arg3

    MyForm1.Show vbModal

    ' Create an array of items to return to the caller

    Dim MyArray(2) As Variant

    MyArray(0) = CInt(MyForm1.TextBox1.Text)

    MyArray(1) = MyForm1.TextBox2.Text

    MyArray(2) = CDbl(MyForm1.TextBox3.Text)

    MyFn = MyArray

End Function

(Where MyForm1 is a form you are adding to the project. Be aware that this just as well could be a function, which returns a value or a list of values to the calling process).

6. Add a Form to the project.  Change its name to "MyForm1". 

7. Add three TextBox controls to the Form.

8. Add a Button control which, when clicked, will hide the Form:

Private Sub Command1_Click()

    Me.Hide

End Sub

9. Select File -> Make MyProject.dll. This creates the DLL and registers it with COM. (You'll need to ensure that the DLL is registered on any other computers you want to run this on. That's usually handled by creating a setup package for your DLL with Visual Basic.)

10. If you want to use the DLL from Visual LISP, simply create a function such as

the following, and load it into AutoCAD:

(defun showDialog (/ acadApp vbApp retVal retList)

   (vl-load-com)

   ;; get the main AutoCAD application object

   (setq acadApp (vlax-get-acad-object))

   ;; load VB ActiveX DLL into AutoCAD's address space 

   (setq vbApp (vla-GetInterfaceObject acadApp "MyProject.MyClass1"))

   (if (not vbApp)  

      (princ "\nError loading ActiveX DLL.")

      (vlax-invoke vbApp "MyFn"

         7                        ; arg1, an integer

         "Arbitrary string"  ; arg2, a string

         1.5                     ; arg3, a 'double'

       )

    )

)

To call the exposed function, type (showDialog) at the command line:

This will return the following list to AutoCAD:

(7 "Arbitrary string" 1.5)

You can see that you can pass arguments to the VB dialog function and also process return values back in AutoCAD. This is particularly useful for creating options dialogs, as these settings need to be initialized and the modified values need to be returned.

11. If you want to use this DLL from VBA, add a reference to this DLL (registering it with COM should add it to the list of ActiveX servers available from VBA, otherwise just browse and select MyProject.dll).

12. Use the following mechanism to load the DLL in-process, and call the function (the values are returned in an array):

Sub MyVBAProject()

    Dim oMyApp As New MyClass1

    Dim vReturn As Variant

   

    Set oMyApp = ThisDrawing.Application.GetInterfaceObject("MyProject.MyClass1")

   

    'Call function w/three arguments

    vReturn = oMyApp.MyFn(7, "Arbitrary string", 1.5)

   

    'Display values returned by function

    MsgBox "Integer: " & CStr(vReturn(0)) & vbCr _

         & "String: " & vReturn(1) & vbCr _

         & "Double: " & CStr(vReturn(2)), _

         vbOKOnly, "Returned values"

End Sub

If you watch the vReturn variable after the call to MyFn, you will see that it contains the same values as seen in AutoLISP.

Using Visual Studio .Net:

It is also possible to do this with a Visual Basic Class Library, with some minor changes. 

1. Start Visual Studio .Net.

2. Select "VisualBasic Projects" and "Class Library" in the New Project Wizard.

3. Change the project's "name" property to "MyProject".

4. There is a default class module in the project, change its "name" property

to "MyClass1".

5. Add a function or sub-routine to the class module such as:

Public Class MyClass1

    ' This function takes three arguments, and will

    ' return an array of data to the calling function

    ' Note: In , the function now must return a type Object instead of Variant.

    Public Function MyFn(ByRef arg1 As Integer, ByRef arg2 As String, ByRef arg3 As Double) As Object

        Dim MyForm1 As New MyForm1()

        'Populate textboxes with passed-in values

        MyForm1.TextBox1.Text = arg1

        MyForm1.TextBox2.Text = arg2

        MyForm1.TextBox3.Text = arg3

        MyForm1.ShowDialog()

        ' Create an array of items to return to the caller   

        Dim MyArray(2) As Object

        MyArray.SetValue(CInt(MyForm1.TextBox1.Text), 0)

        MyArray.SetValue(MyForm1.TextBox2.Text, 1)

        MyArray.SetValue(CDbl(MyForm1.TextBox3.Text), 2)

        Return MyArray

    End Function

End Class

6. Perform steps 6 through 8 above.

7. In your project's Property Pages, go to Configuration Properties -> Build. 

Check the box labeled "Register for COM Interop".  Click "OK".

If you want to use this .NET DLL from VBA, add a reference to the .tlb file.

(MyProject.tlb).

Unloading and debugging ActiveX dlls from visual LISP

Published date: 2005-01-27

ID: TS34023

Applies to:

AutoCAD® 2005

AutoCAD® 2004

AutoCAD® 2002

Issue

I am using a Visual Basic ActiveX DLL from Visual LISP, but when I rebuild it,

VB denies permission to do this. I have to close AutoCAD so that I can rebuild

the DLL. I am using (vla-GetInterfaceObject) to load the COM server. WHy does

this occur?

Solution

You are not releasing the DLL from memory. You need to call (vlax-releaseobject)

with the ActiveX object variable to release the DLL. This decrements the

reference count for the COM server, and should allow unloading. To use more

functionality in the DLL, you will have to reload it, of course.

An alternative method to debug ActiveX DLLs is to change the project settings.

Select Project->Properties in VB, then select the Debugging tab. Make sure that

the radio button "Wait for components to be created" is selected.

Now when you select Run->Start in VB, it will wait for a call to be made to load

the DLL (such as (vla-GetInterfaceObject acadApp "MyProject.MyClass")). You will

be able to set breakpoints in your DLL, which will break when the corresponding

methods are called from Visual LISP. You will be able to modify the DLL code

much more freely using this approach.

Note that when you stop execution from VB, it will ask the following question if

Visual LISP still has a reference to the DLL: "Other applications are currently

accessing an object in your program. Ending the program now could cause errors

in those programs. End at this time?" If you choose Yes, then any Visual LISP

variables referring to the DLL will be invalid. In addition, if you are calling

functionality in the DLL from Visual LISP, then Visual LISP will report a

message such as: "; error: MyProject: Application-defined or object-defined

error". You should be able to restart the debugging without having to close

AutoCAD.

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download