KeyDown/KeyPress/KeyUp wishes
This has really anoyed me for a very long time with .net and it really really really needs to be fixed.
In VB6 on the Keydown/keypress and keyup events we could override the key that came in. As a result we could do things like all caps what the user was typing very easily even in controls that didn't have that property, simply by using one line of code to convert it to upper case.
We could also handle key events and if we didn't like the input, set the keypress to 0 so that it didn't do anything, or if we wanted to handle it, but not have it propogate down the chain.
The reason why this one is highly important is that (2 reasons):
1. Creating custom controls that only allow certain inputs. Right now you have to handle the KeyPreview event and figure out the crap right from the windows message call. This isn't good because you're messing with windows message calls, and when Mono if finally finished this just isn't going to work under Linux, and second, it is a VERY CRAPPY way of doing things.
2. Say you have a text box on a form with a search button beside it. On the key press event you put code to handle the enter key so that if the user hits the enter key it fires the button's click event. The problem right now is two fold: 1. The stupid beep will happen because you can't intercept and kill the enter key. 2. If there is another button that has the default focus on the form at the time simply because the user clicked that button before, it will also get the enter key and click itself causing all kinds of havoc.
The e.Handled = true; doesn't do squat to deal with any of these. (and I love the documentation on it, which basically says NOTHING.)
What should happen is two fold:
1. The KeyChar, KeyData etc. should be writable too. Maybe just in the KeyDown event but they should be writable. If this isn't feesible, then there should be a fully .net-like "KeyPreview" event that fires that is cancelable, and the key should be editable.
2. There should be an e.Cancel = true on the KeyDown event so that you can override that the key ever hapened.
This is #30 on my list of things that despirately need to be fixed.
Thanks!
I've fought with this one a few times, never with any success. I really miss this feature in VB6, as well. I keep thinking there MUST be a sanctioned way to override the keystroke coming into the event, but I haven't found it either. I'm hoping someone will see this and present an easy alternative that we've just missed.
well for your problem with not easily being able to say make all the characters entered uppercase, look at the CharacterCasing Property.
1. What about this doesn't work? If I don't want the user to ever enter an "a", then write a few lines in the KeyPress Event and you're done.
Private Sub MyTextBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyTextBox.KeyPress
If e.KeyChar = "a"c Then
e.Handled = True
End If
End Sub
What about # 1 am I not understanding?
2. For the part about having the AcceptButton getting fired also when you hit enter, I wouldn't say that's a mistake. That's up to your design. If you have an AcceptButton setup, then that's what it's going to do anytime Enter is hit. If you don't want it to do that, then don't set one up. Or, you could possibly just change it to not have one when that particular field gets focus and reset it back up when the field loses focus.
As for the other part of # 2 about the Enter key making a ding sound, I definitely agree with you!
Erik:
I used to do demos for VB6 classes where I'd have a text box and as they typed a phone number like 1800MSWISH1, I'd convert the characters to the corresponding numbers. That is, intercept the keystrokes, and enter 18006794741 into the textbox. This really showed off the power of reacting to the KeyPress event. Can't do this sort of thing anymore. I'm sure there's a security reason for it (can't have code modifying user's keystrokes!) but I miss it!
That's what I'm looking for. The old capability of completely replacing user's keystrokes. Sure, you can disregard keystrokes, but you can't easily REPLACE them, unless I'm missing something.
Ken, it's true, that capability isn't there (sounds pretty neato from VB6, never used it myself), but it seems it's still pretty easy to do. I just tried this example, which takes if you enter a, b, c, d, or e, it will replace what you type with e, d, c, b, a (respectively)
Private Letters() As Char = New Char() {"a"c, "b"c, "c"c, "d"c, "e"c}
Private LettersBackwards() As Char = New Char() {"e"c, "d"c, "c"c, "b"c, "a"c}
Private Sub MyTextBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyTextBox.KeyPress
Dim Index As Int16 = Array.IndexOf(Letters, e.KeyChar)
If Index <> -1 Then
e.Handled = True
MyTextBox.AppendText(LettersBackwards(Index))
End If
End Sub
Isn't that what you're looking for?
The problem is that e.Handled = true doesn't work on any of the controls other than the TextBox (that I can see). For example. on the combo control it is ignored entirely, Hence you can't intercept and kill it.
#2 Your solution is fine, except that it requires that there be special handling on every control or in the Keypreview to fire the enter key based on critiera. With the VB6 solution, you would just kill it after processing the enter key on the text control and nothing else including the default button would get the enter key. This is FAR more eligant.
And yes, I could use the CharacterCasing, but that relies on the control actually supporiting it. Yes, the Textbox does support this, but most of the other controls do not. (i.e. the Grid control, combobox control etc.) Throwing functionality at the controls to fix this problem is not the solution either. Yes, I could subclass all of them and add CharacterCasing, but that is just stupid, nor should MS go and add this type of functionality because this is just one small example. (the phone number one is an excellent example)
KeyDown should allow us to take the key value, and change it to whatever we want so that the value that gets written can be changed. (just like VB6) This addresses all of the cases without any problem.
Alternatively, if this isn't going to work, then there should be a KeyPreview event with exactly the same things as KeyDown and it should allow us to change the character.
Besides which e.Handled isn't intuitive.
Handled doesn't necssarily mean that you don't want it to propogate.
e.Cancel = true would be one heck of a lot better and far more obvious what it means.
If this can't be changed (which I assume it can't at this point) then the help documentation for e.Handled needs to be expanded greatly to explain what it will do in every circumstance and what the ramifications are.
"Sets the handled property of the control" is not helpful nor does it describe the functionality.
One more thing about this:
Create a form
Add a text box directly to the form.
Add a tab control to the form.
Add a tab page to the tab control.
Put a button on the tab page.
In the button's click event put in a message box saying something.
Run the program.
Click the button. (the message comes up)
Now click into the textbox and hit enter.
The button click will fire.
This is related to another bug:
The tab control (and this is true all the way back to VB3 and probably before!) doesn't fire the validate and lost focus events for items contained on it when a control outside of the tab control gets the focus. This is a bug, because the controls inside the container control definately have lost focus, but never get told that they have, so they don't get an opertunity to validate and lose their focus correctly.
Hence in the case above, the focus carrat stays to the button control even though the text box control has the focus in reality and when you hit enter, the button gets clicked.
So I guess one of the wishes along with the stuff above in this thread is to fix this damned tab control problem (its true of all container controls). I know that it's probably a win32 bug, but it should be worked around in the framework to handle this correctly. (it just needs to bubble up the tab's lost focus events etc, because the tab control does receive them.)