dotnet / winforms

Windows Forms is a .NET UI framework for building Windows desktop applications.
MIT License
4.42k stars 984 forks source link

form.ShowDialog(owner) with owner that is Topmost stays hidden behind the owner #6190

Open fivage opened 3 years ago

fivage commented 3 years ago

Problem description:

form.ShowDialog(owner) with owner that is Topmost stays hidden behind the owner.

Expected behavior:

It should be put in front of the owner

RussKie commented 3 years ago

Please provide a repro that shows the issue. Also an animation of the issue would help.

ghost commented 2 years ago

This submission has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for 14 days.

It will be closed if no further activity occurs within 7 days of this comment.

fivage commented 2 years ago

WinFormsApp2.zip

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.TopMost = true;
        }

        private void OpenPopupButton_Click(object sender, EventArgs e)
        {
            PopupForm popupForm = new();
            popupForm.ShowDialog(this);  // PopupForm should be in front of Form1, but is positioned behind Form1 
        }
    }
hyperquantum commented 2 years ago

A workaround seems to be to set TopMost = true in the child window if it detects that its parent has TopMost enabled.

merriemcgaw commented 2 years ago

@hyperquantum that looks like a reasonable workaround. @Olina-Zhang can you help us figure out where this one changed? Was it working in 3.1 the same as it did in 4.7.2/4.8?

Olina-Zhang commented 2 years ago

@merriemcgaw verified this issue in .Net Core 3.1, it works well, and it repro in .Net 5.0/6.0/7.0.

Here is a gif in .Net Core 3.1 behavior: 3_1

elachlan commented 1 year ago

Related #9351

DinkoK commented 1 year ago

Hello, We have encountered a similar behavior when using a derivative of MS CommonDialog. In this case, our Form has the TopMost property set to true. When CommonDialog is shown it will be placed under the Form. It can be reproduced using the following code:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.TopMost = true;
    }

    private void radButton1_Click_1(object sender, EventArgs e)
    {
        new MyCommonDialog().ShowDialog();
    }
}

public class MyCommonDialog : CommonDialog
{
    private Form myForm = new Form();

    public override void Reset()
    {
    }

    protected override bool RunDialog(IntPtr hwndOwner)
    {
        return ((Form)myForm).ShowDialog(NativeWindow.FromHandle(hwndOwner)) == DialogResult.OK;
    }
} 

This behavior is not observed in NetCore 3.1. It is reproducible in Net 5 and above. Dialog-TopMost

I am also attaching my test project.

Show_TopMost.zip

sgf commented 9 months ago

same problem in .net 6

SteffenSchwaiger commented 9 months ago

Same problem in .NET 8.

Also, the workaround only works if TopMost = true is set on the child dialog after ShowDialog is called (e.g. inside the child form's Load event handler).

xv commented 6 months ago

Same problem in .NET 8.

Also, the workaround only works if TopMost = true is set on the child dialog after ShowDialog is called (e.g. inside the child form's Load event handler).

I came across this issue after upgrading to .NET 8 from Framework 4.8.

Setting the child form's TopMost after instantiating it but prior to calling ShowDialog() also works:

using var frmChild = new FrmChild();
frmChild.TopMost = TopMost;
frmChild.ShowDialog();