Using ActiveX DLL's as plug-ins to VB6 app.


Can ActiveX DLL's be used as plug-ins to VB6 application?

Lets say I have an application which draws the graph of some mathematical function.
It increments the X value from 1 to 10000, and for each X it calls some mathematical function which is stored in a DLL.

Here's the example:

 - project name: TestDLLPlugInProject
 -   Class name: TestDLLPlugInClass
 - the code for that class:
Public Function GetY(ByVal X As Single) As Single
    GetY = 1000 * Sin(X)
End Function

 - create command button
 - add reference to TestDLLPlugInProject.DLL
Private Sub Command1_Click()
    Dim Test As TestDLLPlugInClass
    Set Test = New TestDLLPlugInClass
    Dim x As Single
    Dim y As Single
    For x = 1 To 10000
        y = Test.GetY(x)
        Me.PSet (x, y)
    Next x
End Sub

My question is:   Can I have more DLL's, where each of them has TestDLLPlugInClass and GetY function, but each of them performs different math operations.
So the final user can simply select which DLL they want to use, and get different results each time.
They could also be able to create their own DLL's, and use them instead of mine.

An example of different DLL's would be:
Public Function GetY(ByVal X As Single) As Single
    GetY = 1000 * Cos(X)
End Function
Public Function GetY(ByVal X As Single) As Single
    If X < 500 then GetY = 100
    If X >= 500 then GetY = 200
End Function

How do I do this if this is even possible?

Thanks in advance!
LVL 11
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

yes u can have...different DLL's

only thing is u need refernce each of the Get functions ?Using the object of that particular class of the specified DLL's

say if u have included two DLL's in ur project

DLL1 and DLL2 having function GETX in both of them..

declare two variables or objects referencing the class for both the DLL's

dim obj1 as DLL1.Class1
dim Obj2 as DLL2.CLass2

to use the fucntions do following


Hope This will make u understand the thing..
dbrckoviAuthor Commented:
I know how to create more DLL's each with different class name, and reference them all, but this is not the point.
This way I can't let the user to write their own DLL and use it instead of mine.

I tried something like this:

 - I have changed original DLL with this:   GetY = 1000    and compiled it to TestDLLPlugInProject2.DLL       (Class names in both DLL's are the same)

 - in my main project I have added a FileListBox, and now the form's code looks like this:
Dim ActiveDLL As String

Private Sub Command1_Click()
    Dim Test As TestDLLPlugInClass
    Set Test = New TestDLLPlugInClass
    Dim x As Single
    Dim y As Single
    For x = 1 To 10000
        y = Test.GetY(x)
        Me.PSet (x, y)
    Next x
End Sub

Private Sub File1_Click()
    Dim SelectedDLL As String
    SelectedDLL = File1.List(File1.ListIndex)
    If SelectedDLL = ActiveDLL Then
        MsgBox "File already loaded"
        Shell "regsvr32 -u " & App.Path & "\" & ActiveDLL, vbNormalFocus
        Shell "regsvr32 " & App.Path & "\" & SelectedDLL, vbNormalFocus
        ActiveDLL = SelectedDLL
    End If

End Sub

Private Sub Form_Load()
    File1 = App.Path
    ActiveDLL = "TestDLLPlugInProject.dll"
End Sub

When I run it and click on a button, I get a graph produced by GetY function from first DLL.
When I click on another DLL in FileLiestBox, I'd like VB6 to re-reference to GetY in another DLL. So if I click on a button I'd get a straight Line. (Y=1000)

For now Regsvr32 successfully registers and unregisters the DLL's, but clicking on a button, still draws sinusoide.
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

dbrckoviAuthor Commented:

I'm not trying to add reference to more than one DLL at Design-time. I know how to do it.

I want to add reference to a DLL at Run-Time.
Winamp can do it. Can I do it in VB too?

Note that my example is only my approach, which may be wrong, but there has to be some way to do it, becouse many applications use DLL's as plug-ins.

I'm asking this here, becouse I ran out of ideas.

cannot u use optional parameters or
Param array instead of a single parameter

so u can get to know as per the parameters what sould ur funtion do .. depending on the parameter values..

dbrckoviAuthor Commented:
Yes I can, but this is not the point.

The point is to create VB6 application which can use DLL's created by user and reference to them at Run-Time.
This function is only an example, which I used to make it simple.

Another example would be the following:
Let's say I have created a chess game. The main application manages the board, buttons, rules, timer and provides an interface for a human player.
Now I'd like to create more computer opponents.

Artifitial Intelligence (lets say. personality) for each computer player would be in a different DLL.
Now when User selects some computer player (DLL), the game would load that DLL and use the code from that DLL to determine the next computer's move.

My main intention is to enable the user to create their own computer player, with it's own logic and intelligence, add it to already existing players, and play against it.
This opens a possibility for two or more users to create their own "BOT's" and make them compete against each other to see who wrote better AI.
Possibilities are endless.

The only problem is how to make VB6 application reference the DLL at run-time, and use it just as if it was referenced through Project -> References at Design-Time?

P.S. I'm not actualy writing a chess game, but chess is the closest thing with which we all are familliar.
dbrckoviAuthor Commented:
And now I feel like a jackass. :-)

