I am working in a webform and have a form with a tab bar on it. Each tab has multiple text boxes in it. I have the tab indexes incremented, starting with 1 for each tab. I want to tab from tab to tab if the user hits the end of the form and hits tab.
I used the leave method and changed the tabs for my tab control the only problem is if I didn't hit tab and say I click to another control on that tab it will still shoot over to the new tab.
I figure a way to solve this would be to listen for the tab key press and if the key press is tab on leave then change the form to the other tab, I just can't seem to get it to work though. I have tried with keypress and keydown but neither will pick up that tab as a key. If I was to say click or hit start typing it will trigger the events but tab will not.
Any suggestions?
I have tried these and none of these event would even trigger.
private void afsiTxtDaysForTempOEpriceOverrides_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 11)
{
afsiTxtDaysForTempOEpriceOverrides_Leave(sender, e);
}
}
private void afsiTxtDaysForTempOEpriceOverrides_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == "11")
{
afsiTxtDaysForTempOEpriceOverrides_Leave(sender, e);
}
}
private void afsiChkSalesBaseCostUpdate_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 11)
{
afsiChkSalesBaseCostUpdate_Leave(sender, e);
}
}
private void afsiChkSalesBaseCostUpdate_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == 11)
{
afsiChkSalesBaseCostUpdate_Leave(sender, e);
}
}
EDIT: Found out that the page is using UltraWinTabControl from Infragistics so maybe this is causing some issues with the tabbing.
I ended up needing to override ProcessCmdKey now I face a new problem that is kind of related but not particular to this so I will add it as a comment if I get my answer.
private bool isTab = false;
private bool isShiftTab = false;
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Tab)
{
isTab = true;
ShiftTab.Append("Tab");
}
else
{
isTab = false;
}
return base.ProcessCmdKey(ref msg, keyData);
}
You will need to have the MultiLine property set to true, and AcceptsTab also set to true.
Or use e.KeyCode instead or e.KeyData, it worked for me
if (e.KeyCode == Keys.Tab | e.KeyData == Keys.Enter)
Related
I have a basic WinForms project where the user clicks a button. This opens another form as follows:
form2 myForm2 = new form2();
myForm2.ShowDialog();
Inside this new form, there are four buttons which represent values. The user presses the SPACE key to jump between buttons and the ENTER key to select one. When the user presses ENTER on a button I want the form to close. For this is I use 'this.Close()'. This works for absolutely fine with every key other than ENTER. I am using visual studio so I have inserted a break point and stepped over the code. The ENTER key is detected successully and I can step over the code 'this.Close()' but the window never closes. My code is a followed:
private void button1_KeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
// Change colour of the button you are on. This works fine.
}
else if (e.KeyCode == Keys.Enter)
{
this.Close();
// This will close the form with all keys other than the Enter key. Yet the enter key is
// successfully detected and the program enters this else if statement.
}
}
Any help is much appreciated, Thanks.
I'd override ProcessCmdKey() and make the space key act like the tab key to select the next control. Then just handle each the click event of each button like normal. The click handler for the buttons will fire when the user presses enter:
public partial class form2 : Form
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Button btn = this.ActiveControl as Button;
if (btn != null)
{
if (keyData == Keys.Space)
{
// possibly do something else with "btn"?...
this.SelectNextControl(btn, true, true, true, true);
return true; // suppress default handling of space
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void button1_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button1");
this.DialogResult = DialogResult.OK;
}
private void button2_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button2");
this.DialogResult = DialogResult.OK;
}
private void button3_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button3");
this.DialogResult = DialogResult.OK;
}
private void button4_Click(object sender, EventArgs e)
{
// possibly set some value?
Console.WriteLine("button4");
this.DialogResult = DialogResult.OK;
}
}
An alternative approach would be to also trap the enter key in ProcessCmdKey() like this:
public partial class Form2 : Form
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
Button btn = this.ActiveControl as Button;
if (btn != null)
{
if (keyData == Keys.Space)
{
Console.WriteLine("Space -> Tab");
// possibly do something else with "btn"?...
this.SelectNextControl(btn, true, true, true, true);
return true; // suppress default handling of space
}
else if (keyData == Keys.Enter)
{
Console.WriteLine("Enter in ProcessCmdKey() for " + btn.Name);
// possibly do something else with "btn"?...
this.Close();
// < or >
this.DialogResult = DialogResult.OK;
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
Looking into signature of the handler (object sender, PreviewKeyDownEventArgs e) apparently OP is already handling PreviewKeyDown event.
I reproduced and solved the problem.
The behavior is different when you open a Form using Show or ShowDialog. Everything works as expected with Show, but when using ShowDialog, to close the form in PreviewKeyDown, you need to use one of the following options:
private void button1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
e.IsInputKey = true;
this.Close();
// OR
// if (e.KeyData == Keys.Enter)
// this.BeginInvoke(new Action(() => this.Close()));
// OR first hide, then close, without calling BeginInvoke
// this.Hide();
// this.Close();
}
There should be something about model message loop. I didn't traced in details, but you may find the following links useful:
LocalModalMessageLoop in Application
CheckCloseDialog in Form
WMClose in Form
Just as a side note: If the Enter should be handled at form level, then setting AcceptButton of the form or overriding ProcessKeyDown or ProcessDialogKey of the form is the way to go.
I have a small projet in which I want several buttons to behave differently when Clicked or Ctrl+Clicked. To achieve that, each of those buttons has this kind of function attached to their Click() event :
private void Button1_Click(object sender, EventArgs e)
{
int value = 10 //default value
bool boool = false;
if (ModifierKeys == Keys.Control)
{
using (var form = new NUP_Popup(0, value, value, "maximum ?"))
{ //creates a simple window that allows user to change the value of 'value'
form.ShowDialog();
if (form.DialogResult == DialogResult.OK)
{
value = form.retVal;
boool = true;
}
else return;
}
}
//do stuff here, either with default or user value
}
Now, Clicking or Ctrl+Clicking behaves as intended with this function. My problem is that this behaviour doesn't apply when my buttons are activated using the Enter key : Enter key alone triggers the "normal" behaviour but Ctrl+Enter does nothing (button is not activated).
I already have overriden the ProcessDialogKey() function to close the window when Escape is pressed, so I thought I could use it to make Enter key presses trigger the Click() event function :
protected override bool ProcessDialogKey(Keys keyData) //Allows quit when Esc is pressed
{
if (Form.ModifierKeys == Keys.None && keyData == Keys.Escape)
{
this.Close();
return true;
}
if (keyData == Keys.Return)
{
this.OnClick(new EventArgs());
}
return base.ProcessDialogKey(keyData);
}
And that's where I'm stuck. Of course this doesn't do anything but I don't really have an idea of what to type inside my second condition to make it work.
Maybe I'm using the wrong approach ? Can someone point me in the right direction to do it ?
Assuming you placed a Label with ID Label1 and a button with ID Button1, following will do:
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Button Clicked";
if (Control.ModifierKeys == Keys.Control) label1.Text += " with Ctrl";
}
private void button1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '\n') button1_Click(sender, new EventArgs());
}
to your solution, simply add a KeyPress event to your Button1 and apply following code inside the keypress event Button1_KeyPress:
if (e.KeyChar == '\n') Button1_Click(sender, new EventArgs());
Okay, so I finally found a working solution by adding this to my overriden ProcessDialogKey() method :
if (keyData == (Keys.Enter | Keys.Control))
{
(this.ActiveControl as Button).PerformClick();
}
I don't know if it qualifies as "clean" code, but it has the merit of fulfilling my 2 requirements : making Ctrl+Enter function as Ctrl+Click without having to declare 2 methods per Button.
I found a solution that enables you to either click Enter or Ctrl+Enter:
private void txtIP_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '\n' || e.KeyChar == '\r') btnStart_Click(sender, new EventArgs());
}
I have a MaskedTextBox that formats text to look like (###) ###-####
After entering the first 3 digits, they like to press "TAB" to the next set. Unfortunately by pressing TAB, they are in the next field.
So my boss asked me to modify the application so that the users remain in the same field but the cursor is in the next group.
private void maskedTextBoxHomePhone_KeyPress(object sender, KeyPressEventArgs e)
{
MaskedTextBox mtb = (MaskedTextBox)sender;
if (e.KeyChar == (char)Keys.Tab)
{
if (mtb.TextLength == 3)
{
mtb.SelectionStart = 4;
}
}
}
I've also tried
private void maskedTextBoxHomePhone_KeyDown(object sender, KeyEventArgs e)
{
MaskedTextBox mtb = (MaskedTextBox)sender;
if (e.KeyCode == Keys.Tab)
{
if (mtb.TextLength == 3)
{
mtb.SelectionStart = 4;
}
}
}
Tabs have a special meaning, that will cause the focus to change, so the event handler won't get called.
You could work around this by using the Leave event of a text box and counting the textlength that you have stored in some local variable:
private void maskedTextBoxHomePhone_Leave(object sender, EventArgs e)
{
if (_mtbTextLength == 3) { //change selection start and goes back to masked text box }
}
Anyway, actually I would try to convince my boss otherwise. Do you
really need this? Tabs are always used to change fields, you can get
your users confused.
Another option would be to change the Tab behaviour by overriding the ProcessCmdKey:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Tab)
{
//Do something
}
}
I would like to perform some actions when the user presses Ctrl + K on a textbox.
private void subject_TextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.K)
MessageBox.Show("!");
}
Nothing happens when I run it.
When I debug I can see that e.Control is true (this means I pressed Ctrl) but the e.KeyCode is not equivalent to K.
Any ideas?
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Control | Keys.K) && focusedTextbox == subject_TextBox)
{
//Some Code
}
}
private TextBox focusedTextbox = null;
private void subject_TextBox_KeyDown(object sender, KeyEventArgs e)
{
MethodName(e.KeyCode)
}
private void MethodName(Keys keys)
{
focusedTextbox = (TextBox)sender;
}
Use this code, this should work i have tested it myself and it will work, you will want to run the 'MethodName' method in each textbox, or if you can find a better way to change the 'focusedTextBox' field then do that hope this helped.
In the KeyDown event, you just ask for the 'state' of the keyboard.
You might want to check out this topic:
Capture multiple key downs in C#
Really don't know what is the problem reason.
May the event is fired as soon as the Ctrl is pressed, without waiting to the K to be pressed as well.
However, when I use the same code in the TextBox_KeyUp event, it works fine.
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.