Chilkat ActiveX Object Creation in VB6 (Visual Basic 6.0)

Most ActiveX objects, including Chilkat, provide what is called a “dual interface”.   A dual interface allows for programs to bind at compile-time (early binding) or at runtime (late binding).

The type of binding is determined by how the object is created.  For example, compile-time binding in VB6 looks like this:

Dim cert As New ChilkatCert

Runtime binding looks like this:

Set cert = CreateObject(“Chilkat_9_5_0.Cert”)

An ActiveX class (such as ChilkatCert) has a set of properties and methods.  In the underlying COM object, these are contained in a “vTable”, which is an array of function pointers.  Each method or property (i.e. entry) is a function pointer occupying a particular position in the vTable.  For example, the function LoadPem might be the function pointer at index 12.

When compile-time binding is used, the indexes of the entries are hard-coded into  your VB6 executable.  When runtime binding is used, the entry is called by name.  The name is converted to the correct vTable index at runtime.  This means that if the positions of entries change, the application that uses runtime binding will not break.  The application that uses compile time binding must be recompiled to use the updated ActiveX.

For many years, the positions of the entries in the Chilkat ActiveX classes mostly did not change.  This was not by a deliberate action.  Recently, with the introduction of the Async versions of methods, and especially with the latest v9.5.0.64 release, the order of entries in the vTable has unintentionally changed.  This only affects programs that use compile-time (early) binding.  Most languages that provide the ability to use ActiveX classes, such as classic ASP, SQL Server, etc. only provide the ability to create objects via CreateObject (i.e. runtime/late binding), and are thus unaffected.

This leaves VB6 programs using compile-time binding in a difficult position.  If a new version of the ActiveX is registered, then the VB6 application must be recompiled.  It’s not possible to simply install the new ActiveX *if* the vtbl has changed.  Unfortunately, there is no way to fix the versions of Chilkat that have already been released.  In addition, there is no way to make the next version of Chilkat have the same vTable ordering as previous versions.  For example, if v9.5.0.59 has order A, and v9.5.0.64 has order B, then v9.5.0.65 cannot have and order that matches both A and B.

The solution is to have a scheme in place that works going forward.  The proposed scheme is this:

  1. Starting with v9.5.0.65, the vtbl order will become established.  Future versions of Chilkat (where the CLSID is the same) will have vTables with the order of entries matching v9.5.0.65.
  2. When Chilkat releases an entirely new ActiveX, where the CLSID changes and the version, for example, becomes 10.0.0, then the vTable order can change.  This is OK because effectively it’s an entirely new ActiveX.  In other words, the CreateObject statement becomes:  CreateObject(“Chilkat_10_0.Cert”) instead of CreateObject(“Chilkat_9_5_0.Cert”).  When the CLSID changes, and the names of the objects change, then it’s a new ActiveX that can be registered and coexist with the older Chilkat ActiveX.  To use the entirely new ActiveX, a VB6 program would have to remove it’s reference from the old, and add a reference to the new. (When adding a reference in VB6, you would see BOTH “Chilkat_10_0” and “Chilkat_9_5_0” and you could choose either.

 

Using the Chilkat ActiveX in VB6

To use the Chilkat ActiveX in a Visual Basic 6.0 program, review each of these items to make sure you’re doing everything correctly:

  1. Make sure you’re using the 32-bit ActiveX, even on 64-bit Windows.
  2. The ActiveX must be registered (via regsvr32) on each computer.  If you’re having trouble, try using the .msi installer available here: Chilkat 32-bit ActiveX MSI Installer
  3. The ActiveX should be added to the VB6 project by adding a reference.  Add a reference from the VB6 menu “Project–>References”.  Do NOT “add the component”.  Do NOT add the ActiveX via the “Project–>Components…” menu item.  You should NOT see anything added to the VB6 palette.  The Chilkat objects are non-visual and should always be instantiated dynamically using the New keyword.  Do NOT drag-and-drop a Chilkat object onto a form.  (This should not be possible if you’ve only added a reference.)
  4. If the first method call on an object crashes, check to see if the object was created.  Check to see if the variable is Nothing prior to calling the method.  If there is still a problem, check to see if you can examine the Version property.  All Chilkat objects have a Version property.  If the access to the Version property crashes, the ActiveX object was never instantiated.  It may not be registered correctly, or your program may have never created an instance via the New keyword.
  5. If you see a .oca file, this is not something provided by Chilkat.  It is something VB6 generated.  If you recently updated to a new version of the Chilkat ActiveX, delete the old .oca.

VB6 FTP File Upload Progress Monitoring

Question:

I’ve been trying to get the progress bar in VB6 to work, based on the code on your website, but I’m having no luck.  The event isn’t even being triggered.

Answer:

Here are some things to try:

  1. Test progress monitoring with a large enough file  such that the progress does not go from 0 to 100% instantly.
  2. Use the VB6 IDE to generate the event callback method to make sure you have the naming correct.
  3. Set the SendBufferSize property to a smaller value, to get more frequent callbacks.  See the reference documentation: http://www.chilkatsoft.com/refdoc/xChilkatFtp2Ref.html
  4. Make sure your event callback function updates the UI such that the changes are rendered immediately.  For progress bar controls, setting the Value is all that is needed.  For other controls, you may need to call Refresh.

VB6 Error — “TYPE MISMATCH (ERROR CODE 13)” w/ IMAP Search method

This happens if the Chilkat ActiveX objects are dragged and dropped onto your formvia the “Project–>Components” menu. Instead, add a reference to the objects via the “Project–>References” menu.

Instances of the object should be created dynamically. For example:

Dim imap as ChilkatImap
Set imap = New ChilkatImap

VB6 – “TYPE MISMATCH (ERROR CODE 13)” or “Invalid Use of New Keyword”

This error occurs if you incorrectly add the ActiveX component to your VB6 project.  Follow these rules:

1) If the ActiveX objects are dynamically created (they are not dragged and dropped onto a form from the palette), then add a Reference to the ActiveX.  You should NOT see the icons for the ActiveX in the palette.  Instances of the ActiveX objects are created by New statements in your code.