I've been trying to figure this out by myself for months, but no luck, and as soon as I openned this question I managed to answer it.

I was reding some articles about this topic but couldn't find anything usefull until I tried CreateObject. Something I used thousands of times before to create Office objects, but I didn't think of using it
for loading DLL's.

I can't belive it's so simple.
Just register the DLL and call:         Set something = CreateObject("TestDLLProject.TestDLLClass","")     to create the class object
                                             OR  Set something = Nothing                                                              to destroy it.

No design-time references needed. I just have to know Project name, class name and functions in that class.

I guess, I'll have to ask someone in CS to delete this question. Sorry anv.
I have several applications out that allow users to write plugins. The way I do it is to provide a standard interface that the plugin implement. This also needs a calling mechanism. I have a user-customisable validation routine which uses rules to validate data before it gets written to the database. To simplify things a little: rule is made up of  2 expressions (operands) and an operator (equality or inequality). The expressions are small scripts and can contain functions here is are 2 examples:


How it works:

First the users write a DLL that implements this (named IValidFunctionPlug):
Public Function RunFunction(FunctionName As String, _
                            vntParameters As Variant) As Variant
End Function

The interface must be simplistic

Inside their DLL plugin object:

Implements IValidFunctionPlug

Private Function IValidFunctionPlug_RunFunction(FunctionName As String, Parameters As Variant) As Variant
    On Error GoTo ErrorHandler

    Select Case LCase(FunctionName)
        Case "isninumber"
             IValidFunctionPlug_RunFunction = IsNINumber(Parameters)
        Case "convertnull"
             IValidFunctionPlug_RunFunction = ConvertNull(Parameters)
        Case "minimumage"
             IValidFunctionPlug_RunFunction = MinumumAge(Parameters)
        Case "maximumage"
             IValidFunctionPlug_RunFunction = MaximumAge(Parameters)
        Case "isnull"
             IValidFunctionPlug_RunFunction = ValueIsNull(Parameters)
        Case "today"
             IValidFunctionPlug_RunFunction = TodaysDate()
        Case "yearsdiff"
             IValidFunctionPlug_RunFunction = DateTimeDiff("yyyy", Parameters)
        Case "monthsdiff"
        Case Else
            Err.Raise 5, , "'" & MstrFunctionName & "' is not a recognised function name."
    End Select

Yes - its a big case statement. The case statement passes the function call on to the author's (user's) code - nasty but it works.

The user compiles it and it the object is registered.

In my app code the expression parser is recursive. It evaluates each part of the expression as it goes along.
When it comes to evaluating the function call it splits the string into two parts on "::"
    PluginReference = "stdValidPlugin.stdRules"
    FunctionReference = "yearsdiff(DateBirth,statusdate)"

Then I use code like this
    Dim Result As Variant
    Dim FunctionName As String
    Dim objPlugin As IValidFunctionPlug
    Dim vntParameters() As Variant

'The Function Name and parameters are extracted from FunctionReference and parameters evaluated.  The parameters can conttain reference to data or, can be further function calls - hence the recursive nature. The values are placed into a variant array: vntParameters

   Set objPlugin  = CreateObject(PluginReference)  ' latebound - but we know the interface
   Result = objPlugin.RunFunction(FunctionName, vntParameters)

Anyway sorry it was so longwinded. I tried to simplify as musch as I could. I hope it helps.

Experts Exchange Solution brought to you by ConnectWise

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
I should have known - that took me about half an hour to type into the box and you've worked it out yourself two minutes after I started typing. Anyway I hope the calling mechanism stuff helps a little.
I think this should be kept, some mighty jucy info here I recon.
Dingle Berry
dbrckoviAuthor Commented:
Really informative post. I would have accepted it immediately without going to CS.

You know what?
I'm so happy this works after so much time of frustration that I'll give the points anyway.
dbrckoviAuthor Commented:

For participating! :-)
Who howdy! My first expert points! Thank ya!
I will have a big cold one come quiten time and tost ya!
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.