locked
Unable to detect Enter in KeyDown event RRS feed

  • Question

  • I have a mini-calculator with a text box and buttons (representing digits, parenthesis, and operators) embedded in a form and want to catch events when either one of the buttons are pressed or when the keyboard is used for input when the focus is on the form. I have a KeyDown event associated with the form which captures all events except for an enter. When an enter is pressed (randomly?) one of the other event handlers are called but never the KeyDown event handler. I would like to fix this so that the KeyDown event handler is called for all keyboard entry including pressing the enter key.

    The primary question is how to get the enter handled, but if anyone knows why this behavior occurs I would like to know. The only thing that I can think of is to associate the KeyDown event with the textbox but (I think) this limits keyboard input to input from the textbox when it is in focus and not the entire form.

    thanks

    art

    Tuesday, March 20, 2012 9:06 PM

Answers

  • Hi, there's nothing needed to know else, but it alwasy is good to know :-)

    You can simply check with if... for the Keys to catch and return true or not when your ccustom action is done.

    Returning true in such an if-construct is like setting something to "handled", the Message is handled then. If you want to do something else at other position when that key is pressed, dont return true.

    [Comment in and out the return true in the handling of the "A"-Key to see the difference]

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                this.KeyPress += new KeyPressEventHandler(Form1_KeyPress);
            }
    
            void Form1_KeyPress(object sender, KeyPressEventArgs e)
            {
                if (e.KeyChar == 'a')
                    MessageBox.Show("ja!");
            }
    
            protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
            {
                if (keyData == Keys.Enter)
                {
                    MessageBox.Show("Enter");
    
                    //return true, if you do not want to do
                    //something else when enter is pressed
                    return true;
                }
    
                if (keyData == Keys.A)
                {
                    MessageBox.Show("A");
    
                    //return true;
                }
    
                return base.ProcessCmdKey(ref msg, keyData);
            }
    
        }

    • Marked as answer by Dummy yoyo Friday, March 30, 2012 7:11 AM
    Wednesday, March 21, 2012 12:40 AM
  • Hi,

    do as follows:

    -create a new WindowsForms-Project in VS.

    -wait untilk the Form1 is shown and switch to code view.

    -delete the code for Form1, basically this: [but leave the surrounding namespace definition and using statements]

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
        }

    -copy and paste my source code to the place you deleted the code previously.

    -press F5 to run the project.

    [ The  "Expected class. delegate, enum, interface, or struct..." Is often caused by a missing opening or closing curly brace ]


    Thursday, March 22, 2012 12:11 AM

