Ok, so I'm in the process of making a Tic-Tac-Toe game to help me learn C#.
I'm attempting to add a bit of functionality to it, so I want people to be able to use the NumPad on a computer to simulate clicking the buttons.
Here is what I have but when I use the NumPad the buttons don't click.
Can any of you see a reason as to why?
//===============================
// start NumPad Simulate Clicks
// NumPad MyButtons
// 7 8 9 1 2 3
// 4 5 6 4 5 6
// 1 2 3 7 8 9
//===============================
public void myControl_NumPad7(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.NumPad7)
{
button1_Click(null, null);
}
}
public void myControl_NumPad8(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.NumPad8)
{
button2_Click(null, null);
}
}
public void myControl_NumPad9(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.NumPad9)
{
button3_Click(null, null);
}
}
public void myControl_NumPad4(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.NumPad4)
{
button4_Click(null, null);
}
}
public void myControl_NumPad5(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.NumPad5)
{
button5_Click(null, null);
}
}
public void myControl_NumPad6(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.NumPad6)
{
button6_Click(null, null);
}
}
public void myControl_NumPad1(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.NumPad1)
{
button7_Click(null, null);
}
}
public void myControl_NumPad2(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.NumPad2)
{
button8_Click(null, null);
}
}
public void myControl_NumPad3(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.NumPad3)
{
button9_Click(null, null);
}
}
EDIT
Noticed that I have to be clearer about what I mean...
From the code you posted I suspect you have 9 controls you added your key-events to. These controls will only receive key-events when they are focused.
To handle keys globally for the form, you have to set Form.KeyPreview to true. Also, I'd not handle the keys the way you do, but add a Form.KeyDown event and write something like:
switch (e.KeyCode)
{
case Keys.NumPad9:
e.Handled = true;
button3.PerformClick();
break;
case Keys.NumPad8:
e.Handled = true;
button2.PerformClick();
break;
// And so on
}
This will handle the NumPad-Keys within the form - you can then remove all the event handlers you posted in your question.
To programatically "click" a button, you should use the Button.PerformClick() method, as more than one event handler may be added to the click event, which would not be called otherwise.
EDIT 2
Syntax for the switch-statement was invalid. Of course every "case" must start with the case keyword... Now it should work.
You need to use button1.PerformClick(); for every button to invoke event correctly, here's info.
Related
Instead of copying and pasting for each number is there a method that could reference to all buttons?
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.D5)
{
Five.PerformClick();
}
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.D5)
{
Five.PerformClick();
}
}
Firstly, the enum values Keys.D0 to Keys.D9 have sequential integer values. You can abuse this knowledge to turn the KeyCode directly into an array index.
var buttons = new Button[] {Zero, One, ... etc ...};
if(e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9){
var index = (int)e.KeyCode - (int)Keys.D0;
var button = buttons[index];
button.PerformClick();
}
if(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9){
// similar to the above
}
Or you could rearrange your code. Create a separate method for doing the work of "user entered a digit". Then call that method from both the button click event and form key event.
private void HandleDigit(int value){
// todo
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9){
var value = (int)e.KeyCode - (int)Keys.D0;
HandleDigit(value);
}
}
Maybe this can give you an idea -- instead of the code you show something like
Button.PerformClick('5');
would do what you want. Or even
Button.PerformNumberClick(5);
and if + is preseed
Button.PerformOperatorClick('+');
You can create and event for the first button and then tie all the calculator buttons to that event, inside the event you know what key (number) is pressed.
Here is a code that could be useful, i only added two buttons to test it and notice when i live the form im releasing handles unsubscribing the events:
using System;
using System.Windows.Forms;
namespace Calculator
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
CmdButton1.KeyDown += CmdButtonKeyDown;
CmdButton2.KeyDown += CmdButtonKeyDown;
}
private void CmdButtonKeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode==Keys.NumPad1 || e.KeyCode == Keys.NumPad2 )
MessageBox.Show("KeyPressed is " + e.KeyCode.ToString());
}
private void Form1_Leave(object sender, EventArgs e)
{
CmdButton1.KeyDown -= CmdButtonKeyDown;
CmdButton2.KeyDown -= CmdButtonKeyDown;
}
}
}
I have the following event registered:
tb1.KeyPress += new KeyPressEventHandler(tb1KeyDown);
It does this:
public void tb1KeyDown(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
// Do my stuff
e.Handled = true;
}
}
But, if I have entered the Enter key 2 times or more, my tb1KeyDown is in a loop for so often, that I have entered the Enter key.
What am I doing wrong here?
Greetz padde
I have a question. Examples that i find is on a "KeyPress" and they are not longer working on WPF
Can you tell me, how to allow only specified keys from keybord to be write on WPF textbox? I know about keyUp and Down functions, but how to define letters that i want to by type into it?
I think it will be easier, if i will post my code and i tell u what i want to do. What to change here?
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
//something here to only allow "A" key to be pressed and displeyed into textbox
if (e.Key == Key.A)
{
stoper.Start();
}
}
private void textBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.A)
{
//here i stop the stopwatch to count time of pressing the key
stoper.Stop();
string aS = stoper.ElapsedMilliseconds.ToString();
int aI = Convert.ToInt32(aS);
stoper.Reset();
}
}
You can use PreviewKeyDown and use e.Key to filter out what you need.
Or, in any place of your code you can use Keyboard class:
if (Keyboard.IsKeyDown(Key.E)) { /* your code */ }
UPDATE:
To forbid a key, you need to set event as handled:
if (e.Key == Key.E)
{
e.Handled = true;
MessageBox.Show($"{e.Key.ToString()} is forbidden");
}
That thing works pretty fine to me (thanks for #JohnyL):
private void textBox_KeyDown(object sender, KeyEventArgs e)
{
//something here to only allow "A" key to be pressed and displeyed into textbox
if (e.Key == Key.A)
{
stoper.Start();
}
else
e.Handled = true;
}
private void textBox_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.A)
{
//here i stop the stopwatch to count time of pressing the key
stoper.Stop();
string aS = stoper.ElapsedMilliseconds.ToString();
int aI = Convert.ToInt32(aS);
stoper.Reset();
}
}
I have a code like below
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
if (!textBox1.AcceptsReturn)
{
button1.PerformClick();
}
}
}
After I hit Enter, it'll send a message to another textbox and begin a new line. Can anyone help me to bring the cursor back to its first line?
I tried textBox1.SelectionStart, SelectionLength and Focus but it doesn't work, is there any another way?
You can prevent that the keypress is passed on to the control by setting the KeyPressEventArgs.Handled property to true:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
if (!textBox1.AcceptsReturn)
{
button1.PerformClick();
e.Handled = true;
}
}
}
As you mentioned in a comment that you are implementing a chat app, you also might want to implement the typical behavior of Shift+Return inserting a new line:
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyValue == 13 && !e.Shift)
{
if (!textBox1.AcceptsReturn && !string.IsNullOrEmpty(textBox1.Text))
{
button1.PerformClick();
textBox1.Text = "";
e.Handled = true;
}
}
}
To set cursor position to the beginning of a textbox, use the following...
I will hazard a guess that you didn't use these in combination with each other...
textBox1.SelectionStart = 0;
textBox1.SelectionLength = 0;
I want to find out if Enter was pressed in
private void txtMessage_TextChanged(object sender, EventArgs e)
{
// do something
}
But I can't do this :
private void txtMessage_TextChanged(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (e.KeyChar == (char)13)
{
// Then Enter key was pressed
}
}
Since txtMessage_TextChanged doesn't have this overload .
Any suggestions ? thanks !
You need to subscribe to an event that actually captures that information.
The KeyPress event fires before TextChanged, so you could use a bool to indicate whether the Enter key was pressed.
bool enterKeyPressed = false;
private void textBox2_KeyPress(object sender, KeyPressEventArgs e)
{
enterKeyPressed = (e.KeyChar == (char)Keys.Enter);
}
private void txtMessage_TextChanged(object sender, EventArgs e)
{
if (enterKeyPressed)
{
}
}
register to this:
this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.Login_KeyPress);
In that method set a boolean or something if keychar == 13
you can use keypress event to capture enter key event