KeyPress event doesn't trigger on WinForm UserControl - c#

I have a user control in my winforms application with this code in the KeyPress event:
private void txtCodigo_KeyPress(object sender, KeyPressEventArgs e)
{
if ((this.txtCodigo.Text.Length == 0) && (e.KeyChar == '\r'))
{
this.Limpiar();
if (LimpiarEvento != null)
LimpiarEvento(this, new EventArgs());
if (NextControl != null)
NextControl(this, new EventArgs());
}
if ((this.txtCodigo.Text.Length > 0) && (e.KeyChar == '\r'))
this.txtCodigo_Leave(sender, e);
if (NUMEROS.IndexOf(e.KeyChar) < 0)
{
e.Handled = true;
}
}
Now, my problem is that this UserControl is in many forms in my application and works perfectly when i press the enter key in the txtCodigo textbox but in one form the enter key is not being fired. Even if i put a breakpoint it doesn't fire at all.
Why this could be happening?
Edit:
I just try to add a KeyPress event to the form itself and set the KeyPreview to true and the Enter key is not being captured... all the other keys are being captured except the Enter key. I really don't know what is happening. And yes... the enter key works fine in the keyboard :)

Does that particular form have its AcceptButton set?
(Already answered in comments)
This SO question might be relevant for fixing up the Form: Prevent WinForm AcceptButton handling Return key

What may be happening is this:
If you have copy-pasted the code from a previous program of yours the event handler hasn't be set.
First add the event handler from the designer of VS and inside the added handler paste your code.

Are you sure you added the event handler in the designer/code. It can be done this way. It should be added to the constructor where the control belongs.
this.txtCodigo.KeyPress += new KeyPressHandler(txtCodigo_KeyPress);
EDIT:
You are setting the event to be cancelled with this line of code.
e.Handled = true;
Source: http://msdn.microsoft.com/en-us/library/system.windows.forms.keypresseventargs.handled(v=vs.110).aspx

Related

Get keydown event without a textbox

Im trying to do like that: If I press the key "P" a messagebox will open in the screen.But I need to do it without a textbox or other tool, I want to do that direct in the form.
I tried:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.P)
{ MessageBox.Show("Key P pressed"); }
}
Try with the KeyPress Event of the form. It just works fine.
Assuming this is Winforms, on the form you're trying to catch the event on, make sure to set
Form1.KeyPreview = true;
KeyPreview ensures that keyboard events anywhere on the particular form (such as to a textbox with focus) will still count as a keyboard event for the form itself.

Keydown Event fires twice

