C# Windows Forms KeyDown event fires continiously [duplicate] - c#

This question already has answers here:
how not to allow multiple keystokes received at one key press?
(3 answers)
Closed 6 years ago.
In a Windows forms application I'm trying to execute some function when I press a hotkey using Form's KeyDown event. The problem is that when I keep the hotkey pressed the event fires continuously.
I just want to execute some function at the first time I press the button and another function when I release it.
Here is the code I used to accomplish this operation:
bool isPressed_Num7 = false;
bool isPressed_Num9 = false;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.NumPad7 && !isPressed_Num7)
{
isPressed_Num7 = true;
Console.WriteLine("Keydown 7");
}
if (e.KeyData == Keys.NumPad9 && isPressed_Num9)
{
isPressed_Num9 = true;
Console.WriteLine("Keydown 9");
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.NumPad7)
{
isPressed_Num7 = false;
Console.WriteLine("Keyup 7");
}
if (e.KeyData == Keys.NumPad9)
{
isPressed_Num9 = false;
Console.WriteLine("Keyup 9");
}
}
I'm going to use a bunch of hotkeys. So what I'm asking is there a better way to accomplish what I'm trying to do?

You could just a dictionary instead of one variable per key.
Dictionary<Keys, bool> keysPressed = new Dictionary<Keys, bool>();
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
keysPressed[e.KeyData] = false;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (!keysPressed.ContainsKey(e.KeyData) || !keysPressed[e.KeyData]) {
Console.WriteLine(e.KeyData);
keysPressed[e.KeyData] = true;
}
}

Try this:
bool isPressed_Num7 = false;
bool isPressed_Num9 = false;
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyData == Keys.NumPad7) && (!isPressed_Num7))
{
isPressed_Num7 = true;
Console.WriteLine("Keydown 7");
}
if ((e.KeyData == Keys.NumPad9) && (!isPressed_Num9))
{
isPressed_Num9 = true;
Console.WriteLine("Keydown 9");
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if ((e.KeyData == Keys.NumPad7)&&(isPressed_Num7==true))
{
isPressed_Num7 = false;
Console.WriteLine("Keyup 7");
}
if ((e.KeyData == Keys.NumPad9)&&(isPressed_Num9==true))
{
isPressed_Num9 = false;
Console.WriteLine("Keyup 9");
}
}

This solution uses the recommended way to handle keyboard shortcuts according to Microsoft. And allows you to assign action to invoke when pressing a key combination.
public partial class Form1 : Form
{
private readonly IDictionary<Keys, Action> _operationsMap = new Dictionary<Keys, Action>();
public Form1()
{
InitializeComponent();
RegisterKeyShortcuts();
}
private void RegisterKeyShortcuts()
{
_operationsMap.Add(Keys.Control | Keys.F, WhenPressingF);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (_operationsMap.ContainsKey(keyData))
{
_operationsMap[keyData].Invoke();
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
protected void WhenPressingF()
{
MessageBox.Show("What the Ctrl+F?");
}
}

Related

How do i click button from keypress event

I want to click a button when i press F1
this is my code
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
buttonGfxIn_Click.PerformClick();
}
}
But i get this error
that button name Is a 'method' which is not valid in the given context error
I have test with a example and it is working well. try it.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("button1 was clicked");
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
KeyEventArgs e = new KeyEventArgs(keyData);
if (e.KeyCode == Keys.F1)
{
button1_Click("", e);
}
return base.ProcessCmdKey(ref msg, keyData);
}
}

How do i set the label and display an integer value from a TextBox to the label when the enter key is pressed in wpf c#?

