Sign in to follow this  
NotSlyPee

C# KeyDown problem

Recommended Posts

I can't get KeyDown method to work. I need my application to check answer when user clicks 'enter' on his keyboard, but unfortunately nothing happens. Here's the code:
 private void Answer_KeyDown(object sender, KeyEventArgs e)
        
        {
            if (e.KeyCode == Keys.Enter)
            {
                int result = 0;
                if (problemType == "+")
                {
                    result = no1 + no2;
                }
                else if (problemType == "-")
                {
                    result = no1 - no2;
                }
                else if (problemType == "*")
                {
                    result = no1 * no2;
                }

                if (Answer.Text == result.ToString())
                {
                    Feedback.Text = "Correct";
                }
                else
                {
                    Feedback.Text = "Incorrect";
                }

Share this post


Link to post
Share on other sites
1. Make sure the control actually gets focus
2. If it's a TextBox or derived, there are "AcceptsReturn" and "AcceptsTab" properties that you need to set to 'true' if you want KeyDown events for those two keys.
3. In rare cases, override the "IsInputKey" method and return true for enter, otherwise return base.IsInputKey.

Share this post


Link to post
Share on other sites
Quote:
Original post by Nypyren
1. Make sure the control actually gets focus
2. If it's a TextBox or derived, there are "AcceptsReturn" and "AcceptsTab" properties that you need to set to 'true' if you want KeyDown events for those two keys.
3. In rare cases, override the "IsInputKey" method and return true for enter, otherwise return base.IsInputKey.


I didn't understood the get focus part. Can you tell a bit more about it?

Share this post


Link to post
Share on other sites
Well, if it's a TextBox and you're successfully typing text into it, it has focus. If you can't tell if any input is getting to it at all then it might not.

Focus means that the control is the one selected to receive keyboard events.

Typically Focus is set when you click on a control or press the TAB key to move between controls.

Various controls have their "Selectable" style (see "Control.Setstyle") true or false, which can affect this.

Share this post


Link to post
Share on other sites
If AcceptsReturn is true and you're not getting the keydown it's possible that the event hasn't been hooked. Your function by itself won't be called unless you added it to the event, which requires something that looks like the following line:

Answer.KeyDown += new KeyEventHandler(Answer_Keydown);

(edit) oops

Share this post


Link to post
Share on other sites
Ok, i think posting all code was a good idea. :D Here it is:
public partial class Form1 : Form
{
Random randomNo = new Random();
int no1;
int no2;
string problemType = "+";

public Form1()
{
InitializeComponent();
}

private void StartGame_Click(object sender, EventArgs e)
{
Clock = new Timer();
Clock.Interval = 1000;
Clock.Start();
Clock.Tick += new EventHandler(Timer_Tick);
StartGame.Visible = false;
CheckAnswer.Visible = true;
Question.Visible = true;
Answer.Visible = true;
NextQuestion.Visible = true;
Feedback.Text = "";
Feedback.Visible = true;
label1.Visible = true;
Gen_Question();
}

private void Gen_Question()
{
no1 = randomNo.Next(100);
no2 = randomNo.Next(100);

if (radioButton1.Checked)
{
problemType = "+";
}
else if (radioButton2.Checked)
{
problemType = "-";
}
else if (radioButton3.Checked)
{
problemType = "*";
}

Question.Text = no1 + problemType + no2;
}
private void CheckAnswer_Click(object sender, EventArgs e)
{
int result = 0;
if (problemType == "+")
{
result = no1 + no2;
}
else if (problemType == "-")
{
result = no1 - no2;
}
else if (problemType == "*")
{
result = no1 * no2;
}

if (Answer.Text == result.ToString())
{
Feedback.Text = "Correct";
}
else
{
Feedback.Text = "Incorrect";
}

}

private void NextQuestion_Click(object sender, EventArgs e)
{
x = 30;
Clock.Start();
this.label1.Text = "" + x;
Gen_Question();
Answer.Text = "";
Feedback.Text = "";
}
int x = 30;

private void Timer_Tick(object sender, EventArgs e)
{
if (x == 1) { Clock.Stop(); }
x = x - 1;
this.label1.Text = "" + x;
if (x == 0) { stop(); }
}
private void stop()
{
this.Question.Text = "Time's Up";

}

private void Answer_KeyDown(object sender, KeyEventArgs e)

{
if (e.KeyCode == Keys.Enter)
{
int result = 0;
if (problemType == "+")
{
result = no1 + no2;
}
else if (problemType == "-")
{
result = no1 - no2;
}
else if (problemType == "*")
{
result = no1 * no2;
}

if (Answer.Text == result.ToString())
{
Feedback.Text = "Correct";
}
else
{
Feedback.Text = "Incorrect";
}
Answer.KeyDown += new KeyEventHandler(Answer_KeyDown);
}


Once i found an error in computer generated code, so if needed i'll post it later. ;)

Share this post


Link to post
Share on other sites
You need to add the event handler BEFORE the function can ever be called, so adding it in the function is worthless. Maybe you should do it after the call to "InitializeComponent"?

Right now what you are doing is like saying you will give directions to the pizza delivery guy when he gets to your house... it is never going to happen.

Share this post


Link to post
Share on other sites
I usually hook events at the bottom of the form's constructor:


public Form1()
{
InitializeComponent();
Answer.KeyDown += new KeyEventHandler(Answer_KeyDown);
}


The "InitializeComponent" is an auto-generated function that creates all of the controls that you laid out on the Form Designer (the Form Designer writes the code for that function).

You should also look for the "Form1.Designer.cs" file and examine its contents to gain a better understanding of how the program is being set up. It may help you in the future to know exactly what's going on under the hood :)

Share this post


Link to post
Share on other sites
Here's a bit of an explanation into the order of event processing for the Windows controls:

1. Old-school windows messages get sent to the application by the operating system (such as WM_KEYDOWN).

2. Each control in your application has a default message handling wrapper that converts things like WM_KEYDOWN to a function call to OnKeyDown (or dozens of other functions).

3. OnKeyDown is a virtual function, so any derived controls can override it and handle it.

4. OnKeyDown by default raises the KeyDown event after it is done with internal processing, sort of like this:


// Inside System.Windows.Forms.Control class
public event KeyEventHandler KeyDown; // this is the event 'variable' that you get access to.

virtual void OnKeyDown(KeyEventArgs kea)
{
if (KeyDown != null)
{
KeyDown(this, kea);
}
}

// Inside System.Windows.Forms.TextBox
override void OnKeyDown(KeyEventArgs kea)
{
// Code to handle TextBox specific processing would be here.

base.OnKeyDown(kea); // This eventually calls the Control.OnKeyDown function
}



The "KeyDown" variable can be thought of as list of functions that get called when you "call" it. But you have to add your function to that list first, which is what "Answer.KeyDown += new KeyEventHandler(Answer_Keydown);" does. The name of the function doesn't matter at all, and doesn't get automatically added to the event's list.

So you have to add your handler function to the list somewhere early, somewhere in a function that always gets run first (like the Form's constructor), but after the TextBox actually gets created (otherwise the list won't be available yet).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this