Application.OpenForms.Count = 0 siempre

Tengo esta situación. Application.OpenForms no devuelve el resultado correcto. es decir, Application.OpenForms.Count = 0 siempre …

El propósito de obtener el formulario es obtener el propietario del formulario para que pueda pasar al propietario como el parámetro de la función MessageBox.Show() .

Hay un error en Windows Forms que hace que un formulario desaparezca de la colección Application.OpenForms. Esto sucederá cuando asigne la propiedad ShowInTaskbar, FormBorderStyle, ControlBox, Min / MaximizedBox, RightToLeftLayout, HelpButton, Opacity, TransparencyKey, ShowIcon o MdiParent después de que se haya creado la ventana. Estas propiedades son especiales porque se especifican como indicadores de estilo en la llamada nativa CreateWindowEx (). Este formulario de muestra demuestra el error:

 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); } } 

Los formularios de Windows deben llamar a CreateWindowEx () nuevamente para hacer que la propiedad modificada sea efectiva, pasando diferentes indicadores de estilo. La destrucción de la ventana original primero tiene efectos secundarios más allá del parpadeo muy notable, uno de ellos es que la clase Application pierde la pista de la forma ya que ve desaparecer la ventana. Con el error que no lo vuelve a agregar cuando se crea la nueva ventana. Evite el error estableciendo la propiedad solo en el constructor, el código que se ejecuta antes de que se llame a CreateWindowEx (), y en ningún caso a los controladores.

En general, evite confiar en OpenForms debido a este error. Proporcione a la clase que necesita mostrar el cuadro de mensaje una referencia a la instancia de formulario a través de su constructor. MessageBox generalmente descubre una ventana padre por sí mismo correctamente por cierto, seleccionará la ventana activa y eso es correcto el 99% del tiempo. Si necesita llamar a BeginInvoke () desde un hilo de trabajo, asegúrese de copiar SynchronizationContext.Current en su constructor y llame a su método Post () más adelante. Garantiza que su biblioteca también funcionará con otras bibliotecas de clases de GUI.

Obtuve el problema cuando utilicé ShowInTaskBar = true. Lo resolví usando Windows API en lugar de las propiedades .Net. Application.OpenForms se mantuvo intacto.

No sé si funciona como una solución general utilizando SetWindowLong para cambiar las propiedades, pero funciona para ShowInTaskBar = true.

  public static class ShowInTaskBar { [DllImport("User32.dll")] private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); [DllImport("User32.dll")] private static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); private const int SW_HIDE = 0x00; private const int SW_SHOW = 0x05; private const int WS_EX_APPWINDOW = 0x40000; private const int GWL_EXSTYLE = -0x14; public static void ShowWindowInTaskbar(IntPtr pMainWindow) { SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow, GWL_EXSTYLE) | WS_EX_APPWINDOW); ShowWindow(pMainWindow, SW_HIDE); ShowWindow(pMainWindow, SW_SHOW); } public static void HideWindowFromTaskbar(IntPtr pMainWindow) { SetWindowLong(pMainWindow, GWL_EXSTYLE, GetWindowLong(pMainWindow, GWL_EXSTYLE) | ~WS_EX_APPWINDOW); ShowWindow(pMainWindow, SW_HIDE); ShowWindow(pMainWindow, SW_SHOW); } }