Archivo de la etiqueta: reflection

El código de VB y C# de: Mostrar todos los formularios de una aplicación

Pues eso… lo prometido es deuda y aquí tienes el código completo de cómo mostrar todos los formularios de una aplicación (ensamblado) y cómo mostrar un formulario en el segundo monitor.

Al final de todo te pongo el enlace para descargar los proyectos tanto de Visual Basic como de C#.

¡Que te aproveche! Smile

Estas son las capturas (en funcionamiento) de Visual Basic y C#:

mostrar_formularios_01
Figura
1, la aplicación de Visual Basic

mostrar_formularios_02
Figura 2: La aplicación de C#

El código completo de Visual Basic:

'------------------------------------------------------------------------------
' Mostrar todos los formularios de una aplicación (ensamblado)      (16/Dic/18)
' Estén abiertos o no
' Usando reflection
'
' Este código está basado en el artículo que publiqué el 13/Sep/2004 en:
' http://www.elguille.info/NET/dotnet/reflectionTiposdeunensamblado.htm
' 
'
' (c) Guillermo (elGuille) Som, 2018
'------------------------------------------------------------------------------
Option Strict On
Option Infer On

Imports Microsoft.VisualBasic
Imports vb = Microsoft.VisualBasic
Imports System
Imports System.Text
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Diagnostics
Imports System.Linq

Public Class Form1
    ''' <summary>
    ''' Para recorrer todos los formularios de un ensamblado
    ''' estén abiertos o no
    ''' Basado en el código del elGuille.info:
    ''' http://www.elguille.info/NET/dotnet/reflectionTiposdeunensamblado.htm
    ''' </summary>
    Private ass As System.Reflection.Assembly

    ''' <summary>
    ''' Mostrar todos los formularios de la aplicación actual,
    ''' estén o no en memoria, usando reflection.
    ''' Además de los formularios, mostrará:
    ''' My.Application (solo en VB)
    ''' Y todos los nombres esmpiezan con el espacio de nombres
    ''' ESPACIO_DE_NOMBRES.NombreForm
    ''' </summary>
    Private Sub mostrarForms()
        ' llena una colección con los formularios de esta aplicación
        ' estén o no en memoria.
        ' Muestra el resultado en un listbox

        lbForms.Items.Clear()

        For Each t As Type In ass.GetTypes()
            Dim nombreTipo = t.BaseType.Name
            ' También tendrá My.Application: (solo en VB)
            ' <espacio de nombres>.My.MyApplication
            If nombreTipo.ToLower().Contains("form") Then
                lbForms.Items.Add(t.FullName)
            End If
        Next
    End Sub

    ''' <summary>
    ''' Muestra el formulario indicado en el argumento,
    ''' este debe ser con el espacio de nombres completo
    ''' 
    ''' Si es el actual no lo muestra.
    ''' Si da error o no es un formulario se avisa.
    ''' </summary>
    Private Sub mostrarFormulario(s As String)
        ' creamos un tipo a partir del nombre
        Dim t As Type = ass.GetType(s)
        ' instanciamos un nuevo objeto en la memoria
        Dim o As Object

        ' por si hemos seleccionado algo que no es una clase
        Try
            o = Activator.CreateInstance(t)
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Mostrar formularios")
            Exit Sub
        End Try

        ' si no es un formulario, mostramos un aviso y salimos
        If Not (TypeOf o Is Form) Then
            MessageBox.Show(s & ", no es un formulario", "Mostrar formularios")
            Exit Sub
        End If

        ' convertimos el objeto en un formulario
        ' como sabemos que si llega aquí es un formulario,
        ' usamos TryCast que hace menos trabajo que CType o DirectCast.
        Dim f As Form = TryCast(o, Form)
        If f Is Nothing Then
            MessageBox.Show(s & ", parece que no es un formulario",
                            "Mostrar formularios")
            Exit Sub
        End If

        ' si el nombre es el de este formulario,
        ' lo cerramos y salimos.
        If f.Name = Me.Name Then
            ' no volver a crear este formulario
            'f.Close()
            Me.BringToFront()

            MessageBox.Show(s & " es el formulario de inicio.",
                            "Mostrar formularios")

            Return
        End If

        ' mostramos el formulario.
        f.Show()

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' Mostrar esta ventana en el monitor secundario
        MostrarEnVentana2(Me)

        ' mostrar los formularios de esta aplicación
        ass = System.Reflection.Assembly.GetExecutingAssembly()
        mostrarForms()
    End Sub

    Private Sub btnAbrir_Click(sender As Object, e As EventArgs) Handles btnAbrir.Click
        ' Por si no hay un nombre indicado
        If String.IsNullOrWhiteSpace(txtForm.Text) Then Return

        ' Abrir el formulario indicado en el textbox
        mostrarFormulario(txtForm.Text)
    End Sub

    Private Sub btnSalir_Click(sender As Object, e As EventArgs) Handles btnSalir.Click
        Me.Close()
    End Sub

    Private Sub lbForms_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lbForms.SelectedIndexChanged
        txtForm.Text = lbForms.SelectedItem.ToString
    End Sub

    ''' <summary>
    ''' Mostrar el formulario indicado en la segunda pantalla
    ''' Código adaptado de la respuesta 42 de:
    ''' https://stackoverflow.com/questions/2561104/how-do-i-ensure-a-form-displays-on-the-additional-monitor-in-a-dual-monitor-sc
    ''' </summary>
    Public Shared Sub MostrarEnVentana2(frm As Form)
        Dim myScreen = Screen.PrimaryScreen
        Dim otherScreen = If(Screen.AllScreens.FirstOrDefault(
                                Function(s) Not s.Equals(myScreen)), myScreen)

        ' Si queremos indicar dónde mostrarlo
        ' podemos cambiar los valores de Left y Top
        'frm.Left = otherScreen.WorkingArea.Left + 12
        'frm.Top = otherScreen.WorkingArea.Top + 12

    End Sub

    Private Sub btnForm2_Click(sender As Object, e As EventArgs) Handles btnForm2.Click
        Dim f As New Form2
        f.Show()
    End Sub

    Private Sub btnForm3_Click(sender As Object, e As EventArgs) Handles btnForm3.Click
        Dim f As New Form3
        f.Show()
    End Sub
