# VBForums UtilityBank > UtilityBank - Tutorials >  Tutorial: Using Reserved Words as VB6 Class Member Names

## dilettante

*Title*

VB6 Polymorphism as a Means of Using Reserved Words as Class Member Names in VB6

*Description*

On rare occasions you'll want to create a VB6 Class, UserControl, Form, etc. that has methods or properties that duplicate VB6 keywords that the IDE and compiler just won't allow.  Some examples might be Open, Close, Stop, and many others.

The VB6 manuals (and the versions contained in the MSDN Library articles) cover the mechanism required in the sections on creating and using objects under inheritance and polymorphism.  However they do not directly address what you need to do regarding these reserved words.

I haven't seen a decent writeup anywhere on this topic so I thought I might give it a go myself.

This tutorial is an attempt to provide an example of how you might do this, embedded in a working demo Project.

_This is a 300 level tutorial, not for beginners._  It assumes a good deal of knowledge, requires a Windows SDK of recent vintage, and touches your dev system's registry (though we'll try to clean that up too).  I will try to keep things as simple as I can nonetheless.

Everything described may work just as well for VB5.

*Author name*

Bob Riemersma

*System Requirements*

Windows 2000 or newer (though even Win95 may be fine).
VB6 Professional or better installed.
A recent vintage Windows SDK installed (6.0 was used here).
Administrative rights on the system (which you really need for VB6 development anyway).

*License info*

Free for anyone to use or copy with attribution.  No warranties or guarantees, etc.  As-is information, use at your own risk.


*Introduction*

So why might you want to do this?

Well, sometimes it can just be annoying to have to name your "open" method OpenFile rather than Open but that generally isn't important enough for you to go to all this trouble.

But you might be creating a DLL for use in lots of projects, by others, etc. and it has a kind of raggedy look to have to decorate your class member names just so they'll compile.

Or in the case at hand (our guinea pig Project) I'm writing a small script host (using the MS Script Control) where I want to offer a few standard WSH objects and methods on them.  In particular I want to implement a stripped down version of WScript.StdOut that has a Write method on it.  "Write" is a VB reserved word so you can't normally use it as a method name.


*Step 1: First Attempt*

The Project is named RunScript.  First Attempt is the name of a folder in the attached archive that attempts to limp along using xWrite instead of Write as we'd prefer to.

This means my StdOutSim.cls looks like this:


```
Option Explicit
'
'A partial WScript.StdOut object simulation.
'

Public Sub WriteLine(Optional ByVal Text As String = "")
    xWrite Text
    xWrite vbNewLine
End Sub

Public Sub xWrite(ByVal Text As String)
    UIForm.txtOut.SelText = Text
End Sub
```

But it also means my test script GraphSin.vbs must look like:


```
Sub Plot(ByVal X, ByVal Y)
    Dim Line
    Dim Pos

    Line = Spaces & "|" & Spaces
    Pos = 1 + (Y + 1) * Scale
    Line = Left(Line, Pos - 1) & "*" & Mid(Line, Pos + 1)
    With WScript.StdOut
        .xWrite FormatSingle(X)
        .xWrite " -"
        .xWrite Line
        .xWrite "+"
        .WriteLine FormatSingle(Y)
    End With
End Sub
```

Bleh.  Can we do better?


*Step 2: Make a DLL*

Make a DLL is the name of the next folder we have.  It is used to create a DLL containing the classes we want to use reserved words in, prefixed "I-" (for interface).  In my case I only need to tweak StdOutSim.cls so that's all I'll include.

The steps involved here are:
Make a new VB6 ActiveX DLL Project.Change the Project name to RunScriptInterfaces.Remove the unneeded auto-created Class1.cls that we don't want.Copy StdOutSim.cls into this folder as IStdOutSim.cls.Use "Add file..." to add this class to our DLL Project.Rename the class from StdOutSim to IStdOutSim.Change the class Instancing from Private to MultiUse.Edit StdOutSim as shown below:



```
Option Explicit
'
'A partial WScript.StdOut object simulation interface template.
'

Public Sub WriteLine(Optional ByVal Text As String = "")
'Code not needed or wanted here:
'    xWrite Text
'    xWrite vbNewLine
End Sub

Public Sub xWrite(ByVal Text As String)
'Code not needed or wanted here:
'    UIForm.txtOut.SelText = Text
End Sub
```

The attached archive has this folder and these Project files already made.

Then we can go ahead and compile our DLL.  After that go ahead and delete leftovers like .LIB and .EXP files.

Finally, drag and drop the new RunScriptInterfaces.dll's icon onto the icon of the provided DLLUnreg.vbs script.  This will unregister our DLL since we don't need it - just a little cleanup.


