Jay,
The debug statements were a great idea. However, I appear to have
confused
things with my sample application, which was only designed to illustrate
that Form1 was receiving a KeyUp from a key press that occurred on Form2.
Perhaps you're used to this, but it was an unpleasant surprise for me.
So let me start over with a sample that more closely mirrors my real
application. My app starts with Form1 which has a textbox on it. I want
to
display Form2 if the user presses Enter while in the textbox. I'm using
the
KeyUp event of the textbox for that. Form2 has an OK button, and has its
AcceptButton set to that OK button. The scenario runs like this:
1. App starts, Form1 is shown, the textbox has focus
2. The user presses Enter. Form2 is then shown modally.
3. The user does his thing on Form2 and then presses Enter, expecting to
be
returned to Form1.
Here is the sequence of events for step 3:
a. No KeyDown or KeyPress events fire. Presumably, by setting the
AcceptButton property of Form2, it is now intercepting and "handling"
those
events.
b. The Click event of the OK button on Form2 fires, which closes Form2.
c. The KeyUp event of TextBox1 on Form1 fires, which, as described above,
launches Form2.
The user is confused. He pressed enter, he saw Form2 unload, but then it
reloaded immediately. If he presses Enter again, then it repeats (Form2
closes and reopens).
I guess I can work around this by using the KeyDown or KeyPress events. I
don't like them as much as KeyUp, because KeyUp is guaranteed to only
fire
once per key press, whereas the others can fire over and over (if the
user
holds the button down), but they suddenly seem a lot safer in light of
this
issue.
What I was hoping was that there might be some way that I could prevent
the
KeyUp event from happening. Not handle it, mind you, because by then I'm
in
Form1 and I can't tell a "good" KeyUp from a bad one. But if I could
somehow
intercept and clear it, say from the Closing event of my Form2, that
would
be cool.
You see, the bigger issue here is how can I defend one window from events
caused by a user who is in another window? Unwanted KeyUp and/or MouseUp
events can be a rude surprise. It would be nice if there was some way for
a
form that was closing to say "throw away any outstanding KeyUp or MouseUp
events that have not occurred yet".
Thanks again for your help,
-AJ
Adam,
To see why it happens add the following code to Form1:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Debug.WriteLine("Click", "Button1")
Dim f As New Form2
f.ShowDialog()
End Sub
Private Sub Button1_KeyUp(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyEventArgs) Handles Button1.KeyUp
Debug.WriteLine("KeyUp", "Button1")
End Sub
Private Sub Button1_KeyDown(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyEventArgs) Handles Button1.KeyDown
Debug.WriteLine("KeyDown", "Button1")
End Sub
Private Sub Button1_KeyPress(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles Button1.KeyPress
Debug.WriteLine("KeyPress", "Button1")
End Sub
Private Sub Button1_MouseDown(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles Button1.MouseDown
Debug.WriteLine("MouseDown", "Button1")
End Sub
Private Sub Button1_MouseUp(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles Button1.MouseUp
Debug.WriteLine("MouseUp", "Button1")
End Sub
Run your form. Watch the debug messages, especially when you press Enter
(or Space) when Form1.Button1 has the focus & doesn't have the focus.
Also
watch when there are other controls earlier & later in the tab order on
Form1.
Assuming there are no other controls on Form1:
When Form1.Button1 does not have the focus, Button1 gains the focus &
does
the Click event, Form1.Button1 now has the focus, so Form1.Button1.KeyUp
event is raised.
When Form1.Button1 does have the focus, Button1 raises its KeyDown &
KeyPress event, then the Click event, followed by the KeyUp event.
MouseDown, Click, and MouseUp events happen in a similar order.
IMHO Preventing it seems rather easy, Don't handle the
Form1.Button1.KeyUp
event, or if you do need to handle it, make sure you know when the event
is occurring as part of the Click event or another event...
Hope this helps
Jay
Jay,
To reproduce, create a new vb.net winforms app with two forms. Place a
button on each form.
Add this code to form1:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim f As New Form2
f.ShowDialog()
End Sub
Private Sub Button1_KeyUp(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyEventArgs) Handles Button1.KeyUp
Stop
End Sub
Add this code to form2:
Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.AcceptButton = Button1
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Me.Close()
End Sub
Run the app, click the button on form1. Form2 opens, press Enter. Note
that
the breakpoint in form1 gets hit! I don't understand why, since enter
was
pressed while form2 was open. More importantly, I don't understand how
to
prevent it.
p.s. framework v1.1, windows xp-sp2
<<snip>>
I created a very small project. It has two forms. On Form1, I placed a
single textbox. It's keyup handler is shown below:
Private Sub TextBox1_KeyUp(...) Handles TextBox1.KeyUp
If e.KeyCode = Keys.Enter Then
Dim f As New Form2
Debug.WriteLine("Form1: TextBox1: KeyUp")
f.ShowDialog()
f.Dispose
End If
End Sub
On Form2 I placed a single button. I then set the AcceptButton propert of
Form2 to be the button. I added the following code to the Button's click
event:
Private Sub Button1_Click(...) Handles Button1.Click
Debug.WriteLine("Form2: Button1: Click")
Me.Close()
End Sub
When I fire up the program, Form1 appears with the textbox having focus
(since it is the only control on the form). I press enter and Form2
appears. I press enter again which causes the button on form2 to be
clicked which closes form2. Form2 immediately reappears!!
The following text appears in the output windows:
Form1: TextBox1: KeyUp
Form2: Button1: Click
Form1: TextBox1: KeyUp
Where is that extra KeyUp event coming from? When I pressed Enter,
*FORM2*
had focus, form1 should not have gotten a keypress from form2!!
What appears to be happening is that the AcceptButton is being triggered
when the key goes down, which closes the form, but then the key up occurs
after form2 has been closed so the keyup goes to the only form which has
focus: Form1, which, of course, opens form2 again!
While, perhaps, its behavior is undesired, it is logical. The only
workaround I could think of was by adding a boolean flag that is set right
after form2 is closed and checking that flag on entering the keyup event.
If set, don't show form2 again:
'Global boolean
Dim bForm2JustClosed As Boolean
Private Sub TextBox1_KeyUp(...) Handles TextBox1.KeyUp
If e.KeyCode = Keys.Enter Then
'If Form2 just closed, then ignore this KeyUp for the Enter key
If bForm2JustClosed Then
bForm2JustClosed = False
Exit Sub
End If
Debug.WriteLine("Form1: TextBox1: KeyUp")
Dim f As New Form2
f.ShowDialog()
f.Dispose()
'Form2 just closed so set the flag to indicate this
bForm2JustClosed = True
End If
End Sub
This code seems to work for my simple test app, but whether or not it can
work for you, I don't know. Perhaps another option is in the keyUp event
for the textbox, set focus to some hidden control so that IT receives the
keyup event when form2 is closed then in it's keyup event, restore focus
back to the textbox.
Anyway, just wanted to let you know you are not losing your mind.
--
Chris
dunawayc[AT]sbcglobal_lunchmeat_[DOT]net
To send me an E-mail, remove the "[", "]", underscores ,lunchmeat, and
replace certain words in my E-Mail address.