End Class

El código completo de C#:

// ----------------------------------------------------------------------------
// Mostrar todos los formularios de una aplicación (ensamblado)     (16/Dic/18)
// Estén abiertos o no
// Usando reflection
// 
// Este código está basado en el artículo que publiqué el 13/Sep/2004 en:
// http://www.elguille.info/NET/dotnet/reflectionTiposdeunensamblado.htm
// 
// 
// (c) Guillermo (elGuille) Som, 2018
// ----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;

namespace Mostrar_Nombres_Formularios_cs
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Para recorrer todos los formularios de un ensamblado
        /// estén abiertos o no
        /// Basado en el código del elGuille.info:
        /// http://www.elguille.info/NET/dotnet/reflectionTiposdeunensamblado.htm
        /// </summary>
        private System.Reflection.Assembly ass;

        /// <summary>
        /// Mostrar todos los formularios de la aplicación actual,
        /// estén o no en memoria, usando reflection.
        /// Además de los formularios, mostrará:
        /// My.Application (solo en VB)
        /// Y todos los nombres esmpiezan con el espacio de nombres
        /// ESPACIO_DE_NOMBRES.NombreForm
        /// </summary>
        private void mostrarForms()
        {
            // llena una colección con los formularios de esta aplicación
            // estén o no en memoria.
            // Muestra el resultado en un listbox

            lbForms.Items.Clear();

            foreach (Type t in ass.GetTypes())
            {
                var nombreTipo = t.BaseType.Name;
                // También tendrá My.Application: (solo en VB)
                // <espacio de nombres>.My.MyApplication
                if (nombreTipo.ToLower().Contains("form"))
                    lbForms.Items.Add(t.FullName);
            }
        }

        /// <summary>
        /// Muestra el formulario indicado en el argumento,
        /// este debe ser con el espacio de nombres completo
        /// 
        /// Si es el actual no lo muestra.
        /// Si da error o no es un formulario se avisa.
        /// </summary>
        private void mostrarFormulario(string s)
        {
            // creamos un tipo a partir del nombre
            Type t = ass.GetType(s);
            // instanciamos un nuevo objeto en la memoria
            object o;

            // por si hemos seleccionado algo que no es una clase
            try
            {
                o = Activator.CreateInstance(t);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, 
                    "Mostrar formularios");
                return;
            }

            // si no es un formulario, mostramos un aviso y salimos
            if (!(o is Form))
            {
                MessageBox.Show(s + ", no es un formulario", 
                    "Mostrar formularios");
                return;
            }

            // convertimos el objeto en un formulario
            Form f = o as Form;
            if (f == null)
            {
                MessageBox.Show(s + ", parece que no es un formulario", 
                    "Mostrar formularios");
                return;
            }

            // si el nombre es el de este formulario,
            // lo cerramos y salimos.
            if (f.Name == this.Name)
            {
                // no volver a crear este formulario
                // f.Close()
                this.BringToFront();

                MessageBox.Show(s + " es el formulario de inicio.", 
                    "Mostrar formularios");

                return;
            }

            // mostramos el formulario.
            f.Show();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // Mostrar esta ventana en el monitor secundario
            MostrarEnVentana2(this);

            // mostrar los formularios de esta aplicación
            ass = System.Reflection.Assembly.GetExecutingAssembly();
            mostrarForms();
        }

        private void btnAbrir_Click(object sender, EventArgs e)
        {
            //' Por si no hay un nombre indicado
            if (String.IsNullOrWhiteSpace(txtForm.Text))
                return;

            //' Abrir el formulario indicado en el textbox
            mostrarFormulario(txtForm.Text);

        }

        private void btnSalir_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void lbForms_SelectedIndexChanged(object sender, EventArgs e)
        {
            txtForm.Text = lbForms.SelectedItem.ToString();
        }

        /// <summary>
        /// Mostrar el formulario indicado en la segunda pantalla
        /// Código adaptado de la respuesta 42 de:
        /// https://stackoverflow.com/questions/2561104/how-do-i-ensure-a-form-displays-on-the-additional-monitor-in-a-dual-monitor-sc
        /// </summary>
        public static void MostrarEnVentana2(Form frm)
        {
            var myScreen = Screen.PrimaryScreen;
            var otherScreen = Screen.AllScreens.FirstOrDefault(s => !s.Equals(myScreen)) 
                                    ?? myScreen;

            //' Si queremos indicar dónde mostrarlo
            //' podemos cambiar los valores de Left y Top
            //'frm.Left = otherScreen.WorkingArea.Left + 12
            //'frm.Top = otherScreen.WorkingArea.Top + 12
        }
    }
}

