I read a lot of questions about making a hotkey for a Windows Forms Applications and tried the code a lot people said it was working, but for me, somehow not.
Code:
void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.S)
{
timer1.Stop();
e.SuppressKeyPress = true;
}
}
If you want to create global hotkeys manager for your form to be available for all controls in that form, you need to override the Form.ProcessCmdKey() method that catch all keys for all controls, instead of using the form key down event that works only when the background is focused and which can only happens when ActiveControl is null:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
switch ( keyData )
{
case Keys.Control | Keys.S:
timer1.Stop();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
Thus you can catch any key combination you need and return true if processed.
Related
I am trying to bind a keyboard button (preferably "ESC") to stop the code that is running inside the method. But the thing is, it only works with actual buttons, is there anyway to bypass this so it works when pressing labels aswell?
private void label1_Click(object sender, EventArgs e)
{
if (e.Control && e.KeyCode.ToString() == "ESC")
{
MessageBox.Show("This does now work");
}
}
I've read somewhere that it is possible its just that the Visual Studio GUi doesnt provide it, but you can do it with code somehow, is this true?
I am not sure what you are trying to do. The following will get the Escape key when it is pressed when the focus is in the form regardless of what control has the focus. Just add this to the form (the code of course).
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Escape))
{
MessageBox.Show("This works");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
I have a form that has several buttons. I have KeyPreview set to true, and I have Keydown, KeyPress, and keyup events all reading
form_keyevent(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
e.handled = true;
}
For some reason, the enter key still clicks a button that has focus. What am I missing? Is there a way around it?
Pressing the Enter key on a Form with a focused button invokes the Form.ProcessCmdKey method:
This method is called during message preprocessing to handle command keys. Command keys are keys that always take precedence over regular input keys. Examples of command keys include accelerators and menu shortcuts.
You can override this method to mark the key as handled:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// if enter pressed, return 'true' to skip default handler
if ((keyData & Keys.Return) == Keys.Return)
return true;
return base.ProcessCmdKey(ref msg, keyData);
}
If you only want to ignore Enter when buttons are focused, you can use something like:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// if a button is focused AND enter pressed, skip default handler
if (this.ActiveControl is Button && (keyData & Keys.Return) == Keys.Return)
return true;
return base.ProcessCmdKey(ref msg, keyData);
}
This could be happening if your button is set as the AcceptButton property on the form. If that is the case, just clear that property.
In addition to the other answers You can add a KeyDown event handler to your form, in its KeyEventArgs there is a SuppressKeyPress property which will prevent your Keypress from being sent to the parent control.
also see this SO question for what the differences are between handled and SuppressKeyPress,
From the SuppressKeyPress Link:
Gets or sets a value indicating whether the key event should be passed on to the underlying control.
example:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Enter )
e.SuppressKeyPress = true;
}
my code is:
protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
{
if (keyData == (Keys.LWin | Keys.M))
{
MessageBox.Show("LWin M");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void Form1_Load(object sender, EventArgs e)
{
this.FormBorderStyle = FormBorderStyle.None;
}
but the MessageBox.Show("LWin M"); never work,who can help me?thanks
update
the
MessageBos.Show("LWin M");
just for test ,the real code is:
this.WindowState = FormWindowState.Minimized;
This doesn't have anything to do with the FormBorderStyle, your code doesn't work when you omit the Load event as well. The Win + M shortcut keystroke is used by Windows before it sends it to a program. You can easily tell what it does, it minimizes the active window.
Never use the Windows key for your own shortcuts, you'll need to stick with Ctrl, Alt and Shift. Even using unassigned shortcuts is a Bad Idea, that will break in the next Windows version.
it depends what you want
if you want to check if "M" or "LWin" is pressed than try the following part:
if (keyData == Keys.LWin || keyData == Keys.M)
I have tried the following:
private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
if ((Keys) e.KeyValue == Keys.Escape)
this.Close();
}
But it doesn't work.
Then I tried this:
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (e.KeyCode == Keys.Escape)
this.Close();
}
And still nothing's working.
The KeyPreview on my Windows Forms form properties is set to true... What am I doing wrong?
This will always work, regardless of proper event handler assignment, KeyPreview, CancelButton, etc:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == Keys.Escape) {
this.Close();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
You should just be able to set the Form's CancelButton property to your Cancel button and then you won't need any code.
Assuming that you have a "Cancel" button, setting the form's CancelButton property (either in the designer or in code) should take care of this automatically. Just place the code to close in the Click event of the button.
The accepted answer indeed is correct, and I've used that approach several times. Suddenly, it would not work anymore, so I found it strange. Mostly because my breakpoint would not be hit for ESC key, but it would hit for other keys.
After debugging I found out that one of the controls from my form was overriding ProcessCmdKey method, with this code:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// ...
if (keyData == (Keys.Escape))
{
Close();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
... and this was preventing my form from getting the ESC key (notice the return true). So make sure that no child controls are taking over your input.
You set KeyPreview to true in your form options and then you add the Keypress event to it. In your keypress event you type the following:
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 27)
{
Close();
}
}
key.Char == 27 is the value of escape in ASCII code.
You need add this to event "KeyUp".
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Escape)
{
this.Close();
}
}
You can also Trigger some other form.
E.g. trigger a Cancel-Button if you edit the Form CancelButton property and set the button Cancel.
In the code you treath the Cancel Button as follows to close the form:
private void btnCancel_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Abort;
}
By Escape button do you mean the Escape key? Judging by your code I think that's what you want. You could also try Application.Exit(), but Close should work. Do you have a worker thread? If a non-background thread is running this could keep the application open.
I have a form with a single text box on it. No other controls. Whenever I type the 'Enter' key or the 'Esc' key, the form functions as I desire; but I hear that horrible Windows error sound. The code looks similar to the following...
public class EntryForm: Form
{
public EntryForm()
{
}
private void EntryTextBox_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Enter)
{
// do some stuff
Hide(); // I've also used DialogResult = DialogResult.OK here
e.Handled = true;
}
else if(e.KeyCode == Keys.Escape)
{
Hide(); // I've also used DialogResult = DialogResult.Cancel here
e.Handled = true;
}
}
}
I can 'hack' it and make the noise stop by adding the following code to the form's constructor.
AcceptButton = new Button();
CancelButton = new Button();
As I stated this causes the sound to not play, but I think this is bad form; especially since I don't need a button on the form.
Anyone know why this is the behavior and if there is a cleaner way to stop the error sound from playing?
In the KeyDown event, set e.Handled = true and e.SuppressKeyPress = true.
There's a more "correct" fix, one that works regardless of how many controls you have and follows the Windows Forms design model. Paste this code into your form:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == Keys.Escape || keyData == Keys.Enter) {
this.Hide();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
This is too long a reply to Nobugz answer to fit in a comment. If you use Nobugz code as is :
the Form is going to be hidden no matter which control on the form is active and has keyboard input focus, and that is independent of whether the Form has the 'KeyPreview property set to 'true or 'false.
Here's what you need to do to make only a specific control (in this case a TextBox named 'textBox1) be hidden in the ProcessCmdKeys over-ride :
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (msg.HWnd == textBox1.Handle)
{
if (keyData == Keys.Escape || keyData == Keys.Enter)
{
textBox1.Hide();
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
Of course if you wanted to handle the case of multiple controls needing to be hidden, you could implement a 'switch statement or whatever to test the msg.HWnd against : note I make the assumption here that all controls that could have keyboard input will have a valid HWnd.
Some memory (vague) of a situation in which I used this technique, and a text input control somehow still had keyboard input focus ... when I did not intend for it to ... makes me want to add an additional test like this :
&& this.ActiveControl == textBox1
But, take that with a "grain of salt" since I can't be certain it is necessary.