On a Windows store App, I have this simple TextBox
<TextBox Name="TextBoxUser" HorizontalAlignment="Right" Width="147" Margin="20,0,0,0" KeyDown="TextBox_KeyDown" /
That has a KeyDown Event associated with it.
private async void TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
Debug.WriteLine("LA");
}
}
And the output of this function is:
LALA
although I press Enter only once, it prints 2 times.
Any reason for that or am I doing something wrong?
This should only fire the event once, so if it is firing twice I would check a couple of things.
Check that you aren't handling the key down event on a parent control. This could be a panel or the containing window. Events will bubble down through the visual tree. For example a key down on a textbox will also be a keydown on the window containing the textbox.
To stop this happening you can mark the event as handled as below;
e.Handled = true;
The other thing to check is that you aren't subscribing to the event twice. The XAML will do the same as;
TextBoxUser.KeyDown += TextBox_KeyDown
so check that you don't have this in your code behind.
You can check the sender and e.OriginalSource property to see where the event is being fired from.
This is a known bug in Windows RT.You can handle it by checking the Key RepeatCount `
if (e.KeyStatus.RepeatCount == 1)
{
//Execute code
}
I finally realized that there is probably a bug in the KeyDown event.
When I set, as #daniellepelley said,
e.Handled = true;
the event still propagates: other buttons will intercept it, also if they shouldn't.
In my code, I just replaced KeyDown event with KeyUp event and everything works fine (always setting Handled to True value)!
This might be too late, but e.preventDefault() worked for me. Especially in React - TypeScript.
(e: KeyboardEvent) => {
e.preventDefault();
console.log(e);
};
void onKeyPressEvent(object sender, KeyEventArgs e)
{
if(e.Handled)
return;
{
//
// the block of codes to be executed on the key press
// should added here.
//
}
e.Handled = true;
}
I had this same issue in Xamarin.Android where the keypress event fired twice.
In my case it is because the KeyDown and KeyUp are two separate actions which both call the same event. I only respond to one action as below:
private void KeyPress(object sender, View.KeyEventArgs e)
{
if (e.KeyCode == Keycode.Enter)
{
if (e.Event.Action == KeyEventActions.Down)
{
Event();
}
}
}
i was seeing this issue in javascript, where keydown event handler is fired twice, and was able to fix by using .off().on()
$('.text_area').off().on('keydown', function (e) {
// do something
)};
what it does is that, it switches off the extra events and the takes the latest keydown action and executes the handler for it
for me only this solution worked well
thanks

DataGridView KeyDown appears twice

Please, what is wrong with this code:
InitializeComponent();
this.KeyDown += new KeyEventHandler(dgvC_KeyDown);
private void dgvC_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyValue == 188)
{
System.Media.SystemSounds.Beep.Play();
e.SuppressKeyPress = true;
}
if (e.KeyValue == (int)Keys.Delete)
{
MessageBox.Show("323");
}
}
MessageBox appears twice!
I want to execute some code if comma is pressed and another code if DelKey is pressed on a DataGridView (dgvC).
MessageBox is just for test.
You are misunderstanding the purpose of e.SupporessKeyPress. In your dataGridView_KeyDown event, your use of;
e.SuppressKeyPress = true;
only prevents the event from being passed to the DataGridView after your method exits.
In your code, you also assign this event handler to the Form_KeyDown event, so the event is captured for 2 different controls, and SuppressKeyPress does not stop them from both receiving this event.
You need to remove this line from your code, which is assigning the handler (I believe erronesouly) to the Form_KeyDown event;
this.KeyDown += new KeyEventHandler(dgvC_KeyDown);
It looks like you have subscribed to the KeyDown event twice.
Remove the line in the .Designer.cs file and the e.SuppressKeyPress will still work.
Try inserting inside the ifs.
e.Handler = true;
this way the event won't be repeated.

Multiline textbox with skype like Functionalities

I was trying to have a textbox that creates new line when Shift+Enter is pressed and we can get keyevents when Enter is pressed
on backend of KeyDown Event i want to note that if Enter is pressed then do something.
if (e.Key.Equals(Key.RightShift))
{
}
this works fine for single line.as far as i click AcceptReturn = true and textwrapping to wrap then on pressing Enter new line is added to textbox but the event does not fire up.
i want new line to happen at Shift+Enter
and on Enter event should fire.
any idea?
I think you probably need to handle the PreviewKeyDown event. Catch the keypress combination you want to handle, handle it, then set e.Handled = true to make sure it doesn't get handled anywhere else as the keypress event tunnels & bubbles.
XAML:
<TextBox TextWrapping="Wrap" AcceptsReturn="True"
PreviewKeyDown="TextBox_PreviewKeyDown" />
Code-behind:
private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyboardDevice.Modifiers == ModifierKeys.None && e.Key == Key.Enter)
{
e.Handled = true;
// Do your special enter handling here...
}
// Shift+Enter (and any other keys) will be handled as normally...
// ...you'll still get your new line on Shift+Enter
}
Note: If you want an Enter keypress to still add a new line as well as your special handling then just remove the e.Handled = true line.
Try the following on the KeyDown event, should work on a vanilla multiline textbox, no need for anything further:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (!e.Shift && e.KeyValue == (int)Keys.Enter)
{
e.SuppressKeyPress = true;
// Fire my custom event
}
}

Preventing double events in DataGridView

I have a problem that I am not sure how to solve. I have a DataGridView (EditMode = EditProgrammatically). This grid has one checkbox column and one or more textbox columns. The functionality is as following (or should be at least):
When you click on a checkbox, the checkbox should be toggled
When a row (or many rows) are selected, and you press space, the checkboxes should be toggled.
I have these two event handlers:
private void grid_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex == useColumn.Index)
{
if (ModifierKeys != Keys.Shift && ModifierKeys != Keys.Control)
{
ToggleRows(grid.SelectedRows);
}
}
}
private void RowSelectorForm_KeyDown(object sender, KeyEventArgs e)
{
if (grid.Focused && e.KeyCode == Keys.Space)
{
ToggleRows(grid.SelectedRows);
e.Handled = true; // Not sure if this is needed or even does anything
e.SuppressKeyPress = true; // Or this for that matter...
}
}
This almost works. The problem is when you press space and a checkbox cell is active. When a textbox cell is active, it works like it should. The problem is that when you press space and a checkbox cell is active, both events gets fired. Which means it first selects and then deselects (or the reverse). So the checkboxes end up being like they was. How can I prevent this?
I have thought about using a flag, but not sure where I can put it, since I can't really know if it was a double event or if it was just the user using space and then clicking with the mouse. So that can't really be used I think. Is there a different event I should use? Is there a way to see if the cell was clicked by mouse or by space? Is there a way to disable the automatic checkbox toggling when space is pressed? What can I do?
Note: Reason for RowSelectorForm_KeyDown and not just grid_KeyDown was that I was trying to use KeyPreview and then suppress the keypress if it was space and the grid was focused. But that SuppressKeyPress doesn't really seem to do anything at all =/ Maybe I've just misunderstood it...
Well, I didn't want to do it, but I have now fixed it with a timer... but if anyone knows how to do it properly, please let me know!!
Current solution:
private DateTime lastClick = DateTime.MinValue;
and in both events:
if (DateTime.Now - lastClick > TimeSpan.FromMilliseconds(400))
{
lastClick = DateTime.Now;
ToggleRows(grid.SelectedRows);
}
It has been a time since I worked with C#, but I assume that you can disconnect the grid_CellClick event handler before calling ToggleGrid in RowSelectorForm_KeyDown.
After the call, you can reconnect the event handler.
Also, there might be some way to supress the event from being fired in the first place. In some API's certain methods are specially provided that don't trigger any events.
The frustrating problems are:
.Handled doesn't prevent the check box from changing
.SuppressKeyPress doesn't prevent the checkbox from changing
If you DoubleClick on the checkbox, the first click fires the Click() event (toggling the checkbox) and the second click fires the DoubleClick() event (toggling the checkbox yet again).
However, the KeyDown event fires before any of the grid events. Perhaps setting a flag to indicate the spacebar was pressed or if the row was already selected, reset the value of the checkbox.
I used the following and it seemed to work well:
private Keys _ClickSource = 0;
private void dgv_CellClick(object sender, System.Windows.Forms.DataGridViewCellEventArgs e)
{
if (_ClickSource == 0 || _ClickSource != Keys.Space)
{
dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = ! (System.Convert.ToBoolean(dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Value));
}
_ClickSource = null;
}
private void dgv_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
_ClickSource = e.KeyCode;
}

Categories