zer09
zer09

Reputation: 1588

winform ShowDialog(this) still fail

I am already aware that using ShowDialog() can cause the form to go behind to its parent form. So I look for a solution.

Many says that the solution is to pass the parent form as a parameter to the child form.

Something like this.

using(Form f = new Form1())
{
     f.ShowDialog(this);// while the 'this' is the parent form calling
}

but this code still fails. This is the scenario.

Open the child form showing the dialog, then when the child form window is still active, click show desktop (or press Window+D) then, open other application. after opening the application minimize it or close it. now after you close or minimize the other application.

Now the child form is already behind the parent form. now you should press alt+tab or click it form the taskbar to work it again properly.

I will appreciate for any help.

Upvotes: 1

Views: 543

Answers (2)

zer09
zer09

Reputation: 1588

My closest workaround to solve this is set ShowInTaskbar and MinimizeBox to false.

Actually I can just disable ShowInTaskbar without disabling the minimize box, but there is no point, allowing the user to minimize the child form but still they cant perform any action on the parent form.

Upvotes: 0

Loathing
Loathing

Reputation: 5256

Good question. It seems like then the child dialog is visible, and Windows+D is pressed, the parent form ignores the request (or possibly the OS prevents sending a minimize request to the parent form because it has an active modal dialog). Just guessing. The parent form is never sent a minimize message.

You can observe this by using TOOLS -> Spy++ and notice the lack of window messages sent to the parent window when the child dialog is showing and Windows+D is pressed. The messages received are in the orange box:

enter image description here

That means the parent form is never actually minimized. Windows stops painting it, but opening another window turns the painting back on.

So using the WM_ACTIVATEAPP as a reference point, force the parent form to be minimized. This has the side effect that the child dialog is made invisible. Then listen for the SC_RESTORE message, and reshow the child dialog:

public class RestoreForm : Form {

    private const int SC_RESTORE = 0xF120;
    private const int WM_SYSCOMMAND = 0x0112;
    private const int WM_ACTIVATEAPP = 0x1C;

    public RestoreForm() {
        Button btn1 = new Button { Text = "ShowDialog(...)", AutoSize = true };
        btn1.Click += btn1_Click;

        Controls.Add(btn1);
    }

    protected override void WndProc(ref Message m) {
        base.WndProc(ref m);
        if (f2 != null) {
            if (m.Msg == WM_ACTIVATEAPP) {
                if (f2.WindowState == FormWindowState.Minimized) {
                    this.WindowState = FormWindowState.Minimized;
                }
            }
            else if (m.Msg == WM_SYSCOMMAND) {
                var w = m.WParam.ToInt32();
                if (w == SC_RESTORE) {
                    f2.WindowState = FormWindowState.Normal;
                    //f2.Visible = true; // ignores staying on top of previous parent
                    f2.ShowDialog(this);
                }
            }
        }
    }

    Form f2 = null;
    void btn1_Click(object sender, EventArgs e) {
        f2 = new Form { Text = "Child" };
        f2.ShowDialog(this);
    }
}

Upvotes: 1

Related Questions