Practical Examples: Working with Objects
![]() | Most applications use objects throughout. The example that follows applies the technique you learned to enable and disable command buttons in response to the user making changes to the data on the frmClients form, located in Chap8Ex.mdb on the sample code CD-ROM. |
Enabling and Disabling Command Buttons
When a user is in the middle of modifying form data, there's really no need for her to use other parts of the application. It makes sense to disable other features until the user has opted to save the changes to the Client data. The clean form begins with the View Projects command button enabled and the Save and Cancel buttons disabled. The KeyPreview property of the form is set to Yes so that the form previews all keystrokes before the individual controls process them. In the example, the KeyDown event of the form is used to respond to the user "dirtying" the form. It executes whenever the user types ANSI characters while the form has the focus. The KeyDown event of the form (discussed in detail in Chapter 9, "Advanced Form Techniques") looks like this:Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
'If the Save command button is not already enabled
If Not cmdSave.Enabled Then
'If a relevant key was pressed
If ImportantKey(KeyCode, Shift) Then
'Flip the command buttons on the form,
'setting focus to the active control
Call FlipEnabled(Me, Screen.ActiveControl)
'Disable the cboSelectClient combo box
Me.cboSelectClient.Enabled = False
End If
'If the Save button is already enabled (form is dirty)
'ignore the PageUp and PageDown keys
Else
If KeyCode = vbKeyPageDown Or _
KeyCode = vbKeyPageUp Then
KeyCode = 0
End If
End If
End Sub
The KeyDown event automatically receives the code of the key that was pressed, whether Shift, Alt, or Ctrl was pressed along with that key. The event routine checks to determine whether the Save button is already enabled. If it is, there's no reason to continue; the Enabled property of the command buttons has already been flipped. If Save isn't already enabled, the ImportantKey function (discussed in detail later) is called. It receives the key that was pressed, despite whether Shift, Alt, or Control was used.The ImportantKey evaluates the key that was pressed to determine whether a keystroke is modifying the data. If it is, the function returns True. Otherwise, it returns False. If ImportantKey returns True, the FlipEnabled routine is executed. FlipEnabled flips the enabled property of the command buttons on the form so that Save and Cancel are enabled, and View Projects is disabled.If the value returned from the ImportantKey function is True, the enabled property cboSelectClient combo is set to False. If you fail to prevent movement to other records while the form is dirty, users' changes are automatically saved (by Access) when the user navigates to another record. Furthermore, the enabled state of the command buttons still reflects a dirty state of the form.Finally, if Save is already enabled, you know that the form is in a dirty state. If that is the case, it is not appropriate for the user to be able to move to another record using the PageUp and PageDown keys. If the cmdSave command button is enabled, and the key pressed is PageUp or PageDown, the keystroke is ignored.Now that you understand the role of the KeyDown event of the form, take a look at the functions that underlie its functionality. The ImportantKey function looks like this:Function ImportantKey(KeyCode, Shift)
'Set return value to false
ImportantKey = False
'If Alt key was pressed, exit function
If Shift = acAltMask Then
Exit Function
End If
'If Delete, Backspace, or a typeable character was pressed
If KeyCode = vbKeyDelete Or KeyCode = vbKeyBack Or (KeyCode > 31 _
And KeyCode < 256) Then
'If the typeable character was NOT a right, left, up,
'or down arrow, page up, or page down, return True
If KeyCode = vbKeyRight Or KeyCode = vbKeyLeft Or _
KeyCode = vbKeyUp Or KeyCode = vbKeyDown Or _
KeyCode = vbKeyPageUp Or KeyCode = vbKeyPageDown Then
Else
ImportantKey = True
End If
End If
End Function
This generic function, found in basUtils, sets its default return value to False. It tests to see whether the user pressed the Alt key. If so, the user was accessing a menu or accelerator key, which means that there's no reason to flip the command buttons. The function is exited. If the user didn't press the Alt key, the key that was pressed is evaluated. If the Delete key, Backspace key, or any key with an ANSI value between 31 and 256 was pressed (excluding the left, right, up, and down arrow keys, and Page Up or Page Down), True is returned from this function. The Keydown event of the form then calls the FlipEnabled routine. It looks like this:Sub FlipEnabled(frmAny As Form, ctlAny As Control)
'Declare a control object variable
Dim ctl As Control
'If the type of control received as a parameter
'is a command button, enable it and set focus to it
ctlAny.Enabled = True
ctlAny.SetFocus
'Loop through each control in the controls collection
'of the form that was received as a parameter
For Each ctl In frmAny.Controls
'If the type of the control is a command button
'and the name of the control does not match the
'name of the control received as a parameter
'flip the enabled property of the control
If ctl.ControlType = acCommandButton Then
If ctl.Name <> ctlAny.Name Then
ctl.Enabled = Not ctl.Enabled
End If
End If
Next ctl
End Sub
This generic routine, also found in basUtils, flips the Enabled property of every command button in the form, except the one that was passed to the routine as the second parameter. The FlipEnabled routine receives a form and a control as parameters. It begins by creating a control object variable; then it enables the control that was passed as a parameter and sets focus to it. The routine then loops through every control on the form that was passed to it. It tests to see whether each control is a command button. If it finds a command button, and the name of the command button isn't the same as the name of the control that was passed to it, it flips the Enabled property of the command button. The idea is this: When the user clicks Save, you can't immediately disable the Save button because it still has focus. You must first enable a selected control (the one that was passed to the routine) and set focus to the enabled control. After the control is enabled, you don't want to disable it again, so you need to eliminate it from the processing loop.Remember that as long as the cmdSave command button is enabled, the PageUp and PageDown keys are ignored. This is an important step because it is imperative that the user not be able to move from record to record while editing the form data.You need a way to flip the command buttons back the other way when editing is complete. The Click event of the Save button contains the following code:Private Sub cmdSave_Click()
'Save changes to the client record
DoCmd.RunCommand acCmdSaveRecord
'Enable client selection combo
Me.cboSelectClient.Enabled = True
'Call routine to disable save and cancel and
'enable view projects
Call FlipEnabled(Me, Me.cboSelectClient)
End Sub
This code saves the current record and enables the cboSelectClient control. It then calls the FlipEnabled routine, passing a reference to the cboSelectClient control as a parameter. The FlipEnabled routine flips the command buttons back to their original state.The form contains a cancel command button with a similar routine. It looks like this:Private Sub cmdUndo_Click()
'Undo changes
DoCmd.RunCommand acCmdUndo
'Enable client selection combo
Me.cboSelectClient.Enabled = True
'Call routine to disable save and cancel and
'enable view projects
Call FlipEnabled(Me, Me.cboSelectClient)
End Sub
This code undoes changes to the current record. It enables the cboSelectClient control and calls the FlipEnabled routine to once again disable Save and Cancel and enable View Projects.