FORM-RELATED METHODS AND STATEMENTS

 

The Show and Hide Methods

 

The Show method of a form displays that form on the screen.  If the form to be shown is not already loaded into memory, the Show method will load it before showing it.  The Show method is typically used to transfer control from one form to another.  The syntax is:

 

      formname.Show

 

For example, if I am in Form1 and I want to display Form2, the syntax would be:

 

      Form2.Show

 

When you display one form from another, you may want the user to complete work on that form before returning to the first one.  This does not happen automatically. By default, VB will display the second form and then continue executing code from the first form.  To suspend execution of the first form until after the second form is done with, add the keyword constant vbModal as an argument to the Show method.  The syntax is:

 

      Form2.Show vbModal

 

The Hide method of a form removes the form from the screen (makes it invisible), but the form still remains in memory. The syntax is:

 

      formname.Hide

 

To refer to the form in which code is currently running (i.e. the "current" form, or the "active" form), you can of course refer to the form by its name, as in the example above:

 

          Form1.Hide

 

As an alternative, you can use the keyword Me. The keyword "Me" refers to the form in which code is currently running:

 

          Me.Hide

 

Finally, any time you want to execute a method of the form on itself, you can simply code the method name, omitting the "formname." or the "Me.", as in:

 

       Hide

 

 

The Load and Unload Statements

 

The Load statement loads a form into memory, but does not display it.  When you code the Load statement for a form, the Form_Load event of that form will be triggered.  The syntax is:

 

            Load formname

 

The Unload statement removes a form from memory and from the screen. When you code the Unload statement for a form, the Form_Unload event of that form will be triggered.  The syntax is:

 

      Unload formname

 

A form can unload itself, as in:

 

      Unload Me

 

The Unload event is also triggered with the user clicks the Windows "close" button ("X") on the form. 

 

Try this:

·         Place a command button named "cmdExit" with the caption "Exit" on a form.  In the Click event for the command button, instead of coding "End",  code:

 

Private Sub cmdExit_Click()

 

     Unload Me

 

            End Sub

 

·         For the Form_Unload event, code the following:

 

Private Sub Form_Unload(Cancel As Integer)

 

    If MsgBox("Are you sure you want to quit?", _

              vbYesNo + vbQuestion, _

              "Unload Test") = vbNo Then

        Cancel = 1

    End If

 

End Sub

 

·         Run the program and observe what happens either when you click the Exit button, or when you try to close the form by clicking on the "X" button.

 

Note that VB supplies the Unload event with a built-in argument called "Cancel".  If, in the Unload event procedure, you set the Cancel argument to any non-zero value, the Unload event will be cancelled (i.e., the form will not be unloaded) and processing will continue.  This event is where you might ask the user if they are sure they want to quit.  If they respond Yes, let the Unload event "do its thing"; if No, set Cancel to non-zero value.

 

Note: When all forms of a VB project are unloaded, the application ends.  The End statement automatically unloads all forms in a project, but will not trigger the Unload event (so any code you have in the Unload event will not execute) – therefore, ending an application with "End" does not give the user a second chance to keep working with the program. The End statement ends the program abruptly.

 

Centering a Form on the Screen

 

The following code will center a form on the screen. It is best placed in the Form_Load event.

 

            Me.Top = (Screen.Height – Me.Height) / 2

Me.Left = (Screen.Width – Me.Width) / 2

 

In VB project that has multiple forms, it is a good idea to centralize the form-centering logic in a Public Sub procedure of a separate standard (BAS) module.  The sub, which accepts a Form object as a parameter, would look like this:

 

      Public Sub CenterForm(pobjForm As Form)

 

           With pobjForm

               .Top = (Screen.Height – .Height) / 2

        .Left = (Screen.Width – .Width) / 2

    End With

 

End Sub

 

With the above Sub in place, any form in the project can center itself with the following line of code:

 

      CenterForm Me

 

Form_Load vs. Form_Activate

 

In the Form_Load event, you would typically perform initialization-type tasks, as you should. However, certain types of actions cannot be performed in the Load event, due to the fact that the form is fully loaded only after the Load event completes. For one thing, printing to the form will not work when done in the Load event. In addition, if you try to set focus to a particular control on the form during the Load event, you will get the message Run-time error '5': Invalid procedure call or argumentFor example, assume you had a textbox called Text1 on the form.  The following code would result in that error:

 

      Private Sub Form_Load()

 

          ' other initialization stuff

 

          Text1.SetFocus      ' causes an error

 

      End Sub

 

