locked
Enter key press and the accept button RRS feed

  • Question

  • I would like the enter key on the form to always trigger the accept button (even when the accept button loses it's focus), but, I have some controls on the page that I handle the key down event handler for the enter key. So I would like the enter key to always trigger the accept button except when that control that's focused has a key down event handler handled for the enter key. How can I do that?

    Debra has a question

    Friday, February 5, 2016 4:08 PM

Answers

  • I would like when a user presses enter on a form that the submit button of the form is always fired, unless the focus on the form is on a control that has the keydown event handler attached to it for the enter key press. Then, I would like on the first enter press it should handle for the key down event handler for that individual control and the next time the enter  button is pressed it should handle for the submit button's event handler. Is there a way to do that? Was I clear enough?

    Debra has a question

    Your prerequisites are:

    1. When enter is pressed on a specific control ("button1"), fire that button's KeyDown
    2. When enter is pressed on another specific control ("button2"), fire that button's KeyDown
    3. When enter is pressed, but not on the above, fire the submit button's KeyDown
    4. After pressing enter, if enter is pressed a second time, it will fire the submit button's KeyDown
    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        if(e.KeyCode == Keys.Enter)
        {
            if(button1.Focused) //Requirement #1
                button1_Click(null, null);
            else if(button2.Focused) //Requirement #2
                button2_Click(null, null);
            else //Requirement #3
                defaultButton_Click(null, null);
    
            defaultButton.Focus(); //Requirement #4
        }
    }
    Monday, February 8, 2016 5:42 PM
  • That list of requirements is incorrect.

    >Then, I would like on the first enter press it should handle for the key down event handler for that individual control and the next time the enter  button is pressed it should handle for the submit button's event handler.

    You need to work out if the focussed button has a KeyDown event handler.

    That code does not do that.

    This is quite tricky in windows forms. IMO, you'd do best setting tag when you attach a keydown rather than trying to work out if there's a handler subscribed or not.

    Listing specific buttons is asking for maintenance issues later.

    .

    But anyhow. There's a problem

    You can't detect the enter key using KeyDown if you have an accept button set.

    I think this approach fulfils the stated requirements:

        public partial class Form1 : Form
        {
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
            internal static extern IntPtr GetFocus();
    
            private Control GetFocusedControl()
            {
                Control focusedControl = null;
                // To get hold of the focused control:
                IntPtr focusedHandle = GetFocus();
                if (focusedHandle != IntPtr.Zero)
                    // Note that if the focused Control is not a .Net control, then this will return null.
                    focusedControl = Control.FromHandle(focusedHandle);
                return focusedControl;
            }
    
            private Button lastButtonEntered = new Button();
            public Form1()
            {
                this.KeyPreview = true;
                InitializeComponent();
                this.button1.Click += new System.EventHandler(this.button1_Click);
                this.button1.Tag = "Has KeyDown";
                this.AcceptButton = button4;
            }
            private void button4_Click(object sender, EventArgs e)
            {
                Debug.WriteLine("Accept Button Clicked");
            }
            private void Button1_KeyDown(object sender, KeyEventArgs e)
            {
                Debug.WriteLine("Button 1 Key Down");
            }
            private void button1_Click(object sender, EventArgs e)
            {
                Debug.WriteLine("Button 1 click");
            }
            protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
            {
                if (keyData == Keys.Return)
                {
                    Control focussedControl = GetFocusedControl();
                    if (!(focussedControl is Button))
                    {
                        return base.ProcessCmdKey(ref msg, keyData);
                    }
                    DoEnterStuff(focussedControl);
                    return true;
                }
                else
                {
                    return base.ProcessCmdKey(ref msg, keyData);
                }
            }
    
            private void DoEnterStuff(Control focussedControl)
            {
                Button btn = (Button)focussedControl;
                if (btn.Tag.ToString() == "Has KeyDown")
                    if (lastButtonEntered != btn)
                    {
                        btn.PerformClick();
                        lastButtonEntered = btn;
                        return;
                    }
                this.AcceptButton.PerformClick();
                lastButtonEntered = btn;
            }

    Note that ProcessCmdKey gets the enter key even when the acceptbutton is set and before enter fires a click event for a focussed button.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Friday, February 12, 2016 7:56 PM

All replies

  • Hi Debra,

    Is your description to be

    "except when that control has forcus"

    ,instead of

    "except when that control that's focused has a key down event handler handled for the enter key."?

    If it's right, I'll be post later (now, using my small tablet, hard to input).

    Regards.

    Friday, February 5, 2016 6:27 PM
  • Hi Debra! This is how you do it:

    1. Change the property on your Form, "KeyPreview" = true
      What does this do? This says that no matter what control on your form has focus, your form will receive the "key down".
    2. Give your Form a "KeyDown" event.
      This event will be triggered whenever any key is pressed.

    3. Check if the key pressed is the key you want, and if so, trigger your button!
            private void Form1_KeyDown(object sender, KeyEventArgs e)
            {
                if(e.KeyCode == Keys.Enter)
                {
                    button1_Click(null, null);
                }
            }

    Friday, February 5, 2016 7:09 PM
  • Hello Debra,

    >>except when that control that's focused has a key down event handler handled for the enter key

    The same to Ashidacchi, I think the above is hard to understand. If you want to detect something. Maybe you could set a bool value, set it true or false. Then detect this value at here from CodeSmile's code:

     if(e.KeyCode == Keys.Enter)
    

    Best regards,

    Barry


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, February 8, 2016 3:05 AM
  • I would like when a user presses enter on a form that the submit button of the form is always fired, unless the focus on the form is on a control that has the keydown event handler attached to it for the enter key press. Then, I would like on the first enter press it should handle for the key down event handler for that individual control and the next time the enter  button is pressed it should handle for the submit button's event handler. Is there a way to do that? Was I clear enough?

    Debra has a question

    Monday, February 8, 2016 3:22 PM
  • I would like when a user presses enter on a form that the submit button of the form is always fired, unless the focus on the form is on a control that has the keydown event handler attached to it for the enter key press. Then, I would like on the first enter press it should handle for the key down event handler for that individual control and the next time the enter  button is pressed it should handle for the submit button's event handler. Is there a way to do that? Was I clear enough?

    Debra has a question

    Your prerequisites are:

    1. When enter is pressed on a specific control ("button1"), fire that button's KeyDown
    2. When enter is pressed on another specific control ("button2"), fire that button's KeyDown
    3. When enter is pressed, but not on the above, fire the submit button's KeyDown
    4. After pressing enter, if enter is pressed a second time, it will fire the submit button's KeyDown
    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        if(e.KeyCode == Keys.Enter)
        {
            if(button1.Focused) //Requirement #1
                button1_Click(null, null);
            else if(button2.Focused) //Requirement #2
                button2_Click(null, null);
            else //Requirement #3
                defaultButton_Click(null, null);
    
            defaultButton.Focus(); //Requirement #4
        }
    }
    Monday, February 8, 2016 5:42 PM
  • tried doing this but the form doesn't have the focus the control does so it doesn't go through this subroutine (the event handler never gets fired). Maybe it's because it's a user control?

    Debra has a question

    Thursday, February 11, 2016 5:23 PM
  • @Debra,

    Maybe that is the reason of your issue, please see the comments from the following thread on SO:

    http://stackoverflow.com/questions/2362428/setting-focus-to-a-net-usercontrol

    I think the answer is good so I copied it here:

    "UserControl will fight you tooth and nail to avoid getting the focus.  It has code that automatically passes the focus to a child control (if any) if it does get the focus.  You'll at a minimum have to override WndProc() and trap the WM_SETFOCUS message.  There might be other surgery needed, like ControlStyles.Selectable and the TabStop and TabIndex properties.

    Your next issue is that UserControl won't respond meaningfully to, say, keyboard messages when it does have focus.  You'll need to detect clicks on the UC background to handle mouse messages, as well as override the painting so it is obvious to the user that the UC has the focus (use ControlPaint.DrawFocusRectangle).  If this starts to sound unattractive, it's because UC was really meant to be a container control."

    Best regards,

    Barry


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, February 12, 2016 2:12 AM
  • Hi Debra,

    Firstly I apologize you for my slow reply, and I'm sorry I cannot still understand precisely what you want to do.
    You mentioned "the next time the enter  button is pressed it should handle for the submit button's event handler." Is there [Enter] BUTTON on the form?
    I'm confused by [Enter] KEY or [Enter] BUTTON

    Anyway, if your issue still remains after Barry Wang's post, please share your form and code(especally event handers of the form and buttons) via cloud storage such as OneDrive, Dropbox, etc.

    I'm making a test project (VB.NET) in order for me to understand your issue, and share it.
    Click "99_Debra.zip" and download it.

    Regards.
    • Edited by Ashidacchi Friday, February 12, 2016 8:05 AM
    Friday, February 12, 2016 8:00 AM
  • tried doing this but the form doesn't have the focus the control does so it doesn't go through this subroutine (the event handler never gets fired). Maybe it's because it's a user control?

    Debra has a question

    Hi Debra,

    The form doesn't need the focus. Please follow the steps I mentioned in full. :)
    Namely, you need to set the KeyPreview property of your form to "true".

    When this property is set to true, all keypresses on your form, even if the control has focus will go to the form. After this, you can use the code written above.

    So, this is your entire checklist from start to finish:

    1. Turn your form's KeyPreview property to true
    2. Ensure your form has a KeyDown event handler (for example, Form1_KeyDown)
    3. Ensure your buttons have Click event handlers (for example, button1_Click)
    4. Put the following code:
    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        if(e.KeyCode == Keys.Enter)
        {
            if(button1.Focused) //Requirement #1
                button1_Click(null, null);
            else if(button2.Focused) //Requirement #2
                button2_Click(null, null);
            else //Requirement #3
                defaultButton_Click(null, null);
    
            defaultButton.Focus(); //Requirement #4
        }
    }

    Friday, February 12, 2016 4:28 PM
  • That list of requirements is incorrect.

    >Then, I would like on the first enter press it should handle for the key down event handler for that individual control and the next time the enter  button is pressed it should handle for the submit button's event handler.

    You need to work out if the focussed button has a KeyDown event handler.

    That code does not do that.

    This is quite tricky in windows forms. IMO, you'd do best setting tag when you attach a keydown rather than trying to work out if there's a handler subscribed or not.

    Listing specific buttons is asking for maintenance issues later.

    .

    But anyhow. There's a problem

    You can't detect the enter key using KeyDown if you have an accept button set.

    I think this approach fulfils the stated requirements:

        public partial class Form1 : Form
        {
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
            internal static extern IntPtr GetFocus();
    
            private Control GetFocusedControl()
            {
                Control focusedControl = null;
                // To get hold of the focused control:
                IntPtr focusedHandle = GetFocus();
                if (focusedHandle != IntPtr.Zero)
                    // Note that if the focused Control is not a .Net control, then this will return null.
                    focusedControl = Control.FromHandle(focusedHandle);
                return focusedControl;
            }
    
            private Button lastButtonEntered = new Button();
            public Form1()
            {
                this.KeyPreview = true;
                InitializeComponent();
                this.button1.Click += new System.EventHandler(this.button1_Click);
                this.button1.Tag = "Has KeyDown";
                this.AcceptButton = button4;
            }
            private void button4_Click(object sender, EventArgs e)
            {
                Debug.WriteLine("Accept Button Clicked");
            }
            private void Button1_KeyDown(object sender, KeyEventArgs e)
            {
                Debug.WriteLine("Button 1 Key Down");
            }
            private void button1_Click(object sender, EventArgs e)
            {
                Debug.WriteLine("Button 1 click");
            }
            protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
            {
                if (keyData == Keys.Return)
                {
                    Control focussedControl = GetFocusedControl();
                    if (!(focussedControl is Button))
                    {
                        return base.ProcessCmdKey(ref msg, keyData);
                    }
                    DoEnterStuff(focussedControl);
                    return true;
                }
                else
                {
                    return base.ProcessCmdKey(ref msg, keyData);
                }
            }
    
            private void DoEnterStuff(Control focussedControl)
            {
                Button btn = (Button)focussedControl;
                if (btn.Tag.ToString() == "Has KeyDown")
                    if (lastButtonEntered != btn)
                    {
                        btn.PerformClick();
                        lastButtonEntered = btn;
                        return;
                    }
                this.AcceptButton.PerformClick();
                lastButtonEntered = btn;
            }

    Note that ProcessCmdKey gets the enter key even when the acceptbutton is set and before enter fires a click event for a focussed button.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Friday, February 12, 2016 7:56 PM