Combine a KeyPress event with a DblClick event

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • beacon
    Contributor
    • Aug 2007
    • 579

    Combine a KeyPress event with a DblClick event

    Hi everybody,

    I have a double click event for a text box that will put a default value in it when fired.

    I'd like to be able to press 'Ctrl' + double click to put in a different value.

    I know there are others ways of accomplishing this, but it was suggested by one of my keyboard junkie coworkers and I thought I check to see if it was possible because my efforts have failed (I don't know enough about either event I suppose)

    Thanks...
  • DonRayner
    Recognized Expert Contributor
    • Sep 2008
    • 489

    #2
    This should help you out. Just replace the control names with whatever the control names are on your form. You will also have to set the Key Preview property of the form to Yes.

    Code:
    Option Compare Database
    Public ctlPressed As Boolean
    
    Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    If KeyCode = 17 Then
        ctlPressed = True
    Else
        ctlPressed = False
    End If
    End Sub
    
    Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
    ctlPressed = False
    End Sub
    
    Private Sub Text0_DblClick(Cancel As Integer)
    If ctlPressed = True Then
        Me.Text0 = "CNTL Button Down"
    Else
        Me.Text0 = "CNTL Button Up"
    End If
    End Sub

    Comment

    • OldBirdman
      Contributor
      • Mar 2007
      • 675

      #3
      Save the shift status from the MouseDown and apply it in the DblClick event procedure. Of course, replace Debug.Print with If . . . Then or Select Case iShift . . . End Select.

      Code:
      Dim iShift as Integer
      
      Private Sub txtYourField_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
          iShift = Shift
      End Sub
      
      Private Sub txtYourField_DblClick(Cancel As Integer)
          Debug.Print "iShift=" & iShift
      End Sub
      Shift values are:
      iShift=0 - No button down
      iShift=1 - Shift key down
      iShift=2 - Cntl key down
      iShift=4 - Alt key down
      iShift=3 - 1 + 2 = Shift & Cntl
      iShift=5 - 1 + 4 = Shift & Alt
      iShift=6 - 2 + 4 = Cntl & Alt
      iShift=7 - 1 + 2 + 4 = Shift & Cntl & Alt

      OldBirdman

      Comment

      • OldBirdman
        Contributor
        • Mar 2007
        • 675

        #4
        An afterthought - you could double-click a second time. The DblClick event would check the current value, and if the 1st default, change it to the 2nd default value. Wouldn't have to put down the coffee then.

        Comment

        • beacon
          Contributor
          • Aug 2007
          • 579

          #5
          Originally posted by OldBirdman
          An afterthought - you could double-click a second time. The DblClick event would check the current value, and if the 1st default, change it to the 2nd default value. Wouldn't have to put down the coffee then.
          Hi OB,

          It's funny you suggested the putting down the coffee because I ended up doing what you suggested after I couldn't get Don's suggestion to work.

          Good call with the iShift method too...it worked really well.

          Comment

          • NeoPa
            Recognized Expert Moderator MVP
            • Oct 2006
            • 32653

            #6
            I recommend you have a look at the KeyDown and KeyUp events (in the Help system).

            The parameter you're interested in is the Shift (2nd) parameter. This is essentially a bit-flag field with bits mapped for Ctrl, Alt & Shift. There are constants defined for each (acCtrlMask, acAltMask & acShiftMask) to make it easier to deal with. Remember, this always reflects the current status (of all three shift-type keys) - rather than merely the last one pressed. Thus any or all can be shown as down at any time.

            NB. For both events, the object with the focus receives all keystrokes. A form can have the focus only if it has no controls, or all its visible controls are disabled.

            This is very similar to the approach used in OB's code, however as it uses the Shift parameter from the keyboard event, rather than the mouse, it enables you to use the DblClick event more easily.

            Comment

            • OldBirdman
              Contributor
              • Mar 2007
              • 675

              #7
              OK - I'm confused. The MouseDown event will occur only once, on the first click of the DblClick . The KeyDown event should occur repeatedly from the time a key is pressed until all keys are released. KeyUp occurs whenever any key is released even if other keys remain down, in which case KeyDown resumes.
              As the masks for MouseDown and KeyDown are identical, why would I want an event procedure to run many times, perhaps thousands of times, when once is enough?

              I did not mention using the Shift value as a mask. Each is valid, depending on how the information is to be used. If the problem is to identify that only the Cntl key is down during a DblClick, then the code might be:
              Code:
              Private Sub txtYourField_DblClick(Cancel As Integer) 
              'Uses iShift as a value to test for Cntl only pressed, or for no shift key pressed
                  If iShift = 0 Then
                      txtYourField= strDefault1
                  Else If iShift = acCtrlMask Then
                      'Cntl is down, other shift keys are up
                      txtYourField= strDefault2
                  End If
              End Sub
              If when the Cntl key is down and other shift keys are also permitted to be down, then the test might be:
              Code:
              Private Sub txtYourField_DblClick(Cancel As Integer) 
              'Uses iShift against a mask to test for Cntl pressed, or for no shift key pressed
                  If iShift = 0 Then
                      txtYourField= strDefault1
                  Else If iShift And acCtrlMask < 0 Then
                      'Cntl is down, other shift keys may be down
                      txtYourField= strDefault2
                  End If
              End Sub
              As the stated problem is: DblClick with no shift keys inserts the DefaultValue and DblClick with the Cntl pressed inserts the AltDefaultValue , I felt testing the value to be clearer and more straightforward .

              Comment

              • NeoPa
                Recognized Expert Moderator MVP
                • Oct 2006
                • 32653

                #8
                Originally posted by OldBirdman
                OK - I'm confused. The MouseDown event will occur only once, on the first click of the DblClick . The KeyDown event should occur repeatedly from the time a key is pressed until all keys are released. KeyUp occurs whenever any key is released even if other keys remain down, in which case KeyDown resumes.
                While the overhead of managing the state of the shift state via the keys instead of the mouse is entirely negligible, it is nevertheless, as you say, cleaner to use the MouseDown event. A further benefit is that because you can always assume that a MouseDown will ALWAYS occur prior to a DoubleClick event, there is no need to manage (reset) the shift state in the MouseUp event.

                I misunderstood your code when I read it. I'm happy now to recommend the technique you proposed ahead of the one I proposed. If I were to do it myself now, that's what I'd use.
                Originally posted by OldBirdman
                I did not mention using the Shift value as a mask. Each is valid, depending on how the information is to be used.
                Actually, nor did I.

                I was simply explaining the situation for better and clearer understanding. Testing the Shift value against the value 1 (acCtrlMask) is perfectly valid. So is saving the value of (Shift And acCtrlMask) into iShift, to be tested later simply as :
                Code:
                If iShift Then

                Comment

                • OldBirdman
                  Contributor
                  • Mar 2007
                  • 675

                  #9
                  Thank You, NeoPa.
                  I didn't want to mention it when defending my argument, but I think that the keyboard method will fail under some conditions.
                  Using the code:
                  Code:
                  Private Sub txtYourField_KeyDown(KeyCode As Integer, Shift As Integer)
                      Debug.Print "KeyDown-" & Shift
                  End Sub
                  Private Sub txtYourField_KeyUp(KeyCode As Integer, Shift As Integer)
                      Debug.Print "KeyUp-" & Shift
                  End Sub
                  When my test is Cntl down, then Alt down, then Cntl up, then Alt up, I get:
                  Code:
                  KeyDown-2
                  KeyDown-2
                  . . .
                  KeyDown-2
                  KeyDown-6
                  . . .
                  KeyDown-6
                  KeyUp-6
                  KeyDown-4
                  . . .
                  KeyDown-4
                  KeyUp-4
                  But if I only "Tap" the Alt key, I get the following:
                  Code:
                  KeyDown-2
                  . . .
                  KeyDown-2
                  KeyDown-6
                  KeyUp-6
                  At this point, the KeyDown event is apparently not firing, and my Debug.Print stops showing the KeyDown value of Shift. But I still have the Cntl key pressed.
                  Finally, releasing the Cntl key gives me:
                  Code:
                  KeyUp-6
                  1)This should be KeyUp-2, NOT KeyUp-6 as the only key down is Cntl.
                  2)KeyDown should continue with KeyDown-2
                  The same occurs on both my machines, Windows XP, SP-3, one with Access 2000, the other 2003.
                  Any idea what's happening?

                  Comment

                  • NeoPa
                    Recognized Expert Moderator MVP
                    • Oct 2006
                    • 32653

                    #10
                    Certainly, the keyboard hardware only fires repetitions for one (the last pressed) key at a time. You can use this to your advantage if ever you're short of space and have to store something bulky on your keyboard. You'll notice that after a short while, the PC starts to beep at you continually. Not good, especially if you don't want to remove the bulky object at this time. Using the knowledge above however, you can simply press and release a single available key. The noise will stop, even though the bulky object is still resting on the keyboard.

                    With your KeyDown code, it does sound like you may have found a problem with Access' internal handling (or the driver it uses). If I understand the sequence you're handling correctly, it is as follows :
                    Ctrl-Down, Alt-Down, Alt-Up, Ctrl-Up.
                    What I would expect to see here is (Assuming the tap of the Alt key ensures only 1 KeyDown event for it) :
                    Code:
                    Action    Display   Meaning
                    [B]Ctrl-Down[/B] KeyDown-2 Ctrl
                    ...
                    [B]Ctrl-Down[/B] KeyDown-2 Ctrl
                    [B]Alt-Down[/B]  KeyDown-6 Ctrl & Alt
                    [B]Alt-Up[/B]    KeyUp-2   Ctrl
                    [B]Ctrl-Up[/B]   KeyUp-0   None
                    NB. No interrupts or events fire between lines #6 & #7.

                    PS. I would doubt this behaviour is limited to the KeyDown/KeyUp events (as the Shift value is managed internally and, presumably, referenced by both sets of events). Have you determined if this is evident in the MouseDown events also?

                    Comment

                    • OldBirdman
                      Contributor
                      • Mar 2007
                      • 675

                      #11
                      The more I test & try to understand, the more problems I find here. I'm not going to debug MS Code, so I am doing no further testing. Saving the Shift Value at the first MouseDown of the DblClick seems to work correctly under all conditions. Original question solved!
                      The KeyDown Event fires repeatedly whenever any key(s) are pressed, not restricted to shift keys. If multiple keys are pressed, this is reflected in the shift key where a mask is available, but the other keys are identified by their ASCII code, and only the last key is available to the KeyDown function through the argument list.
                      The KeyDown Event quits whenever the last key pressed is released, regardless of whether another key is still down. Consistant=Yes, Logical=???.
                      The MouseDown Event behaves like the KeyPress Event, not like KeyDown, and only fires once. I only have a 2-button mouse, and although Help says I can use the supplied constants as masks, the argument=Button only has a 1 or a 2, never a 3, even though both buttons may be down.
                      Using this code:
                      Code:
                      Private Sub txtYourField_KeyDown(KeyCode As Integer, Shift As Integer)
                          Debug.Print "KeyDown Shift=" & Shift
                      End Sub
                      Private Sub txtYourField_KeyUp(KeyCode As Integer, Shift As Integer)
                          Debug.Print "KeyUp   Shift=" & Shift
                      End Sub
                      Pressing but not holding down the Cntl Key 3 times produces as expected:
                      Code:
                      KeyDown Shift=2
                      KeyUp   Shift=2
                      KeyDown Shift=2
                      KeyUp   Shift=2
                      KeyDown Shift=2
                      KeyUp   Shift=2
                      But doing the same with the Alt Key produces:
                      Code:
                      KeyDown Shift=4
                      KeyUp   Shift=4
                      KeyUp   Shift=4
                      KeyDown Shift=4
                      KeyUp   Shift=4
                      NeoPa - in your "...expect to see" illustration, when I run this, I do not get the expected. I get:
                      Code:
                      Action    Display   Meaning 
                      Ctrl-Down KeyDown-2 Ctrl 
                      ... 
                      Ctrl-Down KeyDown-2 Ctrl 
                      Alt-Down  KeyDown-6 Ctrl & Alt 
                      ... 
                      Alt-Down  KeyDown-6 Ctrl & Alt 
                      Alt-Up    KeyUp-6 Ctrl & Alt 
                      Ctrl-Up   KeyUp-6 Ctrl & Alt
                      I think that there are some strange things here, but normally we don't care when a shift-key is pressed, but which shift-keys are down when another event occurs. At that time we can test the status of the shift-keys. To hazzard a guess as to the cause, I think the repeat function of the keys keeps firing as long as keys are down, and doesn't check the status of the keyboard. When a key is pressed, the value of shift is updated. When a key is released, it is assumed that the value of shift is the value of the key released, but if only one of many keys is released, shift is now in error. This is fixed when either mousedown or keydown occur. Why the Cntl Key acts differently than the the other two shift keys is unknown. I suspect it is the multiple use of Cntl, which can act as a "cursor locator". However, turning off this feature had no effect.

                      OldBirdman

                      Comment

                      • NeoPa
                        Recognized Expert Moderator MVP
                        • Oct 2006
                        • 32653

                        #12
                        Originally posted by OldBirdman
                        The more I test & try to understand, the more problems I find here. I'm not going to debug MS Code, so I am doing no further testing.
                        Makes sense to me.
                        Originally posted by OldBirdman
                        Using this code:
                        Code:
                        Private Sub txtYourField_KeyDown(KeyCode As Integer, Shift As Integer)
                            Debug.Print "KeyDown Shift=" & Shift
                        End Sub
                        Private Sub txtYourField_KeyUp(KeyCode As Integer, Shift As Integer)
                            Debug.Print "KeyUp   Shift=" & Shift
                        End Sub
                        Pressing but not holding down the Cntl Key 3 times produces as expected:
                        Code:
                        KeyDown Shift=2
                        KeyUp   Shift=2
                        KeyDown Shift=2
                        KeyUp   Shift=2
                        KeyDown Shift=2
                        KeyUp   Shift=2
                        Strange. I would expect that the Shift value would be updated to reflect the KeyUp before the event fired to your code. Clearly this is not the case :S

                        It certainly seems that using the MouseDown option is the better way to code it.

                        Comment

                        Working...