Steven
Steven

Reputation: 13769

Properly Hiding Owner Form

The following code hides the parent (Owner) form while the child form is open. Does this code properly handle the issue where the application (briefly with no visible windows) may lose focus in the transition?

Section Main Form

using System;
using System.Windows.Forms;

namespace multiForms
{
    public partial class mainFrm : Form
    {
        public mainFrm()
        {
            InitializeComponent();

            this.button1.Click += new System.EventHandler(this.button1_Click);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            childFrm subForm = new childFrm();
            subForm.ShowDialog(this);
            subForm.Dispose();
        }

    }
}

Section Child Form:

using System;
using System.Windows.Forms;

namespace multiForms
{
    public partial class childFrm : Form
    {
        public childFrm()
        {
            InitializeComponent();

            this.Shown += new System.EventHandler(this.childFrm_Shown);
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.childFrm_FormClosing);
        }

        private void childFrm_Shown(object sender, EventArgs e)
        {
            this.Owner.Hide();
        }

        private void childFrm_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.Owner.Show();
        }

    }
}

Upvotes: 0

Views: 337

Answers (1)

Hans Passant
Hans Passant

Reputation: 942040

It will work fine.

It is not technically correct however. The FormClosing event can be cancelled, it may not be completely under your control since any code can write an event handler for the event and set the e.Cancel property to true. In circumstances like this it gets to be important to stop relying on events. Resilient code overrides the method that fires the event instead. For every Xxxx event there's a corresponding virtual OnXxxx() method that you can override.

In this case, such a method override should like this:

    protected override void OnFormClosing(FormClosingEventArgs e) {
        base.OnFormClosing(e);
        if (!e.Cancel && this.Owner != null) this.Owner.Show();
    }

Now it works fine. If there is any code around that subscribes FormClosing and cancels it then you won't show the owner.

Do note how the override gives you a choice of three different things you can do:

  • You can call base.OnXxxx() first, that leaves you in control.
  • You make your modification, then call base.OnXxxx(), that leaves the other code in control. Normally the correct choice, just not in this specific case. But what you use if you for example display the common "Do you want to save changes" message box. It should be displayed before you fire the event and if the user clicks Cancel then you don't want to fire the event at all.
  • You may not call base.OnXxxx() at all, you do so only if you heavily customized the event handling and allowing the event to still fire is liable to break the program. Pretty rare.

Do note the "feels good" factor of writing event handling code like this. A class listening to its own events doesn't make much sense. Events are meant for external code. Like the code in the Owner, where this really belongs. It just happens to be common in Winforms programming because the designer makes it easy to add event handlers and it matches the VB6 eventing model, the programming tool that Winforms was meant to replace. It is still very easy to write the OnXxxx() method override, IntelliSense supports it well. Just type "protected override on" and auto-complete from there. It is the correct OOPy way.

Upvotes: 3

Related Questions