Winform keyboard management - c#

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.

Related

KeyDown not picking up 'Return' key C#

private void idTextEdit_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return)
{
e.Handled = true;
SearchButtonClick(sender, EventArgs.Empty);
}
}
I have a text box where this code check fires for every single keypress except for the Enter/Return key which for some reason does nothing. The cursor that is active on the textbox disappears, so I'm thinking it changes focus before the keydown event can fire but I'm not sure. How can I get the return key to stop deselecting the box and register as a keypress. Also there is no other code that would set the enter key to have a different functionality and it's a pretty simple one text box screen for testing.
If you have an AcceptButton set then you'll get the behaviour you are seeing.
I tried your code with my sample form and it worked as expected.
I then set the AcceptButton to one of the buttons and the text box stopped responding to the Enter. Setting AcceptsReturn on the text box had no effect.
Set the AcceptsEnter property to true

Overriding keypress

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 ?

How to intercept the TAB key press to prevent standard focus change in C#

Normally when pressing the TAB key you change the focus to the next control in the given tab order. I would like to prevent that and have the TAB key do something else. In my case I'd like to change focus from a combobox to a completely different control. I can't do this by setting the tab order. I need to do this programatically. Any idea how? It seems like the KeyDown and KeyPress events can't handle TAB key correctly.
Thanks.
Override ProcessDialogKey or ProcessTabKey on your Form and do the logic you want depending on which control is focused.
Based on JRS's suggestion of using the PreviewKeyDown event, this sends the key press through to the control:
private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Tab)
e.IsInputKey = true;
}
Then you can handle the control's KeyDown event if you want to customise the behaviour:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab)
{
MessageBox.Show("The tab key was pressed while holding these modifier keys: "
+ e.Modifiers.ToString());
}
}
TextBoxBase alternative
If the control is derived from TextBoxBase (i.e. TextBox or RichTextBox), with the Multiline property set to true, then you can simply set the AcceptsTab property to true.
TextBoxBase.AcceptsTab Property
Gets or sets a value indicating whether pressing the TAB key in a multiline text box control types a TAB character in the control instead of moving the focus to the next control in the tab order.
Override the control's LostFocus event see link below for examples:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.lostfocus.aspx
Since I am building a UserControl, I ended up using the PreviewKeyDown event on the control. This avoids having to handle key press events on the host form.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx
You can try this code on your KeyDown event:
if (e.KeyCode == Keys.Tab) {
//your logic
e.SuppressKeyPress = true;
}
If the button clicked is Tab, then do any custom logic you want, then call SuppressKeyPress to stop the KeyPress event from firing and invoking the normal Tab logic for you.

How to stop textbox leave event firing on form close

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

.NET: TextChanged event for TextBox not always firing, even though KeyUp and KeyDown are firing

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.

Categories