Here's the code. I have modified it bit?
public partial class MainWindow : Window
{
int coursenumber;
public MainWindow()
{
InitializeComponent();
}
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
bool res = int.TryParse(textBox.Text, out coursenumber);
if (res == true)
{
//success
}
}
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
//Check if the key that was pressed was the Enter key.
if (e.Key == Key.Enter)
{
//logic goes here
}
}
Register to the Key Down event and check
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
// your logic here
}
}
What you're looking for is the KeyDown event. Subscribe to this event on your TextBox like this:
<TextBox KeyDown="textBox_KeyDown" ... />
And your event handler will look something like this:
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
//Check if the key that was pressed was the Enter key.
if (e.Key == Key.Enter)
{
bool res = int.TryParse ...
//The rest of your logic here.
}
}
Thanks everyone, i was able to get it working from your responses. here's the modification
public partial class MainWindow : Window
{
int coursenumber;
public MainWindow()
{
InitializeComponent();
}
private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
bool res = int.TryParse(textBox.Text, out coursenumber);
if (res == true)
{
//success
}
}
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
//Check if the key that was pressed was the Enter key.
if (e.Key == Key.Enter)
{
label2.Content = coursenumber;
}
}

Axwindows media player dectect keydown in full screen mode

I have ax windows media player in my windows forms application. When the user double clicks on it, it becomes full screen.
PROBLEM: I want the user to be able to go back to normal screen when he presses the "escape key".
I have put a keydown event on the ax media player. This key down event works when in normal mode, but fails when the media player is made full screen.
WMPLarge.KeyDownEvent += new AxWMPLib._WMPOCXEvents_KeyDownEventHandler(Form1_KeyDown);
private void Form1_KeyDown(object sender, AxWMPLib._WMPOCXEvents_KeyDownEvent e)
{
if (e.nKeyCode == 27)
{
MessageBox.Show("");
WMPLarge.fullScreen = false;
WMPSmall.fullScreen = false;
}
}
How can I achieve this ?
Here is one code snippet I used, I hope that helps.
public partial class Form16 : Form,IMessageFilter
{
public Form16()
{
InitializeComponent();
}
private void Form16_Load(object sender, EventArgs e)
{
this.axWindowsMediaPlayer1.URL = #"D:\MyVideo\myfile.wmv";
Application.AddMessageFilter(this);
}
private void Form16_FormClosing(object sender, FormClosingEventArgs e)
{
Application.RemoveMessageFilter(this);
}
#region IMessageFilter Members
private const UInt32 WM_KEYDOWN = 0x0100;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_KEYDOWN)
{
Keys keyCode = (Keys)(int)m.WParam & Keys.KeyCode;
if (keyCode == Keys.Escape)
{
this.axWindowsMediaPlayer1.fullScreen = false;
}
return true;
}
return false;
}
#endregion
}

Esc handler ignored

Following code, doesn't get triggered when Esc is pressed. Can somebody give me insight?
I like to change the cursor (let's say from drawing mode turn it into pointer mode)
public override void OnKeyDown(MyCanvas dc, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
_line = null;
e.Handled = true;
}
}
Thanks.
#amit's solution:
public override void OnKeyDown(MyCanvas dc, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
_line = null;
dc.CurrentTool = ToolType.Pointer;
dc.Cursor = Cursors.Arrow;
dc.ReleaseMouseCapture();
}
}

How to prevent firing CheckedChanged event when checking a control programmatically?