The reason for the error is that since the form is not fully loaded, neither are any of the controls on it – and you can't set focus to a control that is not yet available.

 

To remedy this problem, you should use one of the other Form events, such as the Activate event. (When VB loads a form, it actually cycles through a number of events, such as: Initialize, Load, Resize, Activate, GotFocus, and Paint. Of these, Load and Activate are probably the ones most  commonly used. ) Placing the code to set focus to a control will work in the Form_Activate event:

 

      Private Sub Form_Activate()

 

          ' other statements

 

          Text1.SetFocus      ' no problem here

 

      End Sub

 

A caution about the activate event: it will fire whenever your application switches to that form. For example, if you switch back and forth between Form1 and Form2, be aware that any code you might have in the Activate events for these forms will be executed when you switch to that form. Therefore, if you have code in the Activate event that you only want to execute "the first time", you will need to control execution with a Boolean switch.  For example, in the General Declarations of your form you could define the following variable:

 

      Private mblnFormActivated As Boolean  ' will be initialized to False by default

 

You can then use this switch in the Activate event as follows:

 

      Private Sub Form_Activate()

 

          If mblnFormActivated Then Exit Sub

 

    ' statements you only want to execute once, including the following

    ' statement to turn the switch on:

 

          mblnFormActivated = True

 

      End Sub

 

Multi-Form Projects

 

Many projects will use more than one form. When you have more than one module (form or standard) in a project, you must specify a "Startup object", which is done via the Project menu, Properties item.  The startup object tells VB which form or standard module is to have its code run first (if a standard module is the startup object, it must contain a public subroutine called "Main", and "Sub Main" is specified for the Startup object).  By default, the startup object is the initial form that is supplied with every new VB Project.

 

Here are a couple of scenarios for projects with multiple forms:

 

(1)                 You have an application that performs a variety of functions, requiring multiple "screens" (forms).  You can use one form as a "switchboard" or "main menu" form that connects to the other forms.

(2)                 You may wish to have a "splash screen" start off your application before the main form is displayed.

 

Using Multiple Forms: "Switchboard" Example

 

Assume you have a project with three forms: Form1, Form2, and Form3. (To add forms to a project, go to the Project menu and select Add Form.) Form1 serves as the switchboard form, which contains three command buttons: cmdForm2, cmdForm3, and cmdExit:

 

 

 

 

The code behind these buttons is:

 

Private Sub cmdForm2_Click()

    Form2.Show vbModal

End Sub

 

Private Sub cmdForm3_Click()

    Form3.Show vbModal

End Sub

 

Private Sub cmdExit_Click()

    Unload Me

End Sub

 

 

        

 

For the sake of the example, Form2 and Form3 simply contain one button with the caption "Return to Main Menu".  The code behind the command button on each of these forms is simply Unload Me.  When either of these forms is unloaded, the main menu form will then become the active form.

 

 

Download the VB project code for the example above here.

 

 

*** BONUS MATERIAL ***

(Form Procedures)

Presented below is a set of procedures that can be used to work with forms. The code presented can be saved as a .BAS module (for example, modForm.bas) and can be included and used in any VB6 project.

 

The set of procedures is described below:

 

Procedure Name

Description

 

CenterForm

Centers a form on the screen. This Sub has been used in previous examples presented on this site.

 

Usage: CenterForm FormName

(where FormName is the name of the form without quotes (e.g. Form1) or the keyword Me)

 

To center the current form, you would use:

CenterForm Me

 

FormIsLoaded

Function that determines whether or not a form in your app is currently loaded. It does this by searching through the VB Forms collection. It accepts a string parameter containing the name of the form that you want to check and returns a Boolean.

 

Usage: If FormIsLoaded("Form1") Then ...

 

EnableFormXButton

Sub that lets you enable or disable the form's "X" (or "Close") button that appears in the right-hand corner of the form's title bar. (A common usage is to disable the X button.) This Sub is a wrapper for a handful of APIs that work together to accomplish this task (GetSystemMenu, GetMenuItemCount, RemoveMenu, DrawMenuBar).

 

Usage: EnableFormXButton FormName, BooleanValue

(where FormName is the name of the form without quotes (e.g. Form1) or the keyword Me and BooleanValue is True or False)

 

To disable the X button on Form1, you would use:

EnableFormXButton Form1, False

 

MakeTopmost

