Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows.Forms, showing a disabled form in non-modal state

Tags:

c#

.net

winforms

I have some trouble showing a disabled Form in non-modal state. Here is the example code:

public partial class Form1 : Form
{
    // ....
    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            Form2 form = new Form2();
            form.Enabled = false;
            form.Show();    // works, but form has no owner
            // form.Show(this); // gives an System.InvalidOperationException
            // ...
            // ... my program here shows a message box, ask user for something
            // ... while 'form' is shown in the background 
            form.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }
}

Any idea why Show() (without parameter) works, but Show(this) gives an exception? In my scenario, form must know its owner to be shown correctly, so I can do the following:

            form.Enabled = false;
            form.Owner=this;
            form.Show();

but is this really a good solution?

EDIT: Thanks for the quick answers. Seems that we really found a bug in the framework here. In spite of your suggestions, I think I will keep with my solution, since disabling the form after the 'Show' gives an ugly visible effect to the user.

like image 853
Doc Brown Avatar asked Jan 22 '23 17:01

Doc Brown


2 Answers

It's a classic cut-and-paste bug. Looks like they copied the code from ShowDialog(), it is indeed invalid to show a disabled form as a dialog. The user would be stuck and can't do anything anymore. But they forgot to remove the test in the Show() method. Just disable it after the Show() call.

like image 152
Hans Passant Avatar answered Jan 29 '23 11:01

Hans Passant


From Microsoft's reference source:

public void Show(IWin32Window owner)
{
    if (owner == this)
    {
        throw new InvalidOperationException(SR.GetString("OwnsSelfOrOwner", new object[] { "Show" }));
    }
    if (base.Visible)
    {
        throw new InvalidOperationException(SR.GetString("ShowDialogOnVisible", new object[] { "Show" }));
    }

    // Here!!!
    if (!base.Enabled)
    {
        throw new InvalidOperationException(SR.GetString("ShowDialogOnDisabled", new object[] { "Show" }));
    }

    if (!this.TopLevel)
    {
        throw new InvalidOperationException(SR.GetString("ShowDialogOnNonTopLevel", new object[] { "Show" }));
    }
    if (!SystemInformation.UserInteractive)
    {
        throw new InvalidOperationException(SR.GetString("CantShowModalOnNonInteractive"));
    }
    if (((owner != null) && ((((int) UnsafeNativeMethods.GetWindowLong(new HandleRef(owner, Control.GetSafeHandle(owner)), -20)) & 8) == 0)) && (owner is Control))
    {
        owner = ((Control) owner).TopLevelControlInternal;
    }

By the way, there is a MS Connect bug declared.

like image 42
serhio Avatar answered Jan 29 '23 13:01

serhio