Application.Openforms.Count = 0 Always

Application.OpenForms.Count = 0 always

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.

Is there any other way to access open forms in C#?

Isn't really necessary a name to get an open form.
You can get the form you want by index:

Form frm = Application.OpenForms[0] //Will get the main form
Form frm = Application.OpenForms[1] //Will get the first child

Forms in the OpenForms collection are ordered in the same way that you create it

Otherwise, an alternative is to save a reference to the form and then accessing it by this reference.

//Where you want to save the reference:
Form theForm;
//Where you create the form:
myClass.theForm = new MyForm();
//Where you want to get that form:
MessageBox.Show(myClass.theForm.Caption);

(myClass is the class that will hold your reference to the form, supposing you are accessing it from different classes)

(Also, see if you are affected by this: Application.OpenForms.Count = 0 always)

is there a way to prevent a form to show multiple times in #c?

You could check the collection OpenForms from the Application object

if(forge.Checked)
{
successfully_injected openForm = Application.OpenForms.OfType<successfully_injected>().FirstOrDefault();
if(openForm == null)
openForm = new successfully_injected();
openForm.Show();
}
else
{
select_option openForm = Application.OpenForms.OfType<select_option>().FirstOrDefault();
if(openForm == null)
openForm = new select_option();
openForm.Show();
}
this.Close();

C# alternative to (Application.OpenForms[0] as Form1)

If your Class1 instance doesn't already have a reference to the Form1 instance then there is not other way. That begs a couple of questions though.

Firstly, if that Class1 object needs to directly affect that Form1 instance then why doesn't it already have that reference? Where did that Class1 object come from? Most likely the Form1 instance created it. If so, why didn't Form1 pass a reference to itself into the Class1 object when it was created?

Secondly, why is that Class1 object directly affecting the Form1 instance anyway? Most likely a better design would be for the Class1 object to raise an event that Form1 can handle and then affect itself.

How to check if a windows form is already open, and close it if it is?

maybe this helps:

FormCollection fc = Application.OpenForms;

foreach (Form frm in fc)
{
//iterate through
if (frm.Name == "YourFormName")
{
bFormNameOpen = true;
}
}

Some code in the foreach to detect the specific form and it could be done. Untested though.

Found on http://bytes.com/topic/c-sharp/answers/591308-iterating-all-open-forms

iterate through open forms and close particular forms only

You can use LINQ to find the forms you want to close and List.ForEach to close them:

Dim ActiveFroms = New List(Of String) From {"FrmSale", "FrmpPurchase", "FrmpSaleReturn", "FrmPurchaseReturn"}

Dim formsToClose = From form In My.Application.OpenForms.Cast(Of Form)()
Join activeFormName In ActiveFroms
On form.Name Equals activeFormName
Select form

formsToClose.ToList().ForEach(Sub(form) form.Close())

You cannot use a For Each with the query above because Form.Close will modify the collection which is not allowed. Therefore i use List.ForEach.



Related Topics



Leave a reply



Submit