Create a Cross-Container Tab Index - c#

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.

Related

How do I bind a keyboard key to a label

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);
}

DateTimePicker subfield selection

So I've been tasked with making a custom data-bindable nullable DateTimePicker. I have it working great. Only issue is, the users don't want to use the arrow keys to navigate the control. They want to use the tab key. However, if you press the tab key when in the DateTimePicker it will leave to the next control. I've worked around this by utilizing the below code. Now the issue is, I can't leave the control, lol. I don't know how to check which subfield I'm currently on so I know if I'm on the far left or far right subfield to just leave the control instead of continuing to cycle through. Anyone have any tips? It would be greatly appreciated. Thanks!
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (!this.ShowCheckBox || (this.ShowCheckBox && this.Checked))
{
if (keyData == Keys.Tab)
{
// **THIS IS WHERE I'M STUCK
// if not on far right subfield do below
SendKeys.Send("{RIGHT}");
return true;
}
else if (keyData == (Keys.Shift | Keys.Tab))
{
// **THIS IS WHERE I'M STUCK
// if not on far left subfield do below
SendKeys.Send("{LEFT}");
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}

F10 Key is not caught

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
}

C# Tab switching in TabControl

Iam facing such problem, which I find hard to overcome. In WinForms I got a TabControl with n TabPages. I want to extend the Ctrl+Tab / Ctrl+Shift+Tab switching. so I wrote some code which works fine as long as the focus is on TabControl or on the Form. When application focus is INSIDE of TabPage (for example on a button which is placed inside of TabPage), while pressing Ctrl+Tab, my code is ignored and TabControl skips to TabPage on his own (avoiding my code).
Anyone idea ?
You need to derive from TabControl and override ProcessCmdKey, virtual method in order to override the Ctrl-Tab behavior.
Example:
public class ExtendedTabControl: TabControl
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Control | Keys.Tab))
{
// Write custom logic here
return true;
}
if (keyData == (Keys.Control | Keys.Shift | Keys.Tab))
{
// Write custom logic here, for backward switching
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
TabControl has fairly unusual processing to handle the Tab key. It overrides the ProcessKeyPreview() method to detect Ctrl/Shift/Tab, then implements the tab selection in its OnKeyDown() method. It does this so it can detect the keystroke both when it has the focus itself as well as any child control. And to avoid stepping on custom Tab key processing by one of its child controls. You can make it work by overriding ProcessCmdKey() but then you'll break child controls that want to respond to tabs.
Best thing to do is to override its OnKeyDown() method. Add a new class to your project and paste the code shown below. Compile. Drop the new tab control from the top of the toolbox onto your form.
using System;
using System.Windows.Forms;
class MyTabControl : TabControl {
protected override void OnKeyDown(KeyEventArgs e) {
if (e.KeyCode == Keys.Tab && (e.KeyData & Keys.Control) != Keys.None) {
bool forward = (e.KeyData & Keys.Shift) == Keys.None;
// Do your stuff
//...
}
else base.OnKeyDown(e);
}
}
Beware that you also ought to consider Ctrl+PageUp and Ctrl+PageDown.

How to Stop Window Error Sound When Typing 'Enter' or 'Esc'

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.

Categories