I have a custom search activity that serves search suggestions. I get a reference to the search input box and set a handler:
mSearchInput = FindViewById(Resource.Id.searchBoxInput) as EditText;
mSearchInput.KeyPress += new System.EventHandler<View.KeyEventArgs>(OnSearchKeypress);
This is the handler that should be called on every key press:
private void OnSearchKeypress(object sender, View.KeyEventArgs e) {
string query = mSearchInput.Text;
if (e.KeyCode == Keycode.Enter && !string.IsNullOrEmpty(query)) {
e.Handled = true;
// launch search results activity
}
else {
e.Handled = false;
if (query.Length > 2) {
// load suggestions if we have 2+ characters
}
}
}
For some reason, on the soft keyboard, only certain key presses fire the event at all. Enter and Delete fire the event. Alphanumeric keys do not. Even if I take out all of the logic and simply do a Toast with e.KeyCode.ToString() it only shows the toast on those few keys.
Am I listening for the wrong event, is this a bug, or have I made some other mistake?
Device: Droid X2
Mono Version: 4.0.4
Update: I discovered that KeyPress is triggered twice for each physical press of a key: once for KeyEventActions.Up and once for Down. This doesn't explain why only certain keys fire the event but it should be noted that you need to check event.E.Action to find out whether the press or release is currently triggering the event.
When is the event not firing? If it is when the user is typing, then you can use the TextChanged event. You can then continue with your implementation in the OnKey method.
Also, look at this article for the "search" button:
http://www.stackoverflow.com/questions/1489852/android-handle-enter-in-an-edittext
Related
I have a winforms application where in I have a textbox inside a form. I need to set focus to the textbox whenever I press 'Ctrl+F'. I have the following code in keyup event.
private void frm_KeyUp(object sender, KeyEventArgs e)
{
// Handle 'Ctrl + F' to Find
if (e.KeyData == (Keys.Control | Keys.F))
SetFocus();
}
Problem I have here is that sometimes, even though the focus is on form and I try 'Ctrl+F' the condition doesn't run. I know, as soon as I press 'Ctrl' the event gets fired even before I would have pressed key 'F'. Eventually it works, when I press both the keys at the very same time. So to the user it might look like the screen is unresponsive to the keys sometimes.
How can I overcome this situation?
You're using the KeyUp event and checking if the event contains both keys. This will only happen when you release both keys at the same time.
Change it to the KeyDown event instead, and check whether Ctrl was pressed at the moment F was pressed:
if (e.Control && e.KeyCode == Keys.F)
{
// ...
}
Pressing a key in a text box, the KeyDown event occurs before KeyPress.
I used a count and message boxes to see what would happen.
The following is my code:
int Ncount = 0;
private void Textbox_KeyDown(object sender, KeyEventArgs e)
{
Ncount += 1;
MessageBox.Show("KeyDown's Ncount : " + Ncount.ToString());
}
private void Textbox_KeyPress(object sender, KeyPressEventArgs e)
{
Ncount += 1;
MessageBox.Show("KeyPress's Ncount : " + Ncount.ToString());
}
When a key is pressed, this will show first...
KeyPress's Ncount : 2
...followed by this:
KeyDown's Ncount : 1
Shouldn't the KeyDown message box (with NCount 1) show before the KeyPress message box (with Ncount 2)?
Short version: MessageBox.Show() is the infamous Application.DoEvents wolf in sheep's clothing. Definitely more benign than DoEvents but it doesn't solve re-entrancy problems like this one. Always use the Debug class in .NET if you want to display debug info.
Longer version: to make sense of this behavior you first have to know a little factoid: by the time you get the KeyDown event, the operating system has already generated the KeyPress notification. It is sitting patiently in the message queue, waiting for your app to resume the dispatcher loop. It will be the next event you get. Unless you set e.Handled to true, then Winforms looks through the message queue and purges the KeyPress notification so the event won't fire.
Next factoid: in order for MessageBox to become modal, or for that matter any ShowDialog() call, it needs to run a dispatcher loop itself. Which ensures that basic stuff still happens, like painting the windows and MessageBox recognizing the OK button click and the user getting slapped with a Ding! when he clicks on anything else but the message box.
Maybe you can connect the dots now, that dispatcher loop in MessageBox will see the KeyPress notification in the queue. And cause your KeyPress event handler to run. So you display another message box, necessarily it is on top of the first one.
Nothing goes dramatically wrong here, the side-effect is just that the Z-order of the boxes is not the one you expect. You'll get a lot more drama if you set e.Handled = true and expect it to work. It won't. It can't. It was already handled by the time your KeyDown event handler completes.
There is no simple fix for this. But one, don't use it. Always use the Debug class to generate debug info. MessageBox has entirely too many side-effects.
A thread on MSDN forums speaks to this oddity:
The event handlers are running in a separate thread. Modal forms are
modal in the context of their own threads.
So whereas message boxes are modal in the form's UI thread, this is not the case for message boxes shown in event handlers.
The message boxes do show in the expected order; they just are not modal per the note above: so they appear to be in the opposite order (when the second/KeyPress message box stacks on top of and covers the first/KeyDown message box).
A variant of your sample code demonstrates what I mean:
int Ncount = 0;
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
Ncount += 1;
var message =
String.Format(
"({0}) KeyDown's Ncount : {1}",
DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture),
Ncount);
Debug.WriteLine(message);
MessageBox.Show(message);
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
Ncount += 1;
var message =
String.Format(
"({0}) KeyPress's Ncount : {1}",
DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture),
Ncount);
Debug.WriteLine(message);
MessageBox.Show(message);
}
It yields the following console output...
(2015-08-15 03:45:31.455) KeyDown's Ncount : 1
(2015-08-15 03:45:31.487) KeyPress's Ncount : 2
...and message boxes in the following unexpected order it would seem...
...but really in the opposite/expected order as the time stamps in the message boxes show.
A KeyPressEventArgs specifies the character that is composed when the user presses a key. For example, when the user presses SHIFT + K, the KeyChar property returns an uppercase K.
A KeyPress event occurs when the user presses a key. Two events that are closely related to the KeyPress event are KeyUp and KeyDown. The KeyDown event precedes each KeyPress event when the user presses a key, and a KeyUp event occurs when the user releases a key. When the user holds down a key, duplicate KeyDown and KeyPress events occur each time the character repeats. One KeyUp event is generated upon release.
With each KeyPress event, a KeyPressEventArgs is passed. A KeyEventArgs is passed with each KeyDown and KeyUp event. A KeyEventArgs specifies whether any modifier keys (CTRL, SHIFT, or ALT) were pressed along with another key. (This modifier information can also be obtained through the ModifierKeys property of the Control class.)
Set Handled to true to cancel the KeyPress event. This keeps the control from processing the key press."
However also note -
"Some controls will process certain key strokes on KeyDown. For example, RichTextBox processes the Enter key before KeyPress is called. In such cases, you cannot cancel the KeyPress event, and must cancel the key stroke from KeyDown instead."
The documentation is clear that KeyDown fires before KeyPress and you can show that it does by coding something like this:
Private Sub TextBox1_KeyDown(sender As Object, e As KeyEventArgs) _
Handles TextBox1.KeyDown
Debug.Print("Down")
MessageBox.Show("Down")
e.Handled = True
End Sub
Private Sub TextBox1_KeyPress(sender As Object, e As KeyPressEventArgs) _
Handles TextBox1.KeyPress
Debug.Print("Press")
MessageBox.Show("Press")
End Sub
Running this you will see that Debug writes "Down" before "Press". You can also but breakpoints in the two handlers and see that KeyDown fires before KeyPress.
You will also see that the "Press" MessageBox shows before the "Down" MessageBox. That is curious and I would be interested if someone could explain it.
Reference: KeyPress Event firing before KeyDown Event on textbox.
It seems that the keydown event does not handle spacebar presses unless the control has focus. How do I, though?
I am using c# and I am making a windows store app, if it matters.
I'm not sure of what code you have within your project already but I'd recommend some JQuery along the lines of:
$(window).keypress(function(e) {
if (e.keyCode == 0) {
console.log('Space pressed, here is my event');
}
});
As the event is bound to a Window event, it will find it regardless of whether an input field is focused or not.
I figured it out.
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
captures all key events.
I have a little problem that needs your ideas, I am building a simple application to detect when user finishes writing text into a textbox, there is a button the user can click or press the enter key to proceed further action
[UPDATE]
Oh I am sorry, I have to add that the textbox is from another windows, it may be any windows.
I don't want to use function like GetAsyncKeyState which is an ugly method.
Use Control.KeyPress Event
this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(CheckKeys);
private void CheckKeys(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
// Then Enter key was pressed
}
}
(char)13 means the Enter key.
Is there a way to start a method in C# if a key is pressed? For example, Esc?
use the OnKeyPress Event of your textbox and in the event
if(e.KeyCode==Keys.Escape)
{
yourTextBox.Text = string.Empty;
}
As others have mentioned, handle the KeyDown or KeyUp event of the appropriate control. The KeyPress event would work for the Escape key as well, though it will not trigger for some keys, such as Shift, Ctrl or ALt.
If you want to execute this function anytime the user presses the Escape key, then you probably want to handle the event on the Form. If you do this, you will probably also want to set the Form's KeyPreview property to true. This will allow the Form control to receive the event even if the focus is currently inside of one of the child controls.
If you want the behavior to be specific to a control, such as clearing the text within a textbox that currently has focus, then you should handle the KeyDown or KeyUp event of the TextBox control. This way, your event handler will not be triggered if the user presses the escape key outside of the textbox.
In some situations you might want to prevent child controls from handling the same event that you've just handled. You can use the SuppressKeyPress property on the KeyEventArgs class to control this behavior:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
MessageBox.Show("Escape key pressed");
// prevent child controls from handling this event as well
e.SuppressKeyPress = true;
}
}
In case someone is looking for how to do this in a console application
if (Console.ReadKey().Key == ConsoleKey.Escape)
{
return;
}
I am writing WinForms application. User fills the textbox and if he wants to delete everything, he just clicks esc key on keyboard
I think you need to handle the KeyDown event.
You have to switch the form property "KeyPreview" to true or your events will not be fired. Handling these events alone will not do anything even though the events are correct. It will look to you like nothing really happens even though you have subscribed the proper event handlers.
First in Properties do > KeyPreview : True
Then :
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
//call your method here
}
}
Are you writing a Console application, a WinForms application or something else? Are you trying to capture the ESC key at all times (regardless of the focused window/application) or something else?
More context required.
If you're writing a Console app, then you should start looking at things like Console.ReadKey...
http://msdn.microsoft.com/en-us/library/system.console.readkey.aspx
With Event KeyPress...
//Escape
if (e.KeyChar == '')
{
this.DialogResult = DialogResult.Cancel;
e.Handled = true;
}
You can use KeyUp event too. I prefer it though.
private void Window_KeyUp(object sender, System.Windows.Input.KeyEventArgs e) {
if (e.Key == Key.Escape) {
//WHAT WILL HAPPEN INSERT HERE
}
}
The basic answer is listed here several time
Implement Form_KeyDown
Private Sub frmCustomerSearch_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
Try
If e.KeyCode = Keys.Escape Then
ClearFindForm()
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Set form.keyPreview
form.KeyPreview = true
The additional thing you need to check is whether you have a button capturing ESC so it can be the form.cancelButton
to be sure ...
form.CancelButton = nothing
This is sneaky. If you have set that and forgot about it, the Escape key will not trigger the KeyDown event.
I was led to this because a button set to be the form.CancelButton does not seem to fire if it is invisible or on a non visible tab,so KEYDOWN is your only option.