Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations dencom on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Keypress event only works in debug. Help 6

Status
Not open for further replies.

wadey

Programmer
Jun 6, 2006
54
GB
this code only works when stepping through. Otherwise it allows me to type anything in the text box. why and how do i fix? :-

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)

If KeyCode < 46 Or KeyCode > 58 Then
KeyCode = 0
End If

End Sub
 
OK I am going to want to see the fix for this one. I too was able to replicate this. As long as there is a break in the code and you either run or step through after the break then it basically does what you want (no accept the keystroke) but at run time without a break it lets you type like normal.


MMMMMM


Andy Baldwin

"Testing is the most overlooked programming language on the books!"

Ask a great question, get a great answer. Ask a vague question, get a vague answer.
Find out how to get great answers FAQ219-2884.
 
Use the KeyPress Event
Code:
Private Sub Text1_KeyPress(KeyAscii As Integer)

    If KeyAscii < 46 Or KeyAscii > 58 Then    
        KeyAscii = 0
    End If

End Sub
that Event does work properly. I don't understand why "KeyUp" and "KeyDown" don't work because the documentation says they should.
 
>this code only works when stepping through

No, actually it doesn't ...
 
The original code did work for me when stepping through it.
Actually if you put a break on the Private Sub line and simply hit run when it stops it will work. Or if you step all the way through it, it will work. Not during run time.


Andy Baldwin

"Testing is the most overlooked programming language on the books!"

Ask a great question, get a great answer. Ask a vague question, get a vague answer.
Find out how to get great answers FAQ219-2884.
 
No, it doesn't. What you are seeing is a completely different effect caused by the message-based operation of Windows, and the switching of focus that arises when you hit a break point.

 
Oh, and also by the fact that the Keydown (and KeyUp) events cannot be used to eat keys this way (which is why golom has correctly suggested using the KeyPress event)
 
The intent of the original code seems to be to allow only numbers and a decimal point to be typed in the text box (plus a /, not sure if that's intentional!) But the original code assumes KeyCode contains ascii values, which it doesn't.

If you step through the original code, no characters show up in the text box, regardless of what you type. If you run it without a breakpoint, it displays whatever character you typed. So, neither way "works". My question is... why the opposite behavior?


 
Well, I've done a fair amount of research and experimentation now, and it looks to me also like altering the keycode has no effect on the value sent to the control. Microsoft appears to remain silent on this matter, so I'm going to opine that the ability in the KeyPress event to respecify the keystroke does not extend to the KeyUp and KeyDown events.

In some ways, that makes sense. KeyAscii from the KeyPress event maps to ASCII values. KeyCode from the KeyUp and KeyDown are intended to identify the keys that don't have an ASCII value associated with them as well as those that do, so many of them do not map to ASCII values. Furthermore, remapping only makes sense with ASCII values: for example there doesn't seem to be an ergonomically sensible scenario that would involve coercing an F1 keypress to an F6 one instead.

This demonstrates the difference between KeyPress and KeyUp very clearly: the ASCII value for the number 1 is 49, and if you press the number 1, you'll find the KeyPress's KeyAscii value dutifully set at 49. You'll also find KeyCode at 49 as well, but only if you press the number 1 on the keyboard. If you press the number 1 on the keypad, you will get the number 97. Obviously, if you want to respecify the underlying value, you aren't going to want to complicate the issue with different keycodes representing the same underlying ASCII value.

To further clarify this, if you go into the object browser, you can select KeyCodeConstants. If you peruse these, you will see that 49 is vbKey1 and 97 is vbKeyNumpad1.

So, use KeyPress to evaluate the value of the key pressed (respecifying if necessary), and use KeyUp (KeyDown is less typical; I would restrict its use to situations where holding down a key has some sort of effect such as in game scenarios) to evaluate what physical key has been pressed.

HTH

Bob
 
>Microsoft appears to remain silent on this matter

Well, the VB documentation explicitly states that the KeyAscii value can be modified in the KeyPress event, and explicitly does not say any such thing about the KeyCode for the KeyUp and KeyDown events, so that's pretty clear to me ..

Anyway, time for the longer explanation (this simplifies a few things BTW)

What we need to understand is that VB hides away much of the complexity of Windows by wrapping large chunks of the API in friendly commands and objects; for example the textbox is a VB wrapper for the edit control

But that has drawbacks to the VB programmer because on occassions it is difficult to see what is going on.

For this particular scenario we need to understand several factors:

Firstly, the whole process of converting a key press into a character is driven by three Windows messages: WM_KEYDOWN, WM_CHAR, and WM_KEYUP

WM_CHAR always follows WM_KEYDOWN, being a translation of the data provided by by the WM_KEYDOWN messages.

These three messages are are received by your VB application (well, a control in the app) and in turn raise the KeyDown, KeyPress, and KeyUp events which is what we get to see (and, as already stated, the MS people clearly decided that being able to modify KeyCode was not something they wanted to be available in VB, whilst altering KeyAscii was). But it is vitally important to realise that the Windows messages that drive the show - if a VB application/control doesn't receive a WM_CHAR for some reason event then you won't get a corresponding KeyPress event.

So, we know that modifying the KeyCode has no real effect. Why then does it appear to do so when we set a break point. More to the point why does it now appear to eat every keystroke?

Well becaue the moment you press a key you generate WM_KEYDOWN. This in turn raises the KeyDown event which, because of the break point, switches focus to the IDE's window. Now the WM_CHAR and WM_KEYUP messages are delivered to that window instead of to the VB application/control originally intended. Without the WM_CHAR event the edit control never gets told what ASCII character to enter at the insertion point, so the effect is that the key press is eaten - not by the KeyPress event, but by the IDE

You can see this for yourself with a simple bit of code, and a form with a textbox:

Option Explicit

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)
Debug.Print "key down"
End Sub

Private Sub Text1_KeyPress(KeyAscii As Integer)
Debug.Print "key press"
End Sub

Private Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer)
Debug.Print "key up"
End Sub


Run this without a breakpoint, and you will see "key down", "key press", and "key up" printed in the immediate window.

Now put a breakpoint on

Debug.Print "key down"

And run the code again. Now you'll only see "key down" in the immediate window
 
Where I say

... not by the KeyPress event, but by the IDE

I of course meant

... not by the KeyDown event, but by the IDE
 
A masterly explanation strongm - Thank you!

________________________________________________________________
If you want to get the best response to a question, please check out FAQ222-2244 first.
'If we're supposed to work in Hex, why have we only got A fingers?'
Drive a Steam Roller
 
Strongm, it's not clear to me that we are taking opposing positions regarding what the Microsoft documentation says on this matter, as you appear to suggest. I submit that to "explicitly not say" something is equivalent to "remaining silent" on the matter in question.

Furthermore, if it were not "pretty clear" to me as well, I wouldn't have opined on the subject! I might add that I'm grateful to you for helping me develop that habit. :)

Thank you as always for explaining what goes on under the hood, and making obscure matters clear. Have another star from me.

Bob

 
Great stuff strongm! This goes in my archive for future reference.

Tracy Dryden

Meddle not in the affairs of dragons,
For you are crunchy, and good with mustard. [dragon]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top