I have a Windows.Form and there overriden ProcessCmdKey. However, this works with all of the F-Keys except for F10. I am trying to search for the reason why ProcessCmdKey is not called when I press F10 on my Form.
Can someone please give me a tip as to how I can find the cause?
Best Regards, Thomas
Windows treats F10 differently. An explanation is given in the "Remarks" section here on MSDN
I just tested this code with Windows Forms on .NET 4 and I got the message box as expected.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.F10)
{
MessageBox.Show("F10 Pressed");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
May be I got your problem, so trying to guess:
Did you set KeyPreview property of your WindowsForm to true ?
This will enable possiblity to WindowsForm proceed keypress events before they pump to the control that holds the focus on UI in that precise moment.
Let me know if it works, please.
Regards.
In my case I was trying to match e.key to system.windows.input.key.F10 and it didn't not work (althougth F1 thru F9 did)
Select Case e.Key
Case is = Key.F10
... do some stuff
end select
however, I changed it to
Select Case e.Key
Case is = 156
... do some stuff
end select
and it worked.
If running into this issue in a WPF app, this blog post shows how to capture the F10 key:
private void Window_KeyDown(object sender, KeyEventArgs e)
{
if (e.SystemKey == Key.F10)
{
YourLogic(e.SystemKey);
}
switch (e.Key)
{
case Key.F1:
case Key.F2:
}
}
Right, and as this is a special key you must add
e.Handled = true;
it tells the caller that you handled it.
So, your code could look like:
switch (e.Key)
...
case Key.System:
if (e.SystemKey == Key.F10)
{
e.Handled = true;
... processing
}
Related
My form has several buttons such as "Scan" and "Exit". I have seen in many programs where buttons will be useable by keypress. Lots of times the unique key to press is underlined in the text on the button (I don't know how to use an underline option on these forums!). I went to the form and added a keypress event:
private void Form1_KeyPress(object sender, KeyPressEventArgs key)
{
switch (key.ToString())
{
case "s":
Run_Scan();
break;
case "e":
Application.Exit();
break;
default:
MessageBox.Show("I'll only accept 's' or 'e'.");
break;
}
}
But then pressing 's' or 'e' on the form doesn't do anything. Not sure where I'm going wrong here?
Overriding ProcessKeyCommand will accept input from anywhere on the form. You should add a modifier however, since pressing 's' or 'e' in a textbox, for example, will also trigger the action.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
switch (keyData)
{
case Keys.S:
Run_Scan();
break;
case Keys.E:
Application.Exit();
break;
default:
MessageBox.Show("I'll only accept 's' or 'e'.");
break;
}
return base.ProcessCmdKey(ref msg, keyData);
}
I think you are looking for what are called Access Keys: There are defined by the '&' symbol.
Get rid of your KeyPress event handler. You will not need it.
Change the text of your buttons to "&Scan" and "&Exit".
Also: Here are some guidelines about using access keys in windows applications.
key.ToString() is the wrong method to call. You want to access the key property: key.KeyChar.
See the MSDN here for more info on the KeyPressEventArgs, which includes examples.
You can put an ampersand in front of the letter you want to make a hot key for the button in the Text property of your button. You can set the Text property from the Properties pane in the form designer, or you can set it programmatically. Below is an example of programmatic approach.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// make the 'B' key the hot key to trigger the key press event of button1
button1.Text = "&Button";
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("B");
}
}
In c# I am using this code to imediately react on press keys.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.NumPad1)
{
button_1.PerformClick();
return true;
}
}
I defined this for all numpad numbers and it WORKS great. But I am not able to define this function for (/,,-,+) on NumPad. I have read some topics with solution throw keyCode...it was like if(e.keykode==46) than something. But it worked after i pressed enter. I need imediatly reaction no keys +,-,,/. Can somebody help me pls?
You're looking for Keys.Add, Keys.Divide, Keys.Multiply, and Keys.Subtract, I believe.
To use them, that would be exactly the same as you have already done:
if(keyData == Keys.Multiply) { // or Add, Divide, or Subtract
btnMultiply.PerformClick(); // Or whatever else you want to do here.
}
Do you want this to occur in an event like so:
private void txtText_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Add)
{
//do something
}
}
Something like this should work for you.
I'm facing a little problem I can't seem to solve.
The problem is in an WinForm I have several containers (TabControls, Panels, ...).
The Tab-order within the controls work fine (of course). But now a customer asked to change the taborder to jump from a textbox in the first container (current tabindex 0,0,1) to a control in another container (current tabindex 0,1,0,1).
My first approach was setting the tabindex of the second to 0,0,1,1 but with no effect. The tab jumps from 0,0,1 to 0,0,2.
I tried a couple of other combinations too but with no result.
Can anybody provide me with hints how I might solve this problem?
PS: the 0,0,0 stands for the containers that contain the control just in case this is not clear
You could work with the Leave event of that Control, and manually set focus in the code behind to do this.
private void textBox1_Leave(object sender, System.EventArgs e)
{
textBox2.Focus();
}
If you want to use the TAB key, it's better to not use the Leave event
It will create some bad redirections if you change with your mouse for example.
Better override ProcessCmdKey
Here is a good solution :
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
bool baseResult = base.ProcessCmdKey(ref msg, keyData);
//if key is tab and TextBox1 is focused then jump to TextBox2
if (keyData == Keys.Tab && TextBox1.Focused)
{
TextBox2.Focus();
return true;
}
else if (keyData == Keys.Tab && TexBox2.Focused)
{
TextBox3.Focus();
return true;
}
return baseResult;
}
Hope it helped.
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.
I'm looking for a best way to implement common Windows keyboard shortcuts (for example Ctrl+F, Ctrl+N) in my Windows Forms application in C#.
The application has a main form which hosts many child forms (one at a time). When a user hits Ctrl+F, I'd like to show a custom search form. The search form would depend on the current open child form in the application.
I was thinking of using something like this in the ChildForm_KeyDown event:
if (e.KeyCode == Keys.F && Control.ModifierKeys == Keys.Control)
// Show search form
But this doesn't work. The event doesn't even fire when you press a key. What is the solution?
You probably forgot to set the form's KeyPreview property to True. Overriding the ProcessCmdKey() method is the generic solution:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == (Keys.Control | Keys.F)) {
MessageBox.Show("What the Ctrl+F?");
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
On your Main form
Set KeyPreview to True
Add KeyDown event handler with the following code
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.N)
{
SearchForm searchForm = new SearchForm();
searchForm.Show();
}
}
The best way is to use menu mnemonics, i.e. to have menu entries in your main form that get assigned the keyboard shortcut you want. Then everything else is handled internally and all you have to do is to implement the appropriate action that gets executed in the Click event handler of that menu entry.
You can even try this example:
public class MDIParent : System.Windows.Forms.Form
{
public bool NextTab()
{
// some code
}
public bool PreviousTab()
{
// some code
}
protected override bool ProcessCmdKey(ref Message message, Keys keys)
{
switch (keys)
{
case Keys.Control | Keys.Tab:
{
NextTab();
return true;
}
case Keys.Control | Keys.Shift | Keys.Tab:
{
PreviousTab();
return true;
}
}
return base.ProcessCmdKey(ref message, keys);
}
}
public class mySecondForm : System.Windows.Forms.Form
{
// some code...
}
If you have a menu then changing ShortcutKeys property of the ToolStripMenuItem should do the trick.
If not, you could create one and set its visible property to false.
From the main Form, you have to:
Be sure you set KeyPreview to true( TRUE by default)
Add MainForm_KeyDown(..) - by which you can set here any shortcuts you want.
Additionally,I have found this on google and I wanted to share this to those who are still searching for answers. (for global)
I think you have to be using user32.dll
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x0312)
{
/* Note that the three lines below are not needed if you only want to register one hotkey.
* The below lines are useful in case you want to register multiple keys, which you can use a switch with the id as argument, or if you want to know which key/modifier was pressed for some particular reason. */
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF); // The key of the hotkey that was pressed.
KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF); // The modifier of the hotkey that was pressed.
int id = m.WParam.ToInt32(); // The id of the hotkey that was pressed.
MessageBox.Show("Hotkey has been pressed!");
// do something
}
}
Further read this http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/
Hans's answer could be made a little easier for someone new to this, so here is my version.
You do not need to fool with KeyPreview, leave it set to false. To use the code below, just paste it below your form1_load and run with F5 to see it work:
protected override void OnKeyPress(KeyPressEventArgs ex)
{
string xo = ex.KeyChar.ToString();
if (xo == "q") //You pressed "q" key on the keyboard
{
Form2 f2 = new Form2();
f2.Show();
}
}
In WinForm, we can always get the Control Key status by:
bool IsCtrlPressed = (Control.ModifierKeys & Keys.Control) != 0;
The VB.NET version of Hans' answer.
(There's a ProcessCmdKey function template in Visual Studio.)
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If (keyData = (Keys.Control Or Keys.F)) Then
' call your sub here, like
SearchDialog()
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
End Class