Here is code for a form with a button(not shown) and a textbox. Pressing any key other than function keys causes the KeyDown Event to fire as expected, the textbox is selected, the cursor flashes and the character of the subsequent keystroke appears in the textbox. When pressing a function key however, although the textbox is selected, the cursor does not flash and the character of the very next keystroke does not appear in the textbox. The characters of subsequent keystrokes do appear as expected.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
textBox1.Select();
}
}
I have been able to circumvent this problem by overriding the ProcessCmdKey method but I am curious to know how to do it with KeyDown.
Thanks!!
These days, the preferred method of reading F[1-12] key presses is to override the ProcessCmdKey method, as you said. However, one (now deprecated) way to allow KeyDown to handle F keys is to set the form's KeyPreview property to true. However, as you can see in this post, there are disadvantages to this approach, so it's safer to use ProcessCmdKey.
Related
I am creating a simple game for school in C#, where I am controlling a character using the WASD keys. The character is taken from a sprite sheet and put into an imagelist. The imagelist is in a picturebox.
Everything works fine when it's just the picturebox in the form, but when I add a button or something else, it's like it lose focus. It doesn't respond.
I have searched endless pages for a solution to set focus on the picturebox when the form opens, but I haven't found anything that works.
I would really appreciate some help.
Edit: It's WinForms.
The PictureBox cannot take the focus. It is intended as a way to show an image but not intended to allow user input such as via the keyboard.
A crude approach would be to intercept the OnKeyDown event on the Form itself and then test for the keys of interest. This will work as long as the control that has the focus, such as your Button, does not want to process those keys itself.
A better approach would be to override ProcessCmdKey() method of the Form. This method is called on the target control, such as your Button, to decide if the key is special. If the Button does not recognize it as special then it calls the parent control. In this way your Form level method will be called for each key press that is not a special key for the actual target. This allows the Button to still process a ENTER key which is used to press the Button but other keys will be processed by your Form.
Lastly, to intercept all keys before they are handled by any of the controls on the Form you would need to implement the IMessageFilter interface. Something like this...
public partial class MyWindow : Form, IMessageFilter
{
public MyWindow()
{
InitializeComponent();
Application.AddMessageFilter(this);
}
public bool PreFilterMessage(ref Message m)
{
// WM_KEYDOWN
if (m.Msg == 0x0100)
{
// Extract the keys being pressed
Keys keys = ((Keys)((int)m.WParam.ToInt64()));
// Test for the A key....
if (keys == Keys.A)
{
return true; // Prevent message reaching destination
}
}
}
return false;
}
I found event MouseHover with pictureBox1_Hover calling pictureBox1.Focus() worked. When the mouse was hovered over the PictureBox in question, it would gain focus. Other than that, it didn't seem that calling pictureBox1.Focus() during form load had any effect on the focus.
this.pictureBox1.MouseHover += new System.EventHandler(this.pictureBox1_Hover);
private void pictureBox1_Hover(object sender, EventArgs e)
{
pictureBox1.Focus();
}
It worked for me!
I know this may be an easy answer to some of you but i dont know how to properly do this. Ive created a text editor, that also has a docking window that will display functions. I have it set up in the menu that F8 is the shortcut key for showing the function window. I would also like to catch the F8 keypress event to parse the current data for the functions in the program but I cant get this to happen..
Capture your Text Editors KeyPressed Event and check the KeyEventArgs that are coming in, then mark the not handled as false which will cause the event to be passed up to the parent control:
Example
KeyPressed(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F8) DoSomething();
e.Handled = false;
}
In response to the comment that you added to your question. You may need to set the controls KeyPreview to True. I think that KeyPreview may be available at only the form level, but I'm not sure.
Set up an event handler for the OnKeyPress (or OnKeyDown or OnKeyUp) event, and check which key was pressed (it will be in the event arguments). Then, you can do whatever you want.
I don't think the tagged answer is correct. The KeyPress event handler won't handle the Function keys; you need to use KeyUp event handler or ProcessDialogKey method.
I'm not sure to understand everything, but can't you use the KeyPress Event available in any Control ?
using c# winforms vs2008
I've got a textbox on a form with a method being called from the textBox1_Leave event. The method takes the contents of the textbox in question and populates other textboxes based on the contents.
My problem is that is the user has focus on the text box then clicks the button to close the form (calling this.close) then the form does not close because the textbox leave event gets fired.
If the textbox does not have focus on form close then the form closes fine.
If however a user closes the form by clicking the little X close icon in the top corner the it closes fine all the time with out the textbox leave event being fired.
How can I duplicate the X close functionality so that I can always close the form without the textbox leave event being fired?
The simplest solution is going to be to check which control is actually focused before doing your post-processing - but you can't do it in the Leave handler, because the focus will still be on the text box at that point.
Instead, you need to move your logic to the LostFocus event, which is not in the designer. You'll have to wire it up at runtime:
public class Form1 : Form
{
public Form1()
{
InitializeComponent();
textBox1.LostFocus += new EventHandler(textBox1_LostFocus);
}
private void textBox1_LostFocus(object sender, EventArgs e)
{
if (closeButton.Focused)
return;
// Update the other text boxes here
}
}
The LostFocus event happens to fire after the new control receives focus.
Clarification - you might find that it works by putting this logic in the Leave event - if the focus is changed by the mouse. If the keyboard is used instead, you'll get the wrong behaviour. LostFocus is reliable in both cases - the focused control will always be the "new" control. This is documented on MSDN: Order of Events in Windows Forms.
Incidentally, the reason why you're not having this problem with the "red X" is that the X is not actually a control that can receive focus, it's part of the window. When the user clicks that, it's not causing the text box to lose focus, and therefore isn't causing the Leave event to fire.
Another approach:
Use the textbox's validating event instead of it's leave event, then change the button's CausesValidation property to false. You will also have to set the textbox to not cause validation in the button's click event so the validating event will not fire when the form is closing (thanks to #Powerlord for pointing this out).
private void button1_Click(object sender, EventArgs e)
{
this.textBox1.CausesValidation = false;
this.Close();
}
You could also handle the FormClosing event and make sure the e.Cancel argument does not get set to true by the validating events on the other controls on the form. I think they will be fired off before the FormClosing event.
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = false;
return;
}
}
you can check to see which control has just got focus.
private void textBox1_Leave(object sender, EventArgs e)
{
if (btnClose.Focused)
return;
// go from here
}
Just check if the form owning the textbox is disposing? If it's getting closed, it's disposing. If it's disposing you could simply end the pesky 'leave' event without doing anything. I didn't check it and forgive me, I'm choked on a project of my own so and I was searching myself, so I don't think I'll have time for that.
private void GuiltyTextBox_Leave(object sender, EventArgs e) {
Form formOwningTheTextBox=(Form)((Control)sender).TopLevelControl;
if (formOwningTheTextBox.Disposing || formOwningTheTextBox.IsDisposed) return;
.......
}
I just believe this is going to work with minimum effort and wanted to send a quick answer before I resume searching my own answer.
Write Following line of code in text box leave event on top
if me.closing then
return
end if
I'm running into a very peculiar issue. I noticed that occasionally while typing into my TextBox, I'll lose some keystrokes. I added a bunch of trace statements in events hooked by this TextBox, and I found that when I lost keystrokes, the KeyUp, KeyDown, and KeyPress events all correctly fired, but the TextChanged event never fired.
Does anybody have any idea why this would happen? I could write this off as a ".NET bug", but I'd rather figure out if there is a solution here.
In case there is a suggestion that I use the KeyUp/KeyDown events to determine if the text has changed, there is an issue there as well. KeyUp/KeyDown are called multiple times for each key press, so it would be very difficult to determine if someone was typing the same letter multiple times.
Hmmm....
This is going to be a shot, but, you did say you have the KeyUp, KeyDown and KeyPress event handlers right? Have you set the flag e.Handled to true in the event handlers, have a look here:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
}
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
e.Handled = true;
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = true;
}
Have a look here in the MSDN about this Handled property. (If you have MSDN 2008 SP 1 installed locally, the link is ms-help://MS.MSDNQTR.v90.en/fxref_system.windows.forms/html/dfc80b44-1d79-6315-cbea-1388a048c018.htm)
To quote:
Handled is implemented differently by different controls within Windows Forms.
For controls like TextBox which subclass native Win32 controls, it is
interpreted to mean that the key message should not be passed to the underlying
native control.
If you set Handled to true on a TextBox, that control will not pass the key
press events to the underlying Win32 text box control, but it will still
display the characters that the user typed.
Maybe it is not set i.e. e.Handled = false; thereby preventing the TextChanged Event from firing?
Can you check and confirm this?
Edit: After dreadprivateryan's response, I can suspect (due to lack of code posted), based on his response, e.Handled is true for when Enter key is pressed and false for everything else which in my mind, thinks that is the reason why no further keystrokes are being accepted as a result of this.
Are you trying to set focus to another control upon the Enter key being pressed? It could be that both KeyUp and KeyDown are conflicting...
Remove the keyboard hook and disable it...
My suggestion is to change the code completely in this manner as shown, take out either KeyDown or KeyUp Event Handler as they, simplistically put it, are the same, ok, technically, it is designated respectively for when a key is pressed down, and likewise when a key is released. Have a look at this link here. There was a similar question posted here on SO.
In the example below, I used the keyUp event handler to switch focus to the next available control upon enter key being pressed. In the KeyPress event handler, this simply filters the input and only allows numbers 0-9 respectively, anything else gets discarded. Included in that event handler, is the allowance for the backspace key to provide editing.
private void textBox1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter) SendKeys.Send("{TAB}");
}
private const string VALID_KEYS = "0123456789";
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (VALID_KEYS.IndexOf(char.ToUpper(e.KeyChar)) != -1 || e.KeyChar == (char)8)
e.Handled = false;
else
e.Handled = true;
}
Hope this helps,
Best regards,
Tom.
I don't actually know, but I have a random guess: You running in a VM?
One hack you could use is make a timer that reads the text and compares to the previously entered value. Call the event handler code when it isn't equal to the previously checked value. When you need to use the final entered value, do one additional check, in case the timer hasn't fired yet.
Do you mean the keypress is actually lost and never shows up in the box? Or do you mean you don't get a TextChanged event for every keypress?
I believe the TextChanged event is driven by the operating system's EN_CHANGE notification which is sent via a WM_COMMAND message. I know that certain kinds of messages in Windows are "coalesced" to avoid redundant notifications. For example this can happen with WM_MOUSEMOVE messages and is why you don't receive a mouse move event for every pixel that the mouse moves across the screen.
I can't say for sure but I suspect that the TextChanged event behaves this way as well. I can say though that alternate input methods have this side effect too. When using a Tablet PC input panel, the textbox will not get a TextChanged notification for every character.
I would like to control the focus of my winform application. It is made of a custom listbox and several other component.
I want all the keyboard event be managed by my window handlers in order to avoid specific control key handling (for example when I press a character and the list box is focused, the item starting with the correspondant letter is selected which is not a correct behaviour for my application).
How can I achieve this?
Make sure your form's KeyPreview property is set to true. Then this code should work for canceling your key events to the listbox...
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (this.ActiveControl == listBox1)
e.Handled = true;
}
The KeyPress event may not work for all your scenarios. In that case, I would try out the KeyDown event.