[AccessD] Checkbox dates

jwcolby jwcolby at colbyconsulting.com
Mon Jul 16 09:58:51 CDT 2007


These methods do not fire the click event?  When I test the + and - keys the
click event fires.  Likewise when pressing the space bar.  This is the
behavior I expect to happen since these keys emulate a mouse click.

So my code works for those three keyboard events.  The toggle works as you
expect, it toggles the control.  MY code also toggles the control using the
- and the + whereas yours (hopefully) clears for the - and sets for the +.

Unfortunately, making matters worse, BOTH the keypress and the click events
happen.  The keypress happens first, then the click event happens.  So if I
"set" the date field in the keypress, then the click event comes along and
sees the value set and clears it.  If the keypress event clears the event,
the click event comes along and sets it.  This makes it APPEAR that the
keystroke - plus or minus - is doing the OPPOSITE of what it is supposed to
do, when in fact it is doing exactly what it is supposed to do.

In order to get around this unfortunate "helping hand", I added a flag to
track that a KeyPressed occurred (set in KeyPress) and if so do NOT execute
the OnClick code (flag always cleared in OnClick).

Thus the code morphs to:

'**********************************************
Option Compare Database
Option Explicit
'
'This class uses a check box to set / void a date in a record
'The objective is to allow the form to set a date to date() if a check box
is checked
'and set that date to void if the check box is cleared.
'
'Likewise the checkbox should DISPLAY a TRUE if the date is NOT VOID
'and should display a FALSE if the date is VOID
'
'The class functions by passing in an UNBOUND check box which is the visual
indicator
'A BOUND text box is passed in which actually stores the state of the flag
as a date data type
'
'Thus as the user clicks the check box, this class sets the underlying (and
invisible) text box
'The text box VALUE property is set to DATE if the check box displays a TRUE
(is checked)
'and the textbox VALUE property is set to NULL if the checkbox displays a
FALSE (is not checked)
'
Private WithEvents mchk As CheckBox
Private mtxt As TextBox
Private Const cstrEventProc As String = "[Event Procedure]"
Private mblnKeyPressed As Boolean

Private Sub Class_Terminate()
    Set mchk = Nothing
    Set mtxt = Nothing
End Sub

Function init(lchk As CheckBox, ltxt As TextBox)
    Set mchk = lchk
    mchk.OnClick = cstrEventProc
    mchk.OnKeyPress = cstrEventProc
    Set mtxt = ltxt
    SetChkState
End Function
'
'This function causes the text box to track the visual state of the control
'If the user clicks the check box and the check box ends up TRUE then set
the text box to Date()
'else set the text box to VOID
'
Private Sub mchk_Click()
On Error GoTo Err_mchk_Click
    '
    'KeyPressed occurs first (if it happens) so short circuit the click
event handler if KeyPressed
    '
    If Not mblnKeyPressed Then
        If IsNull(mtxt.Value) Then
            mtxt.Value = Date
        Else
            mtxt.Value = Null
        End If
        SetChkState
    End If
    mblnKeyPressed = False
Exit_mchk_Click:
Exit Sub
Err_mchk_Click:
    Select Case Err
    Case 0      '.insert Errors you wish to ignore here
        Resume Next
    Case Else   '.All other errors will trap
        Beep
        MsgBox Err.Description, , "Error in Sub clsctlChk2Date.mchk_Click"
        Resume Exit_mchk_Click
    End Select
    Resume 0    '.FOR TROUBLESHOOTING
End Sub
'
'This sub causes the visual state of the checkbox to track the text box
'If the text box is VOID (no date) then display a FALSE
'else display a TRUE
'
Public Sub SetChkState()
On Error GoTo Err_SetChkState
    If IsNull(mtxt.Value) Then
        mchk.Value = False
    Else
        mchk.Value = True
    End If
Exit_SetChkState:
Exit Sub
Err_SetChkState:
    Select Case Err
    Case 0      '.insert Errors you wish to ignore here
        Resume Next
    Case Else   '.All other errors will trap
        Beep
        MsgBox Err.Description, , "Error in Sub clsctlChk2Date.SetChkState"
        Resume Exit_SetChkState
    End Select
    Resume 0    '.FOR TROUBLESHOOTING
End Sub

Private Sub mchk_KeyPress(KeyAscii As Integer)
Dim bytKeyAscii As Byte
    bytKeyAscii = CByte(KeyAscii)
    Select Case Chr(bytKeyAscii)
    Case "+"
        If IsNull(mtxt.Value) Then
            mtxt.Value = Date
        End If
        mblnKeyPressed = True
    Case "-"
        If Not IsNull(mtxt.Value) Then
            mtxt.Value = Null
        End If
        mblnKeyPressed = True
    Case Else
    End Select
    SetChkState
End Sub 
'**********************************************

Notice in particular the new blnKeyPressed flag in the header, the code to
SET the flag in mchk_KeyPress ONLY in the case of the + or -, and the code
in mchk_Click to not execute the normal click code if the blnKeyPressed flag
is set, and always clearing the flag.

By my testing this now correctly handles the keyboard issues raised by
Gustav.

John W. Colby
Colby Consulting
www.ColbyConsulting.com 
-----Original Message-----
From: accessd-bounces at databaseadvisors.com
[mailto:accessd-bounces at databaseadvisors.com] On Behalf Of Gustav Brock
Sent: Monday, July 16, 2007 5:06 AM
To: accessd at databaseadvisors.com
Subject: Re: [AccessD] Checkbox dates

Hi John et al

Sorry to disturb the romance, but you all seem to forget that a Checkbox can
be set/reset by pressing +/- and toggled by pressing the spacebar.
Also, pressing a hotkey combo (Alt + a letter of the associated label) will
toggle the Checkbox.

I once expanded these keypress options a bit with a subfunction you may call
at the OnKeyPress event:

Private Sub chkSomeCheckbox_KeyPress(KeyAscii As Integer)

  Call CheckboxKeyPress(Me!chkSomeCheckbox, KeyAscii)
 
End Sub


Sub CheckboxKeyPress(ByRef chk As CheckBox, ByVal bytKeyAscii As Byte)

' Add more key entries than the standard (+, -, and Space) ' to set/reset or
toggle the checkbox.
'
' 1998-10-08. Cactus Data ApS

  Dim booCheck As Boolean
  
  Select Case UCase(Chr(bytKeyAscii))
    ' List of key entries for set (True).
    Case "1", "Y", "T", "S", "J"
      booCheck = True
    ' List of key entries for reset (False).
    Case "0", "N", "F", "R"
      booCheck = False
    ' List of key entries for toggle.
    Case "*", "X", "C"
      booCheck = Not chk.value
    Case Else
      ' No change.
      booCheck = chk.value
  End Select
  
  ' Only change state if needed.
  If chk.value Xor booCheck Then
    chk.value = booCheck
  End If
  
End Sub

This - or at least the default OnKeyPress behaviour - could easily be
incorporated in the class.

/gustav





More information about the AccessD mailing list