El enlace para descargar el código completo (tanto de Visual Basic como de C#):

Archivo: Mostar_Nombres_Formularios_20181216_2346.zip (204 KB)
MD5 Checksum: DA004D15933BD82355684AC0F20680B1

Nos vemos.
Guillermo

Mostrar los formularios de nuestra aplicación (aunque no estén abiertos)

Pues eso… que estoy haciendo una aplicación para convertir los Windows Forms en WPF (Xaml) y tengo que recorrer todos los formularios de la aplicación para ir convirtiéndolos y he buscado en Internet cómo hacer eso y… ¡no lo he encontrado!

Mostrar todos los formularios de un ensamblado (aplicación) estén o no abiertos

Así que… me dije que yo tenía algún código haciendo Reflection para mostrar una clase y va y resulta que en ese ejemplo tenía la respuesta que buscaba… ¡lo que no esté en el sitio del Guille! Winking smile

Concretamente en esta página:
Las clases de un ensamblado usando Reflection (por ejemplo para saber los formularios de nuestra aplicación)

Y para que no me vuelva a ocurrir lo mismo en un futuro (ese artículo lo escribí el 13 de septiembre de 2004… ¡casi ná! Smile with tongue out) me he decidido a escribir este nuevo…

No te voy a explicar mucho (eso ya lo hice en ese artículo) solo te mostraré el código de ejemplo (y te pondré el proyecto para que lo puedas descargar).
Y como siempre el código tanto para Visual Basic como para C#.

Primero te muestro el código que recorre los formularios del ensamblado o aplicación (que es lo que realmente te puede interesar) y después te mostraré el resto.

El código para Visual Basic:

    ''' <summary>
    ''' Para recorrer todos los formularios de un ensamblado
    ''' estén abiertos o no
    ''' Basado en el código del elGuille.info:
    ''' http://www.elguille.info/NET/dotnet/reflectionTiposdeunensamblado.htm
    ''' </summary>
    Private ass As System.Reflection.Assembly

    ''' <summary>
    ''' Mostrar todos los formularios de la aplicación actual,
    ''' estén o no en memoria, usando reflection.
    ''' Además de los formularios, mostrará:
    ''' My.Application (solo en VB)
    ''' Y todos los nombres esmpiezan con el espacio de nombres
    ''' ESPACIO_DE_NOMBRES.NombreForm
    ''' </summary>
    Private Sub mostrarForms()
        ' llena una colección con los formularios de esta aplicación
        ' estén o no en memoria.
        ' Muestra el resultado en un listbox

        lbForms.Items.Clear()

        For Each t As Type In ass.GetTypes()
            Dim nombreTipo = t.BaseType.Name
            ' También tendrá My.Application: (solo en VB)
            ' <espacio de nombres>.My.MyApplication
            If nombreTipo.ToLower().Contains("form") Then
                lbForms.Items.Add(t.FullName)
            End If
        Next
    End Sub

El código para C#:

        /// <summary>
        /// Para recorrer todos los formularios de un ensamblado
        /// estén abiertos o no
        /// Basado en el código del elGuille.info:
        /// http://www.elguille.info/NET/dotnet/reflectionTiposdeunensamblado.htm
        /// </summary>
        private System.Reflection.Assembly ass;

        /// <summary>
        /// Mostrar todos los formularios de la aplicación actual,
        /// estén o no en memoria, usando reflection.
        /// Además de los formularios, mostrará:
        /// My.Application (solo en VB)
        /// Y todos los nombres esmpiezan con el espacio de nombres
        /// ESPACIO_DE_NOMBRES.NombreForm
        /// </summary>
        private void mostrarForms()
        {
            // llena una colección con los formularios de esta aplicación
            // estén o no en memoria.
            // Muestra el resultado en un listbox
            lbForms.Items.Clear();

            foreach (Type t in ass.GetTypes())
            {
                var nombreTipo = t.BaseType.Name;
                // También tendrá My.Application: (solo en VB)
                // <espacio de nombres>.My.MyApplication
                if (nombreTipo.ToLower().Contains("form"))
                    lbForms.Items.Add(t.FullName);
            }
        }

Solo comentarte que en el código de Visual Basic he añadido 2 botones extras para mostrar los formularios Form2 y Form3 respectivamente. Esto solo es para probar que se pueden mostrar de las dos formas Smile
Pero en cualquier caso, siempre se muestra un nuevo formulario, esté o no abierto.

En la figura 1 puedes ver la aplicación en funcionamiento, mostrando una lista de los formularios de la aplicación.

mostrar_formularios_01.pg
Figura 1. La aplicación en ejecución mostrando los formularios del ensamblado (aplicación)

Si te fijas en la figura 1, se muestra también «My.MyApplication» que no es un formulario, pero el tipo «base» es Form, y por eso se muestra. Esto no ocurre en C#, ya que C# no tiene la clase My.

Nota:
El código de Visual Basic lo he convertido con una utilidad que hay en la web:
Telerik Code Converter

Un extra: Mostrar un formulario en el segundo monitor

Esto ya lo publicaré otro día (realmente era lo que iba a publicar hoy junto con una explicación de los problemas de nuestro código de Windows Forms y Visual Studio y los monitores HDPI), y es que en el código incluyo cómo hacer que un formulario se muestre en el segundo monitor.

Actualmente estoy usando un portátil con la resolución 1920×1080 y usando el tamaño del texto (etc.) al 100% y un segundo monitor con 3840×2160 y el tamaño del texto, etc. al 150%.

Como te explicaré en otra ocasión, yo uso el Visual Studio abriéndolo desde la pantalla principal (la del portátil al 100%), pero después muevo el IDE de Visual Studio al segundo monitor, por tanto cuando ejecuto el código, lo que se muestra lo hace siempre en la pantalla del portátil, por eso busqué cómo hacer que se muestre un formulario en el segundo monitor, y ¡lo encontré!, eso sí, en código para C#, concretamente en una respuesta en el sitio de StackOverflow en un hilo con la siguiente pregunta: How do I ensure a form displays on the “additional” monitor in a dual monitor scenario?
La respuesta que me sirvió fue la 42, con este código:

var myScreen = Screen.FromControl(originalForm);
var otherScreen = Screen.AllScreens.FirstOrDefault(s => !s.Equals(myScreen)) 
               ?? myScreen;
otherForm.Left = otherScreen.WorkingArea.Left + 120;
otherForm.Top = otherScreen.WorkingArea.Top + 120;

Que traducido a Visual Basic sería algo así:

Dim myScreen = Screen.PrimaryScreen
Dim otherScreen = If(Screen.AllScreens.FirstOrDefault(
                        Function(s) Not s.Equals(myScreen)), myScreen)

Y ¡esto es todo amigo!
Espero , como siempre, que te sea de utilidad y si no… al menos a mí dentro de 14 años me puede ser útil… Winking smile

Nos vemos.
Guillermo

P.S.
El código de ejemplo completo y el enlace para la descarga de los proyectos (hechos con Visual Studio 2017 y .NET 4.7.2, ninguno de estos requisitos son necesarios para el código) te los muestro en otra página.

El código de VB y C# de: Mostrar todos los formularios de una aplicación

Winking smile