2) If the Chilkat ActiveX objects are dragged and dropped onto your form, then add the component via the “Project–>Components” menu, NOT the “Project–>References” menu.  In my opinion, it is always better to create instances of the objects dynamically because the Chilkat objects are not visual controls and won’t be visible on your form anyway at runtime.

3) Never do both — you should either add a Reference (Project–>References) or add the component to the palette (Project–>Components) but NEVER BOTH.

How to use an ActiveX in VB6

There are two ways to reference an ActiveX in Visual Basic 6.0.  The first is to select “Project–>References” from the VB6 menu.  The second way is to select “Project–>Components…” from the VB6 menu.

Important:  You should do one or the other, but not both.

Which do you choose?   Use “Project–>References” if you are going to instantiate the ActiveX dynamically.  In other words, you’ll be creating the object dynamically using the New statement.  Such as:

Dim mailman As New ChilkatMailMan2

Dim mm as ChilkatMailMan2
Set mm = New ChilkatMailMan2

Use “Project–>Components…” if you are going to drop an instance of the component onto a Form. When you include an ActiveX using “Project–>Components…”, you’ll see icons added to your toolbox. In this case, you’ll see an icon for the Chilkat MailMan object. You would drag this onto your Form. Adding an ActiveX in this way only makes sense if the component has a visual interface. The Chilkat ActiveX components are non-visual, so there is no point in doing it this way, and I would highly recommend adding a Reference and instantiating the object instances dynamically using the New statement.

Common Errors:

If you add the ActiveX via “Project–>Components…”  and then try to instantiate an object dynamically using the New statement, you’ll get the “Invalid use of New keyword” error.

If you don’t add the ActiveX to your project in any way, (i.e not through “Project–>References” nor through “Project–>Components…”,  you’ll get the “User-defined type not defined” error.

SFTP Upload in VB6 with Progress Monitoring

The PercentDone event is called when the percentage completion increases by one or more points.  To use events in VB6, Dim the variable WithEvents.  Then name the event callback using the variable name.  (You should already understand how to use VB6 events in general prior to using the Chilkat objects.  A good VB6 book is “Programming Visual Basic 6.0” by Francesco Balena.

Here’s the example:

' Assumes a Form with a Button named "Command1" and a progress bar named "ProgressBar1".

Dim WithEvents sftp As ChilkatSFtp

Private Sub sftp_PercentDone(ByVal pctDone As Long)
    ProgressBar1.Value = pctDone
End Sub

Private Sub Command1_Click()

...


    ProgressBar1.Value = 0
    
    success = sftp.UploadFileByName(remoteFilePath, localFilePath)
    If (success <> 1) Then
        MsgBox sftp.LastErrorText
        Exit Sub
    End If
    
    MsgBox "Success."

End Sub

VB6 Variant vs Byte Array

In Visual Basic 6.0, a Variant containing a byte array is different than a byte array.
For example, examine this code:

    ' Assume mime is a ChilkatMime object...
    Set mimePart = mime.GetPart(1)
    
    thefile = FreeFile()
    'Get the attachment filename
    FileName = mimePart.FileName
    'Get the attachment
    Dim mBody As Variant
    mBody = mimePart.GetBodyBinary
    If Len(mBody) > 0 Then
        Open FileName For Binary As #thefile
            Put #thefile, , mBody
        Close #thefile
    End If

The result is not what you expected. There’s a mysterious extra 12 bytes prepended to the content that is saved. Why? Because you saved the Variant structure as well as the contents of the Variant.
This is what you really wanted:

    ' Assume mime is a ChilkatMime object...
    Set mimePart = mime.GetPart(1)
    
    thefile = FreeFile()
    'Get the attachment filename
    FileName = mimePart.FileName
    'Get the attachment
    Dim mBody() As Byte
    mBody = mimePart.GetBodyBinary
    If UBound(mBody) > 0 Then
        Open FileName For Binary As #thefile
            Put #thefile, , mBody
        Close #thefile
    End If

In the above code fragment, mBody is a byte array. There is no Variant structure encapsulating the data. The content of the MIME body is saved exactly as you expected.

Note: There is an implicit conversion happening in this statement:

mBody = mimePart.GetBodyBinary

GetBodyBinary is a function that returns a Variant. However, mBody is declared as an array of Byte. Therefore, the VB6 runtime is converting the Variant to a byte array. In other words, it’s removing the Variant wrapping so-to-speak…

Visual Basic Font.Charset Property

Charset Name Charset Value
(Hex)
Charset Value
(Decimal)
Code-Page ID
ANSI_CHARSET 0x00 0 1252
DEFAULT_CHARSET 0x01 1
SYMBOL_CHARSET 0x02 2
SHIFTJIS_CHARSET 0x80 128 932
HANGUL_CHARSET 0x81 129 949
GB2312_CHARSET 0x86 134 936
CHINESEBIG5_CHARSET 0x88 136 950
GREEK_CHARSET 0xA1 161 1253
TURKISH_CHARSET 0xA2 162 1254
HEBREW_CHARSET 0xB1 177 1255
ARABIC_CHARSET 0xB2 178 1256
BALTIC_CHARSET 0xBA 186 1257
RUSSIAN_CHARSET 0xCC 204 1251
THAI_CHARSET 0xDE 222 874
EE_CHARSET 0xEE 238 1250
OEM_CHARSET 0xFF 255