*Step 3: Extract the IDL*

No archive folder for this step, but we'll use the one from the next step.

Now we'll need to get the type library info from our DLL in a useful form so we can edit it and ultimately compile it into a standalone typelib (TLB) file.

One easy way is to use the OLE View utility, either from your VS 6 Tools Start Menu shortcut or you can use the version from your Windows SDK's Bin folder.  Run this and then open your DLL via View TypeLib...:


This should open a second window with the generated IDL code in the right pane.

Don't bother trying to use the Save menu there, it creates a broken Unicode text file that is useless.  It still does this even using the SDK 7.0 version of OLE View so you can see it doesn't get much love from Microsoft.

Instead open Notepad, then click in the right pane where the generated IDL is, press Ctrl-A to select all text, Ctrl-C to copy it, and then paste that into Notepad.

Finally close both OLE View windows (we're done) and save the Notepad file as a Orig RunScriptInterfaces.odl with ANSI encoding into the next folder...


*Step 4: Modify the IDL*

This folder (from the attached archive) comes with these files in it:

_Annotated ODL.rtf_ - An RTF file showing my original ODL (IDL) with replaced and deleted lines struck out in red and new/changed lines in blue.  A helpful "how to" guide for editing your DLL's ODL file to make a new interface ODL source._Orig RunScriptInterfaces.odl_ - This was my original ODL before editing.  Save yours over it._RunMidl.cmd_ - A batch file we'll use to compile your edited ODL source._RunScriptInterfaces.odl_ - My final ODL after editing._SDK Files Needed.txt_ - A short text document listing the files you will want to copy from the Windows SDK into a handy Make TLib folder for easy running of the MIDL compiler.

So you overwrote Orig RunScriptInterfaces.odl here in the previous step.  Now you need to edit it and save the edited version as RunScriptInterfaces.odl (reaplcing the one I provided) and you can just use Notepad for this.

The .RTF document shows what must change, but there are three GUID values you need to recreate with new values yourself.  If your interfaces TLB will have more classes in it (we just have the one in this simple tutorial) you'll have more GUIDs to replace.

In theory we can use the ones created originally by the VB6 compiler since we've unregisrtered them.  But to be thorough go ahead and use a GUID generator to make fresh ones.  I tend to just use GuidGen.exe from the SDK's Bin folder.



*Step 5: Make TLib*

Create this folder yourself.  It can be handy for future projects, so maybe put it someplace among your stored VB6 project folders or somewhere.

Follow the directions in SDK Files Needed.txt about the files to copy here from your Windows SDK.

Copy the RunMidl.cmd file into here from the archive's Modify the IDL folder.  Then move your edited and saved RunScriptInterfaces.odl file here as well.

_Drag and drop_ RunScriptInterfaces.odl's icon onto RunMidl.cmd's icon in an Explorer window.  This is an easy way to accomplish the MIDL compiler run.

This should produce two new files if all goes well:

_log.txt_ - The MIDL compiler messages, errors if any, etc._RunScriptInterfaces.tlb_ - Your new interfaces type library, ready for use.


*Step 6: Second Attempt*

Here we'll take our first approximation and create a new and improved (Now with Write!) version of RunScript.

Copy the original Project files into a new folder.  Second Attempt from the archive already has this done.

Make a few changes...

First we need to reference our new TLB.  We can do this via "Project|References..." in the IDE, where we'll use the Browse button:


Then we need to modify our StdOutSim class:



```
Option Explicit
'
'A partial WScript.StdOut object simulation.
'

'We'll implement the "abstract class" IStdOutSim here:
Implements RunScriptInterfaces.IStdOutSim

Private Sub IStdOutSim_Write(ByVal Text As String)
    UIForm.txtOut.SelText = Text
End Sub

Private Sub IStdOutSim_WriteLine(Optional ByVal Text As String = "")
    IStdOutSim_Write Text
    IStdOutSim_Write vbNewLine
End Sub
```

Getting those "event handler like" interface proxy method signatures is easy, and much like getting them for more usual event handlers once we've added the Implements... line to the class:


Then we'll need to modify the WScriptSim class to use our new interface on our class:



```
Option Explicit
'
'Global Object class, an instance of which is added to the
'Script Control as global object "WScript".  This is how our
'scripts interact with the host.
'
'A partial WScript object simulation.
'

'Private WshStdOut As StdOutSim becomes:
Private WshStdOut As RunScriptInterfaces.IStdOutSim

'Public Property Get StdOut() As StdOutSim becomes:
Public Property Get StdOut() As RunScriptInterfaces.IStdOutSim
    Set StdOut = WshStdOut
End Property

Public Function CreateObject(ByVal ProgId As String, Optional ByVal Prefix As String) As Object
    'We ignore Prefix in this implementation.
    Set CreateObject = VBA.CreateObject(ProgId)
End Function

Public Sub Echo(ParamArray Text())
    WshStdOut.WriteLine Join$(Text, vbNewLine)
End Sub

Public Sub Quit(Optional ByVal Status As Long)
    Err.Raise gINTERNAL_ERROR 'Internal error, catch this in Script Control Error event!
End Sub

Private Sub Class_Initialize()
    Set WshStdOut = New StdOutSim 'But we create an instance of the "concrete class."
End Sub
```

Now we can go ahead and compile our new program.

But before running it we'll need to update our script:



```
Sub Plot(ByVal X, ByVal Y)
    Dim Line
    Dim Pos

    Line = Spaces & "|" & Spaces
    Pos = 1 + (Y + 1) * Scale
    Line = Left(Line, Pos - 1) & "*" & Mid(Line, Pos + 1)
    With WScript.StdOut
        .Write FormatSingle(X)
        .Write " -"
        .Write Line
        .Write "+"
        .WriteLine FormatSingle(Y)
    End With
End Sub
```


*Cleanup*

By adding the reference to our TLB we caused VB6 to register it.  We don't need the crud left in the registry, and it seems that the VB6 compiler is quite happy to continue using it even after unregistering it!  Perhaps this only works if the TLB is "next to" the VBP file or something, but it seems to work fine.

To unregister the typelib you can _drag and drop_ RunScriptInterfaces.tlb's icon onto the icon of the provided TLBUnreg.vbs (provided in the archive's Second Attempt folder).



