I have a WinForms form with a TableLayoutPanel on it.
In this TableLayoutPanel, I have 2 Button controls.
I press one of these buttons.
Then I press the Up or Down arrow (↑ ↓) on the keyboard.
The focus jumps from one button to the other.
I don't want this behaviour.
Setting the TableLayoutPanel's "TabStop" to "False" doesn't help.
I would instead like to intercept the event and set the focus to another control manually.
However, I didn't find the event that I need to intercept.
How could I disable this jumping by arrow keys?
Which event would I have to intercept to set the focus to another control?
Thank you!
You can handle PreviewKeyDown event of all the buttons using a single handler and check if the pressed key is an arrow key, set e.IsInputKey = true and prevent focus change:
private void button1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
var keys = new[] { Keys.Left, Keys.Right, Keys.Up, Keys.Down };
if (keys.Contains(e.KeyData))
e.IsInputKey = true;
}
You can read about the behavior and the solution in Remarks section of the PreviewKeyDown documentations.
The behavior is in fact implemented in ProcessDialogKey method of the container control (you can see source code) and you can also prevent it by overriding ProcessDialogKey of the Form, like this:
protected override bool ProcessDialogKey(Keys keyData)
{
var keys = new[] { Keys.Left, Keys.Right, Keys.Up, Keys.Down };
if (keys.Contains(keyData))
return true;
else
return base.ProcessDialogKey(keyData);
}
Related
I have a form with a menuStrip control (the layout VerticalStackWithOverflow). How could I enable the arrow keys to navigate this menu? Also how could I get the event of pressing Enter on the selected item?
I dont particularly know about that control, but the arrows and Enter dont work with TextBox either. The default key form moving between controls is Tab. You have to override the keypress event and add that feature by invoking SelectNextControl method something like this(in this case Enter)
private void keypressed(Object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Return)
{
this.SelectNextControl((Control) sender, true, true, true, true);
}
}
I have a (.NET 3.5) winform with a datagridview on which I added an event on checkboxes in the gridview like this. That post doesn't take into account that people can also use spacebar to toggle the checkbox, and because there is no CellKeyUp event like there is a CellMouseUp event, I enabled KeyPreview on the form and added this code to prevent toggling with the spacebar:
private void BulkOrderAddressDifferencesForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
e.Handled = true;
e.SuppressKeyPress = true;
}
}
That works mostly, but there is a scenario in which the event is still handled, even though the debugger shows e.Handled is set to true.
If I click on a checkbox, then 1, then 2, I can toggle the checkbox with the space bar again. I have no idea why this happens, nor do I know how to fix it.
You can override Form's ProcessCmdKey method:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Space && checkBox1.Focused)
{
//instead of checkBox1.Focused condition, you check if your DataGridView contains focus and active cell is of checkBox type
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
If the goal is to always react immediately when the check is changed, rather than preventing the use of the spacebar (Unless I'm mistaken, the problem is that the cellmouseup approach doesn't include (un)checking with space, rather than the goal is that space shouldn't be used at all? ), you could use the celldirtychanged approach instead of cellmouseup to catch both
//grid.CurrentCellDirtyStateChanged += grid_CurrentCellDirtyStateChanged;
void grid_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (grid.IsCurrentCellDirty)
{
var cell = grid.CurrentCell;
if (cell is DataGridViewCheckBoxCell)
{
grid.EndEdit();
//you could catch the cellvaluechanged event (or a bound listchanged event), or handle the change immediately here, e.g.:
//Console.WriteLine("{0} value changed to {1}", cell.OwningColumn.HeaderText, cell.Value);
}
}
}
How about the DataGridView.EditMode Property which
Gets or sets a value indicating how to begin editing a cell.
where
The default is EditOnKeystrokeOrF2.
and
All DataGridViewEditMode values except for EditProgrammatically allow a user to double-click a cell to begin editing it.
You have several options to choose from the DataGridViewEditMode Enumeration
EditOnEnter - Editing begins when the cell receives focus. This mode is useful when pressing the TAB key to enter values across a row, or when pressing the ENTER key to enter values down a column.
EditOnF2 - Editing begins when F2 is pressed while the cell has focus. This mode places the selection point at the end of the cell contents.
EditOnKeystroke - Editing begins when any alphanumeric key is pressed while the cell has focus.
EditOnKeystrokeOrF2 - Editing begins when any alphanumeric key or F2 is pressed while the cell has focus.
EditProgrammatically - Editing begins only when the BeginEdit method is called.
Update for DataGridViewCheckBoxCell:
It turns out that the DataGridViewEditMode does not work for the DataGridViewCheckBoxColumn.
In this case you can create your own DataGridViewCheckBoxColumn & DataGridViewCheckBoxCell. This allows you to override the cell's OnKeyUp event handler and reset the EditingCellFormattedValue if Space was pressed.
public class MyCheckBoxColumn : DataGridViewCheckBoxColumn
{
public MyCheckBoxColumn()
{
CellTemplate = new MyCheckBoxCell();
}
}
public class MyCheckBoxCell : DataGridViewCheckBoxCell
{
protected override void OnKeyUp(KeyEventArgs e, int rowIndex)
{
if (e.KeyCode == Keys.Space)
{
e.Handled = true;
if (EditingCellValueChanged)
{
// Reset the value.
EditingCellFormattedValue = !(bool)EditingCellFormattedValue;
}
}
else
{
base.OnKeyUp(e, rowIndex);
}
}
}
After you rebuild your project the new column should appear in the designer:
i am working with DataGridView trying to provide specific utility to my user...
what i want to do is when some key is presses instead of the normal function that the key was supposed to perform like updown arrows and page up down keys etc i want to stop the default action
like when on a selected row, datagrid in selectfullrow, when down arrow is press it shouldn't change the row selection or goto the next row
You should handle the KeyDown event and set the e.Handled to true to disable the default action:
private void dataGridView1_KeyDown(object sender, KeyEventArgs e) {
e.Handled = e.KeyCode == Keys.Down;
}
I wanted to handle Arrow key press event on the slider control. I tried googling for it but almost all the links gave me information about handling it on the windows(overrideing WndProc or ProcessCmdKey).The KeyDwon and Key Up events aren't fired for the Arrow press. How can i handle it?
Look here.
Here's a short quote from there:
Certain keys, such as the TAB, RETURN, ESC, and arrow keys are handled by controls automatically. To have these keys raise the KeyDown event, you must override the IsInputKey method in each control on your form. The code for the override of the IsInputKey would need to determine if one of the special keys is pressed and return a value of true. Instead of overriding the IsInputKey method, you can handle the PreviewKeyDown event and set the IsInputKey property to true. For a code example, see the PreviewKeyDown event.
And here's the code sample from the PreviewKeyDown event from here (PreviewKeyDown):
// By default, KeyDown does not fire for the ARROW keys
void button1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Down:
case Keys.Up:
if (button1.ContextMenuStrip != null)
{
button1.ContextMenuStrip.Show(button1,
new Point(0, button1.Height), ToolStripDropDownDirection.BelowRight);
}
break;
}
}
// PreviewKeyDown is where you preview the key.
// Do not put any logic here, instead use the
// KeyDown event after setting IsInputKey to true.
private void button1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Down:
case Keys.Up:
e.IsInputKey = true;
break;
}
}
I'm presuming you're using a track bar control when you say slider control? If not, then this answer probably won't help.
Anyway, you need to set the OnKeyDown event for your track bar control. Something as simple as the following code will allow the user to use the left and right arrows to move from side to side.
private void trackBar1_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == Keys.Right) && (trackBar1.Value < trackBar1.Maximum))
trackBar1.Value += 1;
if ((e.KeyCode == Keys.Left) && (trackBar1.Value > trackBar1.Maximum))
trackBar1.Value -= 1;
}
You simply need to detect a key press, and then decide whether it's a left or right arrow, and then what to do from there.
I've tried it and the left and right arrows do trigger it for me. Again, if you're using a different slider control (there isn't any control called the slider control, so I'm assuming track bar) then it may be different.
My ActiveX control contains various shapes which are drawn. CTRL-A is used in the control to select all the objects. Similarly CTRL-C to copy, CTRL-V to paste etc.
However, when I insert this control within a Windows form in a .Net application, it does not receive these keyboard events. I tried adding a PreviewKey event, and this does allow certain keystrokes to be sent e.g. TAB, but not these modified keys.
Does anybody know how to redirect modified keystrokes to a user control?
Thanks.
It's possible that the ActiveX control doesn't have focus and is therefore not receiving the key events. You may want to handle the key events at the form level and then call the appropriate methods on your ActiveX control. If you set the KeyPreview property of your form to true your form will receive the key events for all controls on the form. That way, your shortcuts should work no matter what control currently has focus. Here is a quick example you can play with to test this out. Create a new form with several different controls on it and modify the code like so:
public Form1()
{
InitializeComponent();
KeyPreview = true; // indicates that key events for controls on the form
// should be registered with the form
KeyUp += new KeyEventHandler(Form1_KeyUp);
}
void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.Modifiers == Keys.Control)
{
switch (e.KeyCode)
{
case Keys.A:
MessageBox.Show("Ctrl + A was pressed!");
// activeXControl.SelectAll();
break;
case Keys.C:
MessageBox.Show("Ctrl + C was pressed!");
// activeXControl.Copy();
break;
case Keys.V:
MessageBox.Show("Ctrl + V was pressed!");
// activeXControl.Paste();
break;
}
}
}
No matter what control has focus when you enter the key combinations, your form's Form1_KeyUp method will be called to handle it.
You need to trap the keys and override the ProcessCmdKey method.
class MyDataGrid : System.Windows.Forms.DataGrid
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
...........
}
}
http://support.microsoft.com/kb/320584
KeyPreview is just the wrong method. Try using KeyUp or KeyDown, like this:
private void ControlKeyTestForm_KeyUp(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.A)
this.label1.Text = "Ctrl+A pressed";
}
If you want the containing form to deal with shortcut keys remember to set the KeyPreview property on the form to true then set the KeyDown or KeyUp handlers in the form.
Use Control.ModifierKeys Property to check for Modifier keys.
For example, to check for shift key,
try if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) { }
Full example here:
http://msdn.microsoft.com/en-us/library/aa984219%28VS.71%29.aspx