views:

485

answers:

2

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.

A: 

As our workaround, we captured the enter and leave event for the control that we wanted to have override the acceptbutton functionality. Inside the enter event, we held the current accept button in a private variable and set the acceptbutton to null. On leave, we would reassign the acceptbutton back to the private variable we were holding.

The KeyPreview events could have done something similar to the above. If anyone has a more elegant solution, I would still love to know.

Thanks.

A: 

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);
    }
Joe B
Solid idea. I like how it can be applied at a global level, if needed, whereas mine is just for a specific control.