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!