How to close a dialog form properly when the user presses the escapekey.

S

Sin Jeong-hun

I have a dialog form which pops up from the main window using the
ShowDialog() method. this dialog has no [OK] or [Cancel] button, and
it has quite a lot of controls on it. Now, I want to close this dialog
form when the user presses the escape key, but that's only when no
control on the form is responsible for the escape key. For example, it
has a ComboBox control, and a user can press the escape key just to
close the drop down list that is being dropped down, not the dialog
form.

I added some code like the following at the dialog form's KeyDown
event handler:
if (e.KeyCode == Keys.Escape)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}

The problem is, this close the form, even if when the user pressed the
escape key to close the drop down list, not the form. Of course I
might check if the ComboBox is open like:
if(!ComboBox1.DroppedDown)
{
if (e.KeyCode == Keys.Escape)
{
this.DialogResult = DialogResult.Cancel;
this.Close();
}
}

But this seems to be only a makeshift, because there can be other
controls responsible for the escape key or that kind of controls can
be added later. What would you recommand in this situation? Is there
any cleaner way for the form to receive only orphaned (not consumed by
any other controls on the form) escape key presses?
 
J

Jeff Johnson

I have a dialog form which pops up from the main window using the
ShowDialog() method. this dialog has no [OK] or [Cancel] button

Why not? If you had a Cancel button your entire problem would be solved.
 
N

nano2k

I have a dialog form which pops up from the main window using the
ShowDialog() method. this dialog has no [OK] or [Cancel] button, and
it has quite a lot of controls on it. Now, I want to close this dialog
form when the user presses the escape key, but that's only when no
control on the form is responsible for the escape key. For example, it
has a ComboBox control, and a user can press the escape key just to
close the drop down list that is being dropped down, not the dialog
form.

I added some code like the following at the dialog form's KeyDown
event handler:
                        if (e.KeyCode == Keys..Escape)
                        {
                                this.DialogResult = DialogResult.Cancel;
                                this.Close();
                        }

The problem is, this close the form, even if when the user pressed the
escape key to close the drop down list, not the form. Of course I
might check if the ComboBox is open like:
        if(!ComboBox1.DroppedDown)
        {
                        if (e.KeyCode == Keys..Escape)
                        {
                                this.DialogResult = DialogResult.Cancel;
                                this.Close();
                        }
        }

But this seems to be only a makeshift, because there can be other
controls responsible for the escape key or that kind of controls can
be added later. What would you recommand in this situation? Is there
any cleaner way for the form to receive only orphaned (not consumed by
any other controls on the form) escape key presses?

Not a tested solution, but you may try this:

1. Make sure the form's KeyPreview property is set to false. You don't
want to give to the form the chance to process the Keydown event
before its child controls.
2. For each type of control, create a KeyDown event handler.
For example, for comboboxes, you may use the code you wrote above with
a slight change:

if(!ComboBox1.DroppedDown)
{
if (e.KeyCode == Keys.Escape)
{
this.DialogResult =
DialogResult.Cancel;
this.Close();
}
else{
e.Handled = true; //prevent the event
to propagate and close your form
}
}


And make all comboboxes' KeyDown event be handled by this handler.
And so on, for textboxes, etc.

You may also want to create your own controls that inherit from
combobox / textbox, etc that internally deal with Escape key.
This is a more elegant approach because you will not be forced to
create handlers every time you put the controls on another form.
 
S

Sin Jeong-hun

I have a dialog form which pops up from the main window using the
ShowDialog() method. this dialog has no [OK] or [Cancel] button

Why not? If you had a Cancel button your entire problem would be solved.

That was because that dialog form wasn't asking the user of something
is OK or not, and it has many controls on it, so there is little room
for unnecessary "Close" button, when there already is a close button
in the window's title bar. But if there is no easy way to detect
orphaned escape keys, maybe I can put a dummy close button outside the
form (invisible location). Thank you, for your reply.
 
S

Sin Jeong-hun