Sub that lets you keep a form "always on top", even if it does not currently have the focus. This Sub will also let you reverse the action and make the form "not" always on top. This Sub is a wrapper for the SetWindowPos API.

 

Usage: MakeTopmost FormName, BooleanValue

(where FormName is the name of the form without quotes (e.g. Form1) or the keyword Me and BooleanValue is True or False)

 

To make the current form "always on top", you would use:

MakeTopmost Me, True

 

LockWindow /

UnlockWindow

The purpose of these Subs is help avoid "flicker" when controls and their contents take longer than usual to populate on a form. These Subs are a wrapper for the LockWindowUpdate API, which disables drawing in the given window. Only one window can be locked at a time.

 

Usage (to lock): LockWindow FormName.hwnd

Usage (to unlock): UnlockWindow

 

The code is given below:

 

Option Explicit

 

Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long

Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long

Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long

Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwnd As Long) As Long

Private Declare Function RemoveMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long

Private Declare Sub SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long)

 

Private Const MF_BYPOSITION             As Long = &H400&

Private Const MF_REMOVE                 As Long = &H1000&

Private Const HWND_TOPMOST              As Long = -1

Private Const HWND_NOTOPMOST            As Long = -2

Private Const SWP_NOSIZE                As Long = &H1

Private Const SWP_NOMOVE                As Long = &H2

Private Const SWP_NOACTIVATE            As Long = &H10

Private Const SWP_SHOWWINDOW            As Long = &H40

 

'=============================================================================

'                     Form-related Routines

'=============================================================================

 

'-----------------------------------------------------------------------------

Public Sub CenterForm(pobjForm As Form)

'-----------------------------------------------------------------------------

 

    With pobjForm

        .Top = (Screen.Height - .Height) / 2

        .Left = (Screen.Width - .Width) / 2

    End With

 

  End Sub

 

'-----------------------------------------------------------------------------

Public Function FormIsLoaded(pstrFormName As String) As Boolean

'-----------------------------------------------------------------------------

   

    Dim objForm As Form

   

    For Each objForm In Forms

        If objForm.Name = pstrFormName Then

            FormIsLoaded = True

            Exit Function

        End If

    Next

   

    FormIsLoaded = False

 

End Function

 

'-----------------------------------------------------------------------------

Public Sub EnableFormXButton(pobjForm As Form, pblnEnable As Boolean)

'-----------------------------------------------------------------------------

 

    Dim lngSysMenuID As Long

    Dim lngMenuItemCount     As Long

   

    ' Get handle To our form's system menu

    ' (Contains items for Restore, Maximize, Move, Close etc.)

    lngSysMenuID = GetSystemMenu(pobjForm.hwnd, pblnEnable)

 

    If lngSysMenuID <> 0 Then

        ' Get System menu's menu count

        lngMenuItemCount = GetMenuItemCount(lngSysMenuID)

        If lngMenuItemCount > 0 Then

            ' Remove (hide) the "Close" item itself (the last menu item) ...

            RemoveMenu lngSysMenuID, lngMenuItemCount - 1, MF_BYPOSITION Or MF_REMOVE

            ' Remove (hide) the seperator bar above the "Close" item

            ' (the next to last menu item) ...

            RemoveMenu lngSysMenuID, lngMenuItemCount - 2, MF_BYPOSITION Or MF_REMOVE

        End If

    End If

   

    DrawMenuBar pobjForm.hwnd

   

End Sub

 

'-----------------------------------------------------------------------------

Public Sub LockWindow(hwnd As Long)

'-----------------------------------------------------------------------------

    LockWindowUpdate hwnd

End Sub

 

'-----------------------------------------------------------------------------

Public Sub UnlockWindow()

'-----------------------------------------------------------------------------

    LockWindowUpdate 0

End Sub

 

'-----------------------------------------------------------------------------

Public Sub MakeTopmost(pobjForm As Form, pblnMakeTopmost As Boolean)

'-----------------------------------------------------------------------------

 

    Dim lngParm As Long

   

    lngParm = IIf(pblnMakeTopmost, HWND_TOPMOST, HWND_NOTOPMOST)

   

    SetWindowPos pobjForm.hwnd, _

                 lngParm, _

                 0, _

                 0, _

                 0, _

                 0, _

                 (SWP_NOACTIVATE Or SWP_SHOWWINDOW Or _

                  SWP_NOMOVE Or SWP_NOSIZE)

 

End Sub

 

 

Click here to download a tester project that incorporates this module.