Capturing KeyDown and KeyUp events for cursor keys - c#

I want to move some graphics in a winfor application. To do this I need to know if any of the cursor keys are being pressed. I tried to override ProcessCmdKey but no success.
Any tips/ideas how to implement this?
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
switch (keyData)
{
case Keys.Left:
// while Left is down
// call this method repeadetdly
buttonGoLeft();
// when key is up stop calling this method
// and check for other keys
return true;
//Other cases
}
}

this works!
using System.Windows.Forms;
namespace WindowsFormsApplication5
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
KeyPreview = true;
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
switch (keyData)
{
case Keys.Left:
// while Left is down
// call this method repeadetdly
MessageBox.Show("its left", Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
// when key is up stop calling this method
// and check for other keys
return true;
default:
return false;
}
}
}
}

Related

How to override ShortcutsEnabled for textbox

How should I override ShortcutsEnabled property of textbox to accept some of shortcuts and reject others?
clearify: I tried to create a component base on textbox and also changed its context menu to a more beautiful one. in order to show my context menu I tested 2 methods first using contextMenu/contextMenuStrip property, but it has a problem (if user presses the right mouse button and move out and leave button, this method won't work) other way was using ShortcutsEnabled property that works great. but I like to shortcuts like ctrl+C ,... remain active. here says that it is possible to override this property to specify shortcuts, but I can not find any example about how it can be done.
Edit: I did not find good way to do this. but for solving my problem (disable context menu while shortcuts are enable) I find a solution base on links that #AliTheOne and #x5657 provided. you can catch 0x007B message in WndProc , the good thing is you can still catch right mouse button click in mouse down event and use it for showing custom context menu and normal context menu will not show. Note that this would enable all normal shortcuts.
protected override void WndProc(ref Message m)
{
if (m.Msg != 0x007B)
{
base.WndProc(ref m);
}
}
and
void textBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
//show custom context menu
}
}
Based on the code for textbox I think you need to override ProcessCmdKey.
The base ShortcutsEnabled setter sets which shortcuts are enabled in a shortcutsToDisable field, but unfortunately that's private, so you'd have to "roll you own" implementation.
ProcessCmdKey would look something like this:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (this.ShortcutsEnabled == false) {
foreach (int shortcutValue in shortcutsToDisable) {
if ((int)keyData == shortcutValue ||
(int)keyData == (shortcutValue | (int)Keys.Shift)) {
return true;
}
}
}
//
// There are a few keys that change the alignment of the text, but that
// are not ignored by the native control when the ReadOnly property is set.
// We need to workaround that.
if (textBoxFlags[readOnly]) {
int k = (int)keyData;
if (k == (int)Shortcut.CtrlL // align left
|| k == (int)Shortcut.CtrlR // align right
|| k == (int)Shortcut.CtrlE // align centre
|| k == (int)Shortcut.CtrlJ) { // align justified
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
Base on this: TextBoxBase.cs
You can do this: we want to set alignment by Ctrl+R and Ctrl+L
If you want to disable any built-in shortcuts Like Ctrl+Z and assign new method to it just delete it from public override bool ShortcutsEnabled {} and put it in protected override bool ProcessCmdKey(..) and switch..case
public class MyTextBox : TextBox
{
private static readonly int _readOnly = BitVector32.CreateMask();
private static readonly int _shortcutsEnabled = BitVector32.CreateMask(_readOnly);
private static int[] _shortcutsToDisable;
private BitVector32 _textBoxFlags;
public override bool ShortcutsEnabled
{
get { return _textBoxFlags[_shortcutsEnabled]; }
set
{
if (_shortcutsToDisable == null)
{
_shortcutsToDisable = new int[]
{
(int) Shortcut.CtrlZ,(int) Shortcut.CtrlC, (int) Shortcut.CtrlX,
(int) Shortcut.CtrlV, (int) Shortcut.CtrlA, (int) Shortcut.CtrlL, (int) Shortcut.CtrlR,
(int) Shortcut.CtrlE, (int) Shortcut.CtrlY, (int) Keys.Control + (int) Keys.Back,
(int) Shortcut.CtrlDel, (int) Shortcut.ShiftDel, (int) Shortcut.ShiftIns, (int) Shortcut.CtrlJ
};
}
_textBoxFlags[_shortcutsEnabled] = value;
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (_shortcutsToDisable == null)
{
return false;
}
var k = (int)keyData;
switch (k)
{
case (int)Shortcut.CtrlL:
TextAlign=HorizontalAlignment.Left;
break;
case (int)Shortcut.CtrlR:
TextAlign = HorizontalAlignment.Right;
break;
default:
return base.ProcessCmdKey(ref msg, keyData);
}
return true;
}
}

How to handle alt-key events on a form with c#?

I have the following code that has worked twice and then quit working altogether after I modified the underlying form controls. I can't see what's wrong with the code or why changing the underlying controls would matter to the form.
What do I have to do to get ProcessCmdKey to work reliably?
namespace xyz
{
public partial class DaysNHours : Form
{
public DaysNHours()
{
this.KeyPreview = true;
InitializeComponent();
}
// Detect alt-key presses directed to checkboxes and time boxes
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);
}
}
}

Override KeyDown from another class C#

I have a form that creates a class. This class processes events that are fired on the form. The problem is I am trying to use the KeyDown event, but it isn't working because there are buttons on the form and they are capturing the KeyDown. I found the solution on another post was to override the ProcessCmdKey. The problem is I don't know how to override a method from inside another class. Can anyone tell me how I can capture all KeyDown events from inside my other class?
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Left)
{
MoveLeft(); DrawGame(); DoWhatever();
return true; //for the active control to see the keypress, return false
}
else if (keyData == Keys.Right)
{
MoveRight(); DrawGame(); DoWhatever();
return true; //for the active control to see the keypress, return false
}
else if (keyData == Keys.Up)
{
MoveUp(); DrawGame(); DoWhatever();
return true; //for the active control to see the keypress, return false
}
else if (keyData == Keys.Down)
{
MoveDown(); DrawGame(); DoWhatever();
return true; //for the active control to see the keypress, return false
}
else
return base.ProcessCmdKey(ref msg, keyData);
}
The easiest way to do this would be to expose the KeyDown from Button on the containing form.
class MyForm : Form {
Button m_button;
public event KeyEventHandler ButtonKeyDown;
public MyForm() {
m_button = ...;
m_button.KeyDown += delegate (object, e) {
KeyEventHandler saved = ButtonKeyDown;
if (saved != null) {
saved(object, e);
}
};
}
}
Now the calling code can simple hook into the MyForm::ButtonKeyDown event
I'm not sure how you're wiring up the events with your class, but if you set the KeyPreview property of the form to True, you can grab a hold of the event there and then pass it along to your class that is processing the events. So even when the button has the focus, the KeyDown will fire the event on the form.
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
... Invoke your class
}