How do I prevent firing CheckedChanged event when checking a control programmatically?
I usually do this the following way.
private bool isFrozen = false;
private void btn1_CheckedChanged(object sender, EventArgs e)
{
if (isFrozen)
return;
isFrozen = true;
btn2.Checked = false;
isFrozen = false;
// Do some stuff
}
private void btn2_CheckedChanged(object sender, EventArgs e)
{
if (isFrozen)
return;
isFrozen = true;
btn1.Checked = false;
isFrozen = false;
// Do another stuff
}
Is there a better or more common solution?
I think your way is fine.
The other way to do it is remove the EventHandler before the check, and then add it back again after the check. This way eliminates the need for the isFrozen variable.
private void btn1_CheckedChanged(object sender, EventArgs e)
{
btn2.CheckedChanged -= btn2_CheckedChanged;
btn2.Checked = false;
btn2.CheckedChanged += btn2_CheckedChanged;
// Do some staff
}
private void btn2_CheckedChanged(object sender, EventArgs e)
{
btn1.CheckedChanged -= btn1_CheckedChanged;
btn1.Checked = false;
btn1.CheckedChanged += btn1_CheckedChanged;
// Do another staff
}
In VB:
RemoveHandler btn2.CheckedChanged, AddressOf btn2_CheckedChanged
btn2.Checked = false
AddHandler btn2.CheckedChanged, AddressOf btn2_CheckedChanged
I came across this post after wanting to implement something like this for a while. I regularly use Measurement Studio from National Instruments, and their WinForms controls that have the event StateChanging or StateChanged pass a parameter of type ActionEventArgs, which has a property Action which can take three values: ByKeyboard, ByMouse and Programatic. This is very useful in determining what has caused the state of the control to change. I wanted to replicate this in a standard WinForms checkbox.
Here is my code:
public enum ControlSource
{
Programatic,
ByKeyboard,
ByMouse
}
public class AwareCheckBox : Checkbox
{
public AwareCheckBox()
: base()
{
this.MouseDown += AwareCheckbox_MouseDown;
this.KeyDown += AwareCheckbox_KeyDown;
}
private ControlSource controlSource = ControlSource.Programatic;
void AwareCheckbox_KeyDown(object sender, KeyEventArgs e)
{
controlSource = ControlSource.ByKeyboard;
}
void AwareCheckbox_MouseDown(object sender, MouseEventArgs e)
{
controlSource = ControlSource.ByMouse;
}
public new event AwareControlEventHandler CheckedChanged;
protected override void OnCheckedChanged(EventArgs e)
{
var handler = CheckedChanged;
if (handler != null)
handler(this, new AwareControlEventArgs(controlSource));
controlSource = ControlSource.Programatic;
}
}
public delegate void AwareControlEventHandler(object source, AwareControlEventArgs e);
public class AwareControlEventArgs : EventArgs
{
public ControlSource Source { get; private set; }
public AwareControlEventArgs(ControlSource s)
{
Source = s;
}
}
I'm sure there are improvements to make, but my rudimentary testing has demonstrated that it works. I have posted here simply in case others stumble across this issue and want a clearer way of distinguishing where the change was initiated. Any comments welcome.
Just have a counter value set and check for the value in the beginning of the event. It solved my problem in 10 minutes. I am using 5 slide buttons in Xamarin to make it as a radio button.
private void testtoggle1(object sender, ToggledEventArgs e)
{
if (chk_ctr == 1) { return; }
chk_ctr = 1;
sw2.IsToggled= false;
sw3.IsToggled = false;
sw4.IsToggled = false;
sw5.IsToggled = false;
chk_ctr = 0;
}
private void testtoggle2(object sender, ToggledEventArgs e)
{
if (chk_ctr == 1) { return; }
chk_ctr = 1;
sw1.IsToggled = false;
sw3.IsToggled = false;
sw4.IsToggled = false;
sw5.IsToggled = false;
chk_ctr = 0;
}
private void testtoggle3(object sender, ToggledEventArgs e)
{
if (chk_ctr == 1) { return; }
chk_ctr = 1;
sw1.IsToggled = false;
sw2.IsToggled = false;
sw4.IsToggled = false;
sw5.IsToggled = false;
chk_ctr = 0;
}
private void testtoggle4(object sender, ToggledEventArgs e)
{
if (chk_ctr == 1) { return; }
chk_ctr = 1;
sw1.IsToggled = false;
sw2.IsToggled = false;
sw3.IsToggled = false;
sw5.IsToggled = false;
chk_ctr = 0;
}
private void testtoggle5(object sender, ToggledEventArgs e)
{
if (chk_ctr == 1) { return; }
chk_ctr = 1;
sw1.IsToggled = false;
sw2.IsToggled = false;
sw3.IsToggled = false;
sw4.IsToggled = false;
chk_ctr = 0;
}

Categories