I have a dialog form which pops up from the main window using the
ShowDialog() method. this dialog has no [OK] or [Cancel] button, and
it has quite a lot of controls on it. Now, I want to close this dialog
form when the user presses the escape key, but that's only when no
control on the form is responsible for the escape key. For example, it
has a ComboBox control, and a user can press the escape key just to
close the drop down list that is being dropped down, not the dialog
form.
I added some code like the following at the dialog form's KeyDown
event handler:
                        if (e.KeyCode == Keys.Escape)
                        {
                                this.DialogResult = DialogResult.Cancel;
                                this.Close();
                        }
The problem is, this close the form, even if when the user pressed the
escape key to close the drop down list, not the form. Of course I
might check if the ComboBox is open like:
        if(!ComboBox1.DroppedDown)
        {
                        if (e.KeyCode == Keys.Escape)
                        {
                                this.DialogResult = DialogResult.Cancel;
                                this.Close();
                        }
        }
But this seems to be only a makeshift, because there can be other
controls responsible for the escape key or that kind of controls can
be added later. What would you recommand in this situation? Is there
any cleaner way for the form to receive only orphaned (not consumed by
any other controls on the form) escape key presses?

Not a tested solution, but you may try this:

1. Make sure the form's KeyPreview property is set to false. You don't
want to give to the form the chance to process the Keydown event
before its child controls.
2. For each type of control, create a KeyDown event handler.
For example, for comboboxes, you may use the code you wrote above with
a slight change:

         if(!ComboBox1.DroppedDown)
         {
                         if (e.KeyCode == Keys.Escape)
                         {
                                 this.DialogResult =
DialogResult.Cancel;
                                 this.Close();
                         }
                         else{
                                 e.Handled = true; //prevent the event
to propagate and close your form
                         }
         }

And make all comboboxes' KeyDown event be handled by this handler.
And so on, for textboxes, etc.

You may also want to create your own controls that inherit from
combobox / textbox, etc that internally deal with Escape key.
This is a more elegant approach because you will not be forced to
create handlers every time you put the controls on another form.

Thank you for your detailed answer. But the solution seems to be
complicated for a simple task like just closing the form. I think I
can just put a dummy "Cancel" button to the invisible location of the
form. Like the other reply said, that could simply solve the problem,
though not so clean.
 
J

Jeff Johnson

That was because that dialog form wasn't asking the user of something
is OK or not, and it has many controls on it, so there is little room
for unnecessary "Close" button, when there already is a close button
in the window's title bar. But if there is no easy way to detect
orphaned escape keys, maybe I can put a dummy close button outside the
form (invisible location). Thank you, for your reply.

Personally I would feel very uncomfortable using an application that allowed
the ESC key to function as "I'm done, submit this." It is COMPLETELY
non-standard behavior. But if you're going to go this route, I recommend
that you turn off the TabStop property for the Cancel button so the user
can't accidentally tab to a control that can't be seen.
 
S

Sin Jeong-hun

Personally I would feel very uncomfortable using an application that allowed
the ESC key to function as "I'm done, submit this." It is COMPLETELY
non-standard behavior. But if you're going to go this route, I recommend
that you turn off the TabStop property for the Cancel button so the user
can't accidentally tab to a control that can't be seen.

Thanks for the tip. The form was meant to be closed by clicking on the
close button on the title bar. Users close the form when they don't
need the form any more, not to submit something. Currently, clicking
the close button on the title bar is the only way to close the form,
but I thought it would be more convenient if I can close it with
simple ESC stroke. I don't think "Close" button is always necessary
for forms, when they have the close button on the title bar, it's
redundancy.
 
J

Jeff Johnson

Thanks for the tip. The form was meant to be closed by clicking on the
close button on the title bar. Users close the form when they don't
need the form any more, not to submit something. Currently, clicking
the close button on the title bar is the only way to close the form,
but I thought it would be more convenient if I can close it with
simple ESC stroke.

Okay, this is making more sense now. Sort of like the Find dialog in the
IDE.

You might consider overriding the ProcessCmdKey() method. In there you first
check to see if the key in question is the Escape key, and then you could
check all your combo boxes to see if any of their DroppedDown properties is
true. If so, you exit the method without processing the key (to let the
combo box handle it itself), otherwise you close the form. That would
probably provide you with the cleaner method of closing the form that you're
looking for.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top