By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,461 Members | 2,184 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,461 IT Pros & Developers. It's quick & easy.

Combine a KeyPress event with a DblClick event

beacon
100+
P: 579
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...
Feb 7 '09 #1
Share this Question
Share on Google+
11 Replies


DonRayner
Expert 100+
P: 489
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.

Expand|Select|Wrap|Line Numbers
  1. Option Compare Database
  2. Public ctlPressed As Boolean
  3.  
  4. Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
  5. If KeyCode = 17 Then
  6.     ctlPressed = True
  7. Else
  8.     ctlPressed = False
  9. End If
  10. End Sub
  11.  
  12. Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
  13. ctlPressed = False
  14. End Sub
  15.  
  16. Private Sub Text0_DblClick(Cancel As Integer)
  17. If ctlPressed = True Then
  18.     Me.Text0 = "CNTL Button Down"
  19. Else
  20.     Me.Text0 = "CNTL Button Up"
  21. End If
  22. End Sub
Feb 7 '09 #2

100+
P: 675
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.

Expand|Select|Wrap|Line Numbers
  1. Dim iShift as Integer
  2.  
  3. Private Sub txtYourField_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
  4.     iShift = Shift
  5. End Sub
  6.  
  7. Private Sub txtYourField_DblClick(Cancel As Integer)
  8.     Debug.Print "iShift=" & iShift
  9. End Sub
  10.  
  11.  
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
Feb 7 '09 #3

100+
P: 675
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.
Feb 7 '09 #4

beacon
100+
P: 579
@OldBirdman
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.
Feb 8 '09 #5

NeoPa
Expert Mod 15k+
P: 31,398
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.
Feb 8 '09 #6

100+
P: 675
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:
Expand|Select|Wrap|Line Numbers
  1. Private Sub txtYourField_DblClick(Cancel As Integer) 
  2. 'Uses iShift as a value to test for Cntl only pressed, or for no shift key pressed
  3.     If iShift = 0 Then
  4.         txtYourField= strDefault1
  5.     Else If iShift = acCtrlMask Then
  6.         'Cntl is down, other shift keys are up
  7.         txtYourField= strDefault2
  8.     End If
  9. End Sub 
  10.  
If when the Cntl key is down and other shift keys are also permitted to be down, then the test might be:
Expand|Select|Wrap|Line Numbers
  1. Private Sub txtYourField_DblClick(Cancel As Integer) 
  2. 'Uses iShift against a mask to test for Cntl pressed, or for no shift key pressed
  3.     If iShift = 0 Then
  4.         txtYourField= strDefault1
  5.     Else If iShift And acCtrlMask < 0 Then
  6.         'Cntl is down, other shift keys may be down
  7.         txtYourField= strDefault2
  8.     End If
  9. End Sub 
  10.  
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.
Feb 10 '09 #7

NeoPa
Expert Mod 15k+
P: 31,398
@OldBirdman
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.
@OldBirdman
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 :
Expand|Select|Wrap|Line Numbers
  1. If iShift Then
Feb 11 '09 #8

100+
P: 675
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:
Expand|Select|Wrap|Line Numbers
  1. Private Sub txtYourField_KeyDown(KeyCode As Integer, Shift As Integer)
  2.     Debug.Print "KeyDown-" & Shift
  3. End Sub
  4. Private Sub txtYourField_KeyUp(KeyCode As Integer, Shift As Integer)
  5.     Debug.Print "KeyUp-" & Shift
  6. End Sub
  7.  
When my test is Cntl down, then Alt down, then Cntl up, then Alt up, I get:
Expand|Select|Wrap|Line Numbers
  1. KeyDown-2
  2. KeyDown-2
  3. . . .
  4. KeyDown-2
  5. KeyDown-6
  6. . . .
  7. KeyDown-6
  8. KeyUp-6
  9. KeyDown-4
  10. . . .
  11. KeyDown-4
  12. KeyUp-4
  13.  
But if I only "Tap" the Alt key, I get the following:
Expand|Select|Wrap|Line Numbers
  1. KeyDown-2
  2. . . .
  3. KeyDown-2
  4. KeyDown-6
  5. KeyUp-6
  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:
Expand|Select|Wrap|Line Numbers
  1. KeyUp-6
  2.  
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?
Feb 11 '09 #9

NeoPa
Expert Mod 15k+
P: 31,398
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) :
Expand|Select|Wrap|Line Numbers
  1. Action    Display   Meaning
  2. Ctrl-Down KeyDown-2 Ctrl
  3. ...
  4. Ctrl-Down KeyDown-2 Ctrl
  5. Alt-Down  KeyDown-6 Ctrl & Alt
  6. Alt-Up    KeyUp-2   Ctrl
  7. Ctrl-Up   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?
Feb 12 '09 #10

100+
P: 675
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:
Expand|Select|Wrap|Line Numbers
  1. Private Sub txtYourField_KeyDown(KeyCode As Integer, Shift As Integer)
  2.     Debug.Print "KeyDown Shift=" & Shift
  3. End Sub
  4. Private Sub txtYourField_KeyUp(KeyCode As Integer, Shift As Integer)
  5.     Debug.Print "KeyUp   Shift=" & Shift
  6. End Sub
  7.  
Pressing but not holding down the Cntl Key 3 times produces as expected:
Expand|Select|Wrap|Line Numbers
  1. KeyDown Shift=2
  2. KeyUp   Shift=2
  3. KeyDown Shift=2
  4. KeyUp   Shift=2
  5. KeyDown Shift=2
  6. KeyUp   Shift=2
  7.  
But doing the same with the Alt Key produces:
Expand|Select|Wrap|Line Numbers
  1. KeyDown Shift=4
  2. KeyUp   Shift=4
  3. KeyUp   Shift=4
  4. KeyDown Shift=4
  5. KeyUp   Shift=4
  6.  
NeoPa - in your "...expect to see" illustration, when I run this, I do not get the expected. I get:
Expand|Select|Wrap|Line Numbers
  1. Action    Display   Meaning 
  2. Ctrl-Down KeyDown-2 Ctrl 
  3. ... 
  4. Ctrl-Down KeyDown-2 Ctrl 
  5. Alt-Down  KeyDown-6 Ctrl & Alt 
  6. ... 
  7. Alt-Down  KeyDown-6 Ctrl & Alt 
  8. Alt-Up    KeyUp-6 Ctrl & Alt 
  9. Ctrl-Up   KeyUp-6 Ctrl & Alt 
  10.  
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
Feb 12 '09 #11

NeoPa
Expert Mod 15k+
P: 31,398
@OldBirdman
Makes sense to me.
@OldBirdman
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.
Feb 12 '09 #12

Post your reply

Sign in to post your reply or Sign up for a free account.