All replies

  • You may want to consider setting the KeyPreview to true on the containing form: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx

    It would be greatly appreciated if you would mark any helpful entries as helpful and if the entry answers your question, please mark it with the Answer link.

    Tuesday, March 20, 2012 9:20 PM
  • Enter key in Keydown event (do as TSoftware said):

    //on load time (on in constructor do:

    this.KeyPreiew = true; private void form1_KeyDown(object sender, KeyEventArgs e) { if(e.Keys == Key.Enter) { //enter key captured! } }



    Mitja

    Tuesday, March 20, 2012 9:28 PM
  • Form.KeyDown with Form.KeyPreview = True  and Textbox1.Focused captures Enter for me.

    Tuesday, March 20, 2012 9:39 PM
  • Sigh; No go.

    Form.KeyPreview is set to true.

    this.KeyPreview set in Calculator_Load() and then Calculator() after InitializeComponent().

    The result is the same. All keys except enter are captured in my KeyDown event handler. Enter sometimes does nothing (that I can see), sometimes is handled by the Button_0 event handler, and in the past, was handled by my Clear event handler and sometimes others. Basically, it don't work and I don't know why or how to fix it.

    The code is available (if anyone has the time or patience). It implements a simple bottom-up expression processor (Djikstra's Shunt Yard Algorithm) with parentheses, the usual operators, the square root, and clear and clear entry. Only one class (of smallsize) contains all the event handlers. Documentation is extensive and output by Doxygen as HTML.

    Any help is greatly appreciated. I've been trying to track this down for a couple of weeks and don't even know where to start. I do have working examples where an enter is accepted; it's just my code that fails.

    Thanks

    art

    Tuesday, March 20, 2012 10:33 PM
  • For me too. Even when form has a focus.

    Which are actually the events where you want to capture Enter key?  on form or on some control?


    Mitja

    Tuesday, March 20, 2012 11:15 PM
  • What other event handler is being called?


    JP Cowboy Coders Unite!

    Tuesday, March 20, 2012 11:24 PM
  • Hi,

    why not simply override ProcessCmdKey? No need to set KeyPreview then.

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
            protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
            {
                if (keyData == Keys.Enter)
                {
                    MessageBox.Show("Enter");
    
                    //return true, if you do not want to do
                    //something else when enter is pressed
                    return true;
                }
    
                return base.ProcessCmdKey(ref msg, keyData);
            }
        }

    Regards,

      Thorsten

    Tuesday, March 20, 2012 11:27 PM
  • I have been called to dinner (a higher calling) but to answer all:

    Javaman II (what happened to I)?

    The event handlers are:

    • All digit buttons (0 - 9)
    • Decimal point
    • Operators (+, - *, /, %, =, square root)
    • Clear
    • Clear entry

    In the KeyDown event handler I can detect all except square root and clear and clear entry, and of course, enter. Enter has 'called' the handler for '0', '1', and Clear so far. Mostly it calls '0'.

    The KeyDown event handler defers processing to the button event handlers and rejects the rest. (It is a "Good News Hanlder").

    All button events work correctly (as does my logic).

    Mitja: I'm glad to hear that I am not the only one with this problem (yeh, not good for you though). This encourages me to think that there may be some other issues at play.

    Thorsten I will try your proposed solution tomorrow, I don't know when yet. Is there anything that I need to know about setting the event up and it's handling of the other keyboard entries.

    Wednesday, March 21, 2012 12:28 AM
  • Hi, there's nothing needed to know else, but it alwasy is good to know :-)

    You can simply check with if... for the Keys to catch and return true or not when your ccustom action is done.

    Returning true in such an if-construct is like setting something to "handled", the Message is handled then. If you want to do something else at other position when that key is pressed, dont return true.

    [Comment in and out the return true in the handling of the "A"-Key to see the difference]

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                this.KeyPress += new KeyPressEventHandler(Form1_KeyPress);
            }
    
            void Form1_KeyPress(object sender, KeyPressEventArgs e)
            {
                if (e.KeyChar == 'a')
                    MessageBox.Show("ja!");
            }
    
            protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
            {
                if (keyData == Keys.Enter)
                {
                    MessageBox.Show("Enter");
    
                    //return true, if you do not want to do
                    //something else when enter is pressed
                    return true;
                }
    
                if (keyData == Keys.A)
                {
                    MessageBox.Show("A");
    
                    //return true;
                }
    
                return base.ProcessCmdKey(ref msg, keyData);
            }
    
        }

    • Marked as answer by Dummy yoyo Friday, March 30, 2012 7:11 AM
    Wednesday, March 21, 2012 12:40 AM
  • I think I'm going blistering mad.

    Thorsten: I tried your code and was greeted by the message "Expected class. delegate, enum, interface, or struct" for the return value (bool) of ProcessCmdKey. So, I checked the base definition (F12) and Googled the MSDN method reference. Both agree that it should be a 'bool', only the compiler disagrees.

    I chose the the 'Enter' property, redirecting the event to my own handler. Sometimes it worked, sometimes it didn't.

    As usual I tried to use the call stack when one of the incorrect event handlers was called. And, as you all well know, Microsoft has cleverly hidden the call tree for any 'internal' runtime kernel calls.

    If you (all) have an other ideas please tell me so that I can pursue them. I don't know quite what to do.

    art

    Wednesday, March 21, 2012 7:05 PM
  • Add a MessageFilter.  The KeyDown message is 256.  Enter is wparam = 13.
    • Edited by JohnWein Wednesday, March 21, 2012 8:15 PM
    Wednesday, March 21, 2012 8:13 PM
  • Thorsten: I was in a rush. I was unable to use F12 to get the definition (or ProcessCmdKey). I successrully found the definition using F12 on the base ckass Forms and searched Forms to find the definition of ProcessCmdKey,. I suspect that this mens that, somehow, part of my partial class is not contained in the forms class, and that makes no sense to me.

    John: I am truly a newbie. How do I add a filter? I will be searching with Google when I get home but if you have a quick answer I'd appreciate it.

    Wednesday, March 21, 2012 8:56 PM
  • " I will be searching with Google"

    Google is a very poor choice for searching the MSDN library.  Use the IDE help.  Finding the example code in the help files is so much more informative than anyone can post to a forum.  You get examples and extensive documentation along with links.

    Wednesday, March 21, 2012 9:11 PM
  • Hi,

    do as follows:

    -create a new WindowsForms-Project in VS.

    -wait untilk the Form1 is shown and switch to code view.

    -delete the code for Form1, basically this: [but leave the surrounding namespace definition and using statements]

        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
        }

    -copy and paste my source code to the place you deleted the code previously.

    -press F5 to run the project.

    [ The  "Expected class. delegate, enum, interface, or struct..." Is often caused by a missing opening or closing curly brace ]


    Thursday, March 22, 2012 12:11 AM
  • I think I'm going blistering mad.

    Thorsten: I tried your code and was greeted by the message "Expected class. delegate, enum, interface, or struct" for the return value (bool) of ProcessCmdKey.


    This happens if you closed the class definition before the ProcessCmdKey method. I guess you have one too many closing braces.
    Thursday, March 22, 2012 9:45 AM
  • <p>Thorsten: I am abashed and apologize. I put your suggested solution in the wrong place and got the wrong answer. It works just fine when you get all your stuff where it should go.</p><p>I did find out that the reason 'enter' was triggering event handlers for a button was that the focus was on a button and 'enter' acted as a mouse click. So, the button event handler was triggered.</p><p>Another solution proposed by my instructor is to provide a hidden text box on the form and for each event triggered, to programmatically shift the focus to the text box before exiting. Didn't try it and, now, won't, but it is an idea.</p><p>To all THANK YOU.</p>
    Thursday, March 22, 2012 3:54 PM