David I. McIntosh
David I. McIntosh

Reputation: 2130

Problems adding a non-modal, child Windows.Forms.Form to a main Form which prevent child from receiving focus

Preface (likely to be removed later, after answers posted). This is a question to which I could not find an answer anywhere online (after a couple of days searching). I found an answer myself through trial-ans-error, but I am not particularly familiar the subject matter - forms - and so my solution may not be the best, or even correct.

I have created a small application using Windows Forms. The application does some (lengthy) data processing, and it needs a second, separate window to display (ongoing) errors. For this, I am using a (simple) non-modal form.

The structure is fairly simple:

public static class Program
{
    [STAThread]
    public static int Main(string[] args)
    {
        MainForm mainForm = new MainForm();
        mainForm.showTheForm();
    }
}


public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        init();
    }

    private NonModalInfo m_infoBox = null;      
    //plus a few other data members...

    private void init()
    {
        //initialize some data members and other stuff, etc.

        //Then, this critical line:
        m_infoBox = new NonModalInfo();
    }

    public void showTheForm()
    {
        this.ShowDialog();
    }

    //private void somecontrol_click(...)
    //{
        //for(some loop)
        //{
        //    doStuff;
        //    showInfo("SomeMessage");
        //    doStuff;
        //}
    //}

    //this method only gets called while the mainForm is showing, 
    //  as, for example, in the somecontrol_click method above
    public void showInfo(string msg)
    {
        if (m_infoBox == null || m_infoBox.IsDisposed)
        {
            m_infoBox = new NonModalInfo();
        }
        m_infoBox.updateMessage(msg);
        if (this.Visible)
        {
            if(!m_infoBox.Visible)
            {
                m_infoBox.Owner = this;
                m_infoBox.Show();
            }
        }
    }
}

public partial class NonModalInfo : Form
{
    public NonModalInfo()
    {
        InitializeComponent();
    }
    //This form has one element, a label called lb_Message.
    public void updateMessage(string msg)
    {
        if (msg != null)
        {
            lb_Message.Text = msg;
            if (Visible)
            {
                Update();
            }
        }
    }
}

The basic idea here is that the NonModalInfo form is used by the mainForm to display logging and/or error information to the user. The structure above, as I have it, works perfectly. The issue is the line I have commented above as Then, this critical line:. Without that line - which is how I wrote the code originally - the code almost works: the non-modal form is opened, displayed, updates, etc. The issue, is that the non-modal form can never receive focus: any attempt to click on the non-modal form to give it focus results in the mainForm blinking and maintaining focus. The behaviour is exactly what one would expect when the mainForm is opened modally, so that the non-modal form cannot receive focus.

Now, the mainForm is being opened modal (ShowDialog()), so perhaps this is not unexpected, but all the documentation and examples on the web indicate that a (modal) main dialog such as this should be able to open a non-modal child dialog, and that the child dialog should be able to recieve focus. Furthermore, simply ensuring that the member data element m_infoBox is initialized with some instance of NonModalInfo, then the behaviour is different: the child form will be given focus, no problem. From appearances, in the case where m_infoBox is initialized with a non-null instance before showing the mainForm, the mainForm seems as if it is shown as non-modal (in spite of having been shown with ShowDialog()).

My question is, why do I need to ensure the mainForm's member m_infoBox is initialized with a non-null instance? Is there any way to construct the mainForm and "show" it, so that when I do construct, add and show the non-modal child, the child can receive focus? Where is there documentation on this? Is the code above actually the correct way to do this? Can anyone explain what is going on under the hood?

Edit: In fact, the situation is more complicated than this. If the child non-modal form is visible at the time the parent is shown, the parent will be "modal", and the child will not be able to receive focus. If the child form has had its owner set to the parent prior to the parent being shown, an exception gets thrown when attempting to show the parent. I cannot find decent documentation on all these issues.

Upvotes: 0

Views: 73

Answers (0)

Related Questions