Change focus control when press enter key

I have a windows form, i need when user press Enter set focus to next control.
Any idea how to achive this
(without using Key Press events)
You can catch the KeyPreview of your form. Set KeyPreview to true in the constructor and then you can use this:
protected override bool ProcessKeyPreview(ref Message m)
{
if (m.Msg == 0x0100 && (int)m.WParam == 13)
{
this.ProcessTabKey(true);
}
return base.ProcessKeyPreview(ref m);
}
You can use ProcessCmdKey checking if keyData contains the Enter Key then using the SelectNextControl Method to set your focus.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData.HasFlag(Keys.Enter))
{
SelectNextControl(ActiveControl,true,true,true,true);
return true; //Stops the beeping
}
return base.ProcessCmdKey(ref msg, keyData);
}
If you dont want to use key press events you will have to override ProcessCmdKey
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Return)
{
MessageBox.Show("You pressed the Enter key");
}
return base.ProcessCmdKey(ref msg, keyData);
}

c# datagridview key handling

I use DataGridView, and in some places I add control to it (e.g. textbox, combobox)
dataGridView1.Controls.Add(comboBox);
comboBox.Focus();
The problem is that using this control, and than commiting choice by using ENTER cause the DataGridView to "handle" the key -> after clickng enter instead of choosing sth from combobox, the selection in datagridview changes( moves to next cell).
I use sth like :
public class MyDataGridView:DataGridView
{
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if(keyData == Keys.Enter)
{
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
But it cause that datagridview and combobox doesn't answer to ENTER, and other keys...
Additional infromation: I must use ComboBox class, instead of DataGridViewCombobox. Can anyone help me how to handle ENTER in my comobox?
Try:
if((keyData == Keys.Enter) && (MyComboBox.Focused))
so DataGridView responds to ENTER except when your control is focused.
I am not sure the following code fits your situation, but maybe you could try something like:
public class MyDataGridView:DataGridView
{
public ComboBox MyComboBox { get; set; } //in case you had no other way to refer to it
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if((keyData == Keys.Enter) && (MyComboBox.Focused))
{
//commit choice logic
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
}
and from your form, if it needs, set the reference to your ComboBox:
dataGridView1.Controls.Add(comboBox);
dataGridView1.MyComboBox = comboBox;
comboBox.Focus();

Categories