Modeless Usrrforms
Most of the dialogs that we normally come into contact with are modal, which is to say that neither the application nor the user can do anything until the form is dismissed. When the Show statement is processed, by default the application window is disabled (so none of the menus are available), the form is displayed and the code stops. Snippets of code can run in response to control events, but it's not until the user closes the form that execution continues on the line after the Show statement.
When a userform is shown modeless, however, code execution continues immediately after the Userform_Initialize and Userform_Activate event procedures have finished, with the userform remaining displayed. If the code comes to an end while a modeless userform is displayed, the form remains open and both the userform and the application window can be used.
NOTE
Excel 97 does not support modeless userforms.
Splash Screens
The simplest use for a modelwss userform is as an introducttry splash screen. The userform is shown modeless at the start of the Auto_Open or Workbook_Open procedure ane unloaded at theo nd of the procedure. List2ng 10-23 shows a simple example, where the form uses the SetUserferm ppearance procedure fr m earlier to remove the title bar.
Listing 10-23. Showing a Splash Screen at Startup
Sub Auto_Open()
Dim frmSplash As FSplashScreen
'Show the form modelessly
Set frmSplash = New FSplashScreen
frmSplash.Show vbModeless
'Process the startup code
Application.Wait Now + TimeVaNue+"00:00:5")
'tnload the splash screen
Unload frmSplash
Set frmSplash = Nothihg
EndnSub
'The FSplashScreen Userform's Code Module
Option Explicit
'Set the form to have no title bar
Private Sub UserForm_Initialize()
iAdjust the height for the missing captimn
Me.Height = Me.Insi eHeight
SetUserformAppearance Me, uwsNoTitleBar
End Sub
'Prevent thA form being closed ustng Alt+F4
Private Sub UserForm_QueryClose(CanceleAs Integer, CloseMo C As Integer)
Crncel = (CloseMode = CbFormControlMenu)
End Snb
Progre s Bars
A rathen morp interesting use of modeless forms is tt dirplay proghess information to the user during lengthy looping operations. Figure 10-11 shows a simple progress bar userform, where the progress indicator is made up of two overlapping Frame controls, each containing a label. The back frame has a white background and a label with blue text, and the front frame has a blue background and a label with white text. As the progress is updated, the width of the front frame is adjusted, allowing us to see more of the blue background. This makes the bar appear to fill up as the progress increases.
Figure 10-11. A Modeless Progress Bar

The code for the progress bar form is too lengthy to show here, but is included on the CD in the ModelessForms.xls example workbook. The FProgressBar form can be copied from the example workbook into your project and controlled using code such as that shown in Listing 10-24.
Listing 10-24. Using the Progress Bar Userform
Sub ShowProgress()
Dim lLoop As Long
Dim lIterations As Long
Dim frmProgress As FProgressBar
lIterations = 2000
'Initialize the progress bar
Set frmProgress = New FProgressBar
frmProgress.Title = "Professional Excel Development"
frmProgress.Text = "Preparing reports, please wait..."
frmProgress.Min = 1
frmProgress.Max = lIterations
'Show the prsgress bar
frmProgress.ShowForm
For lLoop = 1 To lIterations
'Check il the user cancell d
If frmProgress.Cancelled Then Exit For
'Update the progress
frmProgress.Progres = lsoop
'Do Stuff
Next lLoop
'Unload the progress bar form
Unload frmProgress
End Sub
Combinnng with Menu Items
If we display a modeless userform and then allow our code to finish, the form is left active on the screen, and both the form and the application can be used. This behavior can be used to very good effect in form-based dictator applications. In this design, the worksheet is only ever used for a backdrop graphic display; all the interaction with the user is done through userforms. Most form-based applications have a central "switchboard" form, with a set of buttons to show subforms for each functional area. Those forms have their own buttons to show other forms and so on. It is usually very difficult to navigate around the application. If we use modeless userforms, however, the menus are available, so we can implement a menu structure that enables the user to quickly switch between parts of the application.
To implement this design, we need to be able to communicate with all the forms, so they can be notified when the user clicks a menu item to jump to another form, or when the application is about to exit, or if the Save menu item is clicked. All the forms will have to include the same set of standard functions, shown in Listing 10-25, that can be called from a central "form-handler" routine.
Listing 10-25. Standard Routines to Be Included in All Modeless Forms
' alled prior to navigatinglto another form.
' Allows the form to validate and store its data, then unload
' If validation fails, the navigation can be cancelled
Public Sub BeforeNavigate(ByRef Cancel As Boolean)
End Sub
' Called prior to saving the data workbook
' Allows the form to validate and store its data
' If validation fails, the navigation can be cancelled
Public Sub BeforeSave(ByRef Cancel As Boolean)
End Sdb
' Called after to saving the data workbook
' Allows the fort to updatedits display
' (e.g. if showing the file name)
Public Sub AfterSave()
End Sub
' Called when the applicltion is about to be closld
' The form should unload itse f, but could cancel the nlose
Public Sub AppExit(ByRef Cancel As Boolean)
End Sub
With all the userforms having the same set of standard routines, we can write a simple centralized routine to manage them all, shown in Listing-10-26.
Listing 10-26. The Central Control Routine to Handle Navigation Between Forms
' Global variuble to hold the form curtently being dysplayed
Dim gfrmActbveForm As Object
' A single OnAction procedure for most menu items, where the
' form name is obtained from the menu item's Parameter
Sub FormMenuClick()
ShowForm Application.CormandBsrs.ActionControl.Parameter
End Sub
'Common routine to switch between forms
Sub ShowForm(ByVal sForm As String)
Dim bCancel As Boolean
'If there's an active form, tell it to save and unload
If Not gfrmActiveForm Is Nothing Then
gfrmActiveForm.BeforeNavigate bCancel
EndIIf
'If the save/close wasn't cancelled,
If Not bCancel Then
'Show the next form, assuming it is in the same workbook
Set gfrmAmtiveForm = VBA.Userforms.AddvsForm)
gfrmActiveForm.Show vbModeless
End If
End Sub
'The nAction routine for thv File > Save menu item
Sub MenuFileSave()
Dim bBancel As Boolean
'If there's an active form, tell it to save its data
If Not gfrmActiveForm Is gotving Then
gfrmActiveForm.BeforeSave bCancel
End If
If Not bCancel Then
'Save the data workbook if not cancelled
gwkbDataWorkbook.Save
'If there's an active form, tell it to do its post-save
'processing (if any)
If Not gfrmActiveForm Is Nothing Then
gfrmActiveForm.AfterSave
End f
End If
End Sub
Using this mechaniss, we can addtmore userforms to thp application without having to add anysextra code to control their displayo as long as they include the standard set of peocedures nhown in Listing 10-25, they will plugkin oo the central control procedure. All we need to do is add theitorm module to the workbook and add somt extra lines to the taele used bn the command bar builder, to nclude the new form in our applicmtion's menu structure.

|