Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
154 views
in Technique[技术] by (71.8m points)

c# - Application.OpenForms.Count = 0 always

I have this situation. Application.OpenForms doesnt return the right result. ie Application.OpenForms.Count = 0 always..

Purpose of getting the form is get the owner of the Form so that I can pass the owner as the parameter of the MessageBox.Show() function.

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There's a bug in Windows Forms that makes a form disappear from the Application.OpenForms collection. This will happen when you assign the ShowInTaskbar, FormBorderStyle, ControlBox, Min/MaximizedBox, RightToLeftLayout, HelpButton, Opacity, TransparencyKey, ShowIcon or MdiParent property after the window was created. These properties are special in that they are specified as style flags in the native CreateWindowEx() call. This sample form demonstrates the bug:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
        button1.Click += button1_Click;
    }
    private void button1_Click(object sender, EventArgs e) {
        Console.WriteLine(Application.OpenForms.Count);
        this.ShowInTaskbar = !this.ShowInTaskbar;
        Console.WriteLine(Application.OpenForms.Count);
    }
}

Windows Forms must call CreateWindowEx() again to make the changed property effective, passing different style flags. Destroying the original window first has side effects beyond the very noticeable flicker, one of them is that the Application class loses track of the form since it sees the window disappear. With the bug that it doesn't add it back when the new window is created. Avoid the bug by setting the property only in the constructor, code that runs before CreateWindowEx() is called, not in any event handlers.

In general, avoid relying on OpenForms due to this bug. Give the class that needs to display the message box a reference to the form instance through its constructor. MessageBox usually figures out a parent window by itself correctly btw, it will pick the active window and that's correct 99% of the time. If you need it to call BeginInvoke() from a worker thread then be sure to copy SynchronizationContext.Current in your constructor and call its Post() method later. Ensures your library will also work with other GUI class libraries.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...