*Last Word*

This works great for many VB6 reserved words.  However one that is particularly stubborn is the Print pseudo-method.  The compiler handles this and a few others as special cases.

That doesn't mean you _can't_ do this with Print, but you won't be able to invoke it from within a VB6 program.  It still works for a script via Script Control (VBScript doesn't care about "Print" as a reserved word), or it works compiled into a DLL that some other language will use.  But for VB6 it just isn't going to happen as far as I can tell.

At best you _might_ get away with syntax such as this:



```
fudd.[Print] arg1, arg2, arg3
```

... assuming an object fudd of a class you have created a Print method on via this polymorphism trick.

I hope this information helps someone.  As I said, I haven't seen it written up before even though a lot of us know about it.

----------


## Dragokas

dilettante, thanks a much. Very clearly explained and very easy to use.

Little things:
I just would like to leave here more detailed instruction how to build TLB from ODL:

A) If you have Visual Studio installed:

Go to Start menu => Visual Studio => Visual Studio tools => Developer Command Prompt for VS

Enter:


```
cd /d "Path to folder where your ODL located"

midl.exe /mktyplib203 RunScriptInterfaces.odl
```

B) If VS is not installed (or if your need exactly SDK v6.0, because some ODLs cannot be compiled with newer versions):

Download SDK 6.0: online installer or stand-alone. Install it.

Create such bat-file (right click on 'RunMidl.cmd' => Edit):


```
set SDK=C:\Program Files\Microsoft SDKs\Windows\v6.0
set PATH=%SDK%\Bin;%SDK%\VC\Bin;%PATH%
set INCLUDE=%SDK%\Include

midl.exe /mktyplib203 "%~1"
pause
```

If you have Windows x64, you need replace C:\Program Files by C:\Program Files (x86)

Drag and drop RunScriptInterfaces.odl's icon onto bat-file.

You will see RunScriptInterfaces.tlb created.
-----------------
Also, I'd like to note that CreateObject("TLI.TLIApplication") is not working on some OS. However, this has almost no relation to this topic.
____________
Only one question: Bob Riemersma is an author of idea, of this tutorial, or ?

----------


## Dragokas

It's pity that approach cannot be used in mixed mode, like:


```
Implements RunScriptInterfaces.IStdOutSim

Private Sub IStdOutSim_Write(ByVal Text As String)
    UIForm.txtOut.SelText = Text
End Sub

Public Sub WriteLine(Optional ByVal Text As String = "")
    IStdOutSim_Write Text
    IStdOutSim_Write vbNewLine
End Sub
```

So, if I need to add new method/property I must change interface (edit ODL, recompile; if I not sure how, I also need again re-create dll, extract typelib e.t.c.),
instead of just adding new method to class as usual. So, it's very inconvenient especially if program is under active development.

----------


## dilettante

> Only one question: Bob Riemersma is an author of idea, of this tutorial, or ?


The tutorial.

----------

