Visual Basic

What Are the Benefits of Subclassing?

Subclassing allows you to extend, expand, and even diminish, or degrade, the existing Visual Basic functions and subroutines-perhaps to add extra validation of parameters, perform additional processing to the original function, or even to change the purpose of the function or subroutine altogether. This last choice has obvious pitfalls for users who are not aware that a routine now performs a completely different function than what the manual says, and should be avoided for that reason. For the first two purposes, however, subclassing can add real value to the existing Visual Basic equivalents.

One useful application of subclassing that we have implemented is in replacing the standard Visual Basic MsgBox function. The code for our MsgBox function is shown here:

Public Function MsgBox(ByVal isText As String, _
      Optional ByVal ivButtons As Variant, _
      Optional ByVal ivTitle As Variant, _
      Optional ByVal ivLogText As Variant, _
      Optional ByVal ivBut1Text As Variant, _
      Optional ByVal ivBut2Text As Variant, _
      Optional ByVal ivBut3Text As Variant, _
      Optional ByVal ivBut4Text As Variant) As Integer
  '==================================================================
  '
  '    Module: Message_Box. Function: MsgBox.
  '
  '    Object: General
  '
  '    Author - TMS Programmer. TMS Ltd.
  '    Template fitted : Date - 01/07/95    Time - 14:27
  '
  '    Function's Purpose/Description In Brief
  '
  '    Internal, replacement MsgBox function and statement used in
  '    TMS Tools. Allows four buttons, configurable button caption text,
  '    and logging of error text to a LOG file. See nInternalMsgBox
  '    for more information.
  '
  '    This function provides a simple wrapper around frmIMsgBox's
  '    nMb2InternalMsgBox method, allowing that method to be called
  '    without bothering with the class prefix. As such, its name is
  '    not nMb1MsgBox but MsgBox so as to keep its name short and such
  '    that it overrides VBA's function/statement of the same name.
  '
  '    Revision History:
  '
  '    BY            WHY & WHEN            AFFECTED
  '    TMS Programmer. TMS Ltd. - Original Code 01/07/95, 14:27
  '
  '    INPUTS - See nMb2InternalMsgBox for a description.
  '
  '
  '    OUTPUTS - Possibly nothing, possibly an integer; i.e., as
  '              it's a VB function, its return value may be ignored.
  '              See nMb2InternalMsgBox for a full description.
  '
  '==================================================================
      ' Set up general error handler.
      On Error GoTo Error_In_General_MsgBox:
      Const ERROR_ID = "Message_Box - General_MsgBox"
      Call TrTMS2TraceIn(ERROR_ID)
      ' ========== Body Code Starts.==========
      Dim fp      As Form
      Dim sTitle  As String
      ' Create the message box form.
      Set fp = New frmIMsgBox
      Load fp
      If IsMissing(ivTitle) Then
          sTitle = App.MsgBoxTitle & App.Title
      Else
          sTitle = App.MsgBoxTitle & CStr(ivTitle)
      End If
      ' Create and show the message box.
      MsgBox = fp.nMb2InternalMsgBox(isText, ivButtons, sTitle, _
                                     ivLogText, ivBut1Text, _
                                     ivBut2Text, ivBut3Text, ivBut4Text)
      ' Destroy the message box form.
      Unload fp
      Set fp = Nothing
      ' ========== Body Code Ends.  ==========
      Call TrTMS2TraceOut(ERROR_ID)
      Exit Function
  ' Error handler
  Error_In_General_MsgBox:
      ' Store error details on stack. Pass procedure name.
      Err.Push ERROR_ID
      ' Add rollback code here...
      Err.Pop
      ' Call TMS error handler.
      Select Case frmErrorHandler.nEhTMSErrorHandler
          Case ERROR_ABORT: Resume Exit_General_MsgBox
          Case ERROR_RETRY: Resume
          Case ERROR_IGNORE: Resume Next
          Case ERROR_END: Call GuDoEndApp
          Case Else: End
      End Select
  Exit_General_MsgBox:
  End Function

This is an example of a routine where we have completely replaced the original Visual Basic functionality. However, it is also possible to use the existing functionality and extend it, as in the following example:

Public Property Get EXEName() As String
      EXEName = UCase$(VB.App.EXEName & _
          IIf(App.InDesign = True, ".VBP", ".EXE"))
  End Property

Here we are simply taking the EXEName property of the App object and reformatting it to our own standard. Note that to access the original Visual Basic property we must fully qualify the reference. When this is done, Visual Basic ignores the rules above for resolving the location of the routine and instead resolves it directly using the explicit reference.

The potential for subclassing Visual Basic intrinsic functionality should not be underestimated. In the MsgBox example alone, the scope you have for customization is enormous. For example, the TMS MsgBox function allows you to log any message displayed with the vbCritical flag. It contains auto-reply functionality in which you can have the message box automatically choose a reply after a given period of time. You can also configure up to four buttons with custom captions. All this functionality from one Visual Basic method!