Gustav Brock
Gustav at cactus.dk
Mon Jul 16 10:41:59 CDT 2007
Hi John Interesting. I should have tested more carefully, sorry. But since when has a keypress raised an OnClick event? I don't see the relation between these two events. It must be a special case for the checkbox control. But that being so, couldn't you just eat the keypress and skip all the flag stuff? Like: Private Sub mchk_KeyPress(KeyAscii As Integer) KeyAscii = 0 End Sub But no. This eats +/- and the hotkey but not the spacebar. Go figure. /gustav >>> jwcolby at colbyconsulting.com 16-07-2007 16:58 >>> 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