Search code examples
eventsacceptbutton

Key Preview and Accept Button


Using winforms, I have set the KeyPreview property to true and have event handles for the proper key events within the base form as well.

Within the forms that inherit from it, I set the AcceptButton property based on the requirements of the application.

There are certain cases in which I want the enter key to have functionality different than that of the AcceptButton.

I was hoping to capture the enter key press within my base form and check for the special cases where I do not want the AcceptButton event to fire.

It appears though, that the AcceptButton click is fired before any of the key events within my basef form. I could write functionality into the click events of the possible acceptbuttons, but, in my opinion, that would be a hack.

Any suggestions?

Thanks.


Solution

  • Another way to handle this is to override the form's ProcessDialogKey() method where you can suppress the accept and/or cancel buttons. For example, I have an application with a filter editor that filters a grid based on user input. I want the user to be able to hit the return key when the filter editor control has the focus to apply the filter. The problem is the accept button code runs and closes the form. The code below resolves the issue.

        protected override bool ProcessDialogKey(Keys keyData)
        {
            // Suppress the accept button when the filter editor has the focus.
            // This doesn't work in the KeyDown or KeyPress events.
            if (((keyData & Keys.Return) == Keys.Return) && (filterEditor.ContainsFocus))
                return false;
    
            return base.ProcessDialogKey(keyData);
        }
    

    You can take this even further by dropping the following code in a base dialog form. Then you can suppress the accept button for controls in subclasses as necessary.

        private readonly List<Control> _disableAcceptButtonList = new List<Control>();
    
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (((keyData & Keys.Return) == Keys.Return) && (_disableAcceptButtonList.Count > 0))
            {
                foreach (Control control in _disableAcceptButtonList)
                    if (control.ContainsFocus)
                        return false;
            }
    
            return base.ProcessDialogKey(keyData);
        }
    
        protected virtual void DisableAcceptButtonForControl(Control control)
        {
            if (!_disableAcceptButtonList.Contains(control))
                _disableAcceptButtonList.Add(control);
        }