Etiqueta: VB.NET

Temas relacionados con Visual Basic para .NET Framework

  • gsColorearNET

    Nota del 26-oct-2020 20:45:
    Esta página estaba originalmente publicada en elguille.info y la he pasado al blog para poder editarla más fácilmente ya que lo que publico en elGuille.info lo hago con un editor de texto normal y corriente… y ¡es un rollo!
    Por supuesto, esta misma página aparecerá en elGuille.info, así que… no se notará mucho que no está realmente ubicada allí.

     

    Esta es una biblioteca (DLL) compilada para .NET Standard 2.0 y así poder usarla en cualquier plataforma que lo acepte, incluidos los proyectos de .NET Framework 4.6.1 a 4.8 y de .NET Core 2.0 a .NET 5.0, entre otros…
    Si quieres ver dónde se pueden usar las DLL compiladas con .NET Standard 2.0 mira este enlace: .NET Standard

    Últimas actualizaciones

    Nota del 24/Oct/2020 (v1.0.0.14)
    He actualizado tanto el paquete de NuGet como el código en GitHub.
    También la utilidad de gsColorearCodigo para que use esta nueva versión.

    Los cambios principales son para no eliminar las líneas en blanco que haya en el código.
    Esto era porque la función Split original de Visual Basic no elimina las líneas en blanco.
    Además de usar vbCr en lugar de vbCrLf al examinar cada línea y crear nuevas separaciones, ya que al añadir vbCrLf añadía una línea extra en blanco.

    Aunque últimamente se me ha dado el problema que no todos los ficheros tienen el mismo tipo de retorno de carro.
    Por tanto he tenido que comprobar antes de hacer el Split qué tipo de retorno de carro tiene: vbCrLf o vbCr o vbLf.

    Nota del 16/Sep/2020 (v1.0.0.7)
    He actualizado tanto el paquete de NuGet como el código en GitHub.
    También la utilidad de gsColorearCodigo para que use esta nueva versión.

    Los cambios principales son para no eliminar las líneas en blanco que haya en el código.
    Esto era porque la función Split original de Visual Basic no elimina las líneas en blanco.
    Además de usar vbCr en lugar de vbCrLf al examinar cada línea y crear nuevas separaciones, ya que al añadir vbCrLf añadía una línea extra en blanco.

    Nota del 13/Sep/2020 (v1.0.0.6)
    He actualizado tanto el paquete de NuGet como el código en GitHub.
    También la utilidad de gsColorearCodigo para que use esta nueva versión.

    Con fecha del 12 de septiembre de 2020 he creado un repositorio en gitHub para el código de gsColorearNET.

    De ahí puedes descargar el proyecto completo a excepción del fichero de nombre seguro (.snk)

    Este es el enlace: gsColorearNET en gitHub.

    Y este es el enlace a los paquetes de NuGet: gsColorearNET en NuGet.

    Estoy probando la utilidad de colorear en .NET 5.0 Preview 8 y a duras penas ya está operativa… es que el editor de Visual Studio 2019 Preview está aún muy verde para las aplicaciones de Windows Forms para Visual Basic (y para C# tampoco está muy fino).

    El hacerlo con esa versión es para poder depurar el código de la DLL de colorear, ya que en un proyecto de .NET framework no se puede… o yo no sé cómo hacerlo… todo hay que decirlo.

    Cuando tenga tiempo publicaré en el blog las cosillas que recomiendo hacer hasta que mejoren el editor/diseñador de WinForms para Visual Basic.

    NOTA:
    Aún la estoy probando desde NuGet ya que usándola como proyecto compila y funciona bien, pero al publicar el paquete en NuGet (aquí tienes el enlace: gsColorearNET en NuGet), no me encuentra los lenguajes de las palabras clave.
    ¡Esto último ya está solucionado con el paquete 1.0.0.1!
    Smile

    He publicado la utilidad de colorear código (gsColorearCodigo) para instalar con ClickOnce que utiliza el paquete de NuGet 1.0.0.1 y… ¡funciona a la perfección!

    Por ahora no te voy a poner el código fuente, en realidad ha cambiado poco desde lo que publiqué anteayer, y como lo que quiero añadir o corregir aún lo tengo que hacer… pues… habrá que esperar unos días a que lo tenga terminado y así ya la publico de forma, que salvo que haya algunos fallos, no tenga que modificarla en algún tiempo.

    Lo que sí haré es actualizar el paquete de NuGet con las correcciones que le vaya haciendo.

    Sobre el uso de un proyecto DLL de .NET Standard con un proyecto de .NET Framework

    Probando el código de gsColorearCodigo usando el .NET 4.8 en Visual Studio 2019 con el proyecto de gsColorearNET usando .NET Standard 2.0, al producirse un error (o sin que se produzca) y querer depurar en el código de la DLL, el VS no me dejaba…
    Así que… para comprobar porqué fallaba el penúltimo cambio que le hice, tuve que
    abrir un proyecto de .NET 5.0 (Preview 8) usando el Visual Studio Preview, y en ese entorno si pude depurar y averiguar cuál era el fallo… que después resultó ser algo trivial, pero…

    Así qué… ya sabes… si mezclas… no debugues… 😉

    Usar código de Visual Basic en .NET Standard

    Otra de las cosillas que me he encontrado a la hora de poder compilar el código del proyecto gsColorear para .NET Framework (ya hay que ir haciendo las aclaraciones de que no todo es simplemtente .NET, porque tenemos .NET Framework, .NET Core, .NET Standard y… casi ya… también simplemente .NET refiriéndose a .NET Core) es la definición de algunas de las funciones del ensamblado Microsoft.VisualBasic en concreto de la clase Strings que no están definidas en .NET Standard 2.0, tal como:
    Len, Left, Mid, Right, Split, InStr y Trim.

    Para no tener que cambiar todo el código que usaba esas funciones (recuerda que el código de colorear lo hice sobre el año 2001, sí, con Visual Basic 6.0, después en diciembre del 2002 lo pasé a la beta de Visual Studio .NET, la aplicación de aquél entonces era HTMLColorCode, aunque debo tener otra aplicación llamada gsEditor… el tiempo no perdona… por la memoria…) así que… me he creado una clase en la que
    he definido esas funciones, que (seguramente) pueden mejorarse, pero… así las he programado / codificado / como prefieras decirlo.

    Y te pego aquí el código por si te puede ser de ayuda.

    '------------------------------------------------------------------------------
    ' Clase definida en la biblioteca para .NET Standard 2.0            (10/Sep/20)
    ' Basada en gsColorear y gsColorearCore
    '
    ' VBCompat                                                          (10/Sep/20)
    ' Clase con instrucciones para compatibilidad con .NET Standard 2.0
    '
    ' Declaro algunas funciones de Microsoft.VisualBasic.Strings
    ' que no están en .NET Standard 2.0
    '
    ' (c) Guillermo (elGuille) Som, 2020
    '------------------------------------------------------------------------------
    Option Strict On
    Option Infer On
    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Collections.Generic
    'Imports System.Data
    Public Class VBCompat
        ''' <summary>
        ''' Devuelve los caracteres desde la posición (en base 1)
        ''' hasta el final.
        ''' </summary>
        ''' <param name="str"></param>
        ''' <param name="pos"></param>
        Public Shared Function Mid(str As String, pos As Integer) As String
            Return str.Substring(pos - 1)
        End Function
        ''' <summary>
        ''' Devuelve la cadena desde la posición indicada con len caracteres.
        ''' La posición del primer carácter es el 1.
        ''' </summary>
        ''' <param name="str"></param>
        ''' <param name="pos"></param>
        ''' <param name="len"></param>
        ''' <remarks>10/Sep/20/20</remarks>
        Public Shared Function Mid(str As String, pos As Integer, len As Integer) As String
            Return str.Substring(pos - 1, len)
        End Function
        ''' <summary>
        ''' Devuelve el número de caracteres.
        ''' Si es cadena vacía o nulo devuelve 0.
        ''' </summary>
        ''' <param name="str"></param>
        ''' <returns></returns>
        Public Shared Function Len(str As String) As Integer
            If String.IsNullOrEmpty(str) Then Return 0
            Return str.Length
        End Function
        ''' <summary>
        ''' Devuelve los primeros caracteres de la cadena.
        ''' </summary>
        ''' <param name="str"></param>
        ''' <param name="len"></param>
        ''' <returns></returns>
        Public Shared Function Left(str As String, len As Integer) As String
            Return str.Substring(0, If(len > str.Length, str.Length, len))
        End Function
        ''' <summary>
        ''' Devuelve los caracteres indicados desde la derecha.
        ''' </summary>
        ''' <param name="str"></param>
        ''' <param name="len"></param>
        ''' <returns></returns>
        Public Shared Function Right(str As String, len As Integer) As String
            Dim iPos = str.Length - len
            Return str.Substring(iPos, len)
        End Function
        ''' <summary>
        ''' Devuelve la posición (en base 1) de la segunda cadena en la primera
        ''' </summary>
        ''' <param name="str1"></param>
        ''' <param name="str2"></param>
        ''' <returns></returns>
        Public Shared Function InStr(str1 As String, str2 As String) As Integer
            Return str1.IndexOf(str2) + 1
        End Function
        ''' <summary>
        ''' Devuelve la posición (en base 1) de la segunda cadena en la primera 
        ''' empezando en la posición indicada.
        ''' </summary>
        ''' <param name="startPos"></param>
        ''' <param name="str1"></param>
        ''' <param name="str2"></param>
        ''' <returns></returns>
        Public Shared Function InStr(startPos As Integer, str1 As String, str2 As String) As Integer
            Return str1.IndexOf(str2, startPos - 1) + 1
        End Function
        ''' <summary>
        ''' Devuelve una cadena después de haber quitado 
        ''' los espacios delante y detrás.
        ''' </summary>
        ''' <param name="str"></param>
        ''' <returns></returns>
        Public Shared Function Trim(str As String) As String
            Return str.Trim
        End Function
        ''' <summary>
        ''' Divide una cadena en elementos de un array.
        ''' Usando el delimitador indicado.
        ''' </summary>
        ''' <param name="Expression"></param>
        ''' <param name="Delimiter"></param>
        ''' <returns></returns>
        Public Shared Function Split(Expression As String, Optional Delimiter As String = " ") As String()
            Return Expression.Split(Delimiter.ToCharArray, StringSplitOptions.RemoveEmptyEntries)
        End Function
        ''
        '' El código IL de Prueba1 es más corto (y parece que eficiente) que el de Prueba2
        ''
        'Public Shared Function Prueba1(str As String, len As Integer) As String
        '    Return str.Substring(0, If(len > str.Length, str.Length, len))
        'End Function
        'Public Shared Function Prueba2(str As String, len As Integer) As String
        '    If len > str.Length Then
        '        len = str.Length
        '    End If
        '    Return str.Substring(0, len)
        'End Function
    End Class
    

    Y esto es todo por ahora…

    Espero que te sea de utilidad

    Nos vemos.
    Guillermo

     

     
    El código fuente completo

    El código para Visual Basic con el proyecto para Visual Studio 2019 está publicado en gitHub.

     

    Este es el enlace: gsColorearNET en gitHub.

     

    Y este es el enlace a los paquetes de NuGet: gsColorearNET en NuGet.

     

     

  • Truco por si asignas la posición del formulario a una guardada y cambias de tipo de pantalla

    Pues eso… que hace poco mandé al servicio técnico de LG la pantalla externa que conecto a mi ordenador portátil y estoy teniendo problemas cuando abro las aplicaciones que he estado usando con ese monitor, al menos las que tengo programadas para que al cambiar la posición o el tamaño se guardan en un fichero de configuración para cuando cargue de nuevo esa aplicación se muestre donde estuvo la vez anterior.

    Una de las opciones por la que opté fue poner que siempre se mostrasen en el centro de la pantalla, pero con el tamaño indicado en el diseño del formulario.

    La idea que se me ha ocurrido esta mañana es la de comprobar dónde está la posición Left y Top guardadas y si estarían fuera del rango de esos mismos valores de las propiedades de el WorkingArea de PrimaryScreen.

    Los valores de alto y ancho (Height y Width) no los toco, ya que el usuario podrá cambiar esos tamaños a su antojo, ya que ahora sí que podrá ver la ventana de la aplicación.

    Este es el código para Visual Basic con el que hago la comprobación que te he mencionado:

    ' Asignar el tamaño y última posición
    ' Comprobar que esté en la parte visible                    (24/Oct/20)
    Dim l = cfg.GetValue("Ventana", "Left", Me.Left)
    Dim t = cfg.GetValue("Ventana", "Top", Me.Top)
    If Screen.PrimaryScreen.WorkingArea.Left < l Then
        Me.Left = cfg.GetValue("Ventana", "Left", Me.Left)
    Else
        Me.Left = 0
    End If
    If Screen.PrimaryScreen.WorkingArea.Top < t Then
        Me.Top = cfg.GetValue("Ventana", "Top", Me.Top)
    Else
        Me.Top = 0
    End If
    Me.Height = cfg.GetValue("Ventana", "Height", Me.Height)
    Me.Width = cfg.GetValue("Ventana", "Width", Me.Width)
    

    Los valores de la posición y tamaño del formulario los obtengo de un fichero de configuración y solo asigno el valor Left si la posición Left de WorkingArea es menor, ya que cuando está en el monitor externo (al menos en mi caso) el valor de Left suele ser negativo.
    Y con el valor Top hacemos lo mismo, solo asignarlo si no es menor que el valor Top del área de trabajo de la pantalla principal.

     

    Y aquí tienes el mismo código para C#:

    // Asignar el tamaño y última posición
    // Comprobar que esté en la parte visible                    (24/Oct/20)
    var l = cfg.GetValue("Ventana", "Left", this.Left);
    var t = cfg.GetValue("Ventana", "Top", this.Top);
    if (Screen.PrimaryScreen.WorkingArea.Left < l)
        this.Left = cfg.GetValue("Ventana", "Left", this.Left);
    else
        this.Left = 0;
    
    if (Screen.PrimaryScreen.WorkingArea.Top < t)
        this.Top = cfg.GetValue("Ventana", "Top", this.Top);
    else
        this.Top = 0;
    
    this.Height = cfg.GetValue("Ventana", "Height", this.Height);
    this.Width = cfg.GetValue("Ventana", "Width", this.Width);
    

     

    Y esto es todo, espero que te haya sido de utilidad.

     

    Nos vemos.
    Guillermo

  • El porqué C# siempre tendrá novedades aunque Visual Basic ya no

    Pues eso… el otro día estaba leyendo un artículo de Anthony D. Green (miembro del team de Visual Basic de Microsoft del 2010 al 2018) sobre todo lo relacionado con la que se lio por el tema de que a Visual Basic no se le añadirán nuevas características, (
    Future features of .NET Core that require language changes may not be supported in Visual Basic.), pero no es de eso de lo que te quiero hablar aquí. Es de lo que dice Anthony en su artículo.

    Concretamente esta parte es la que me ha hecho reflexionar un poco sobre C#:

    C# advances the .NET platform.
    I’m not begrudging or envying them that role but recognizing that that’s what the language has always done where VB is traditionally focused on innovation in experience.
    It’s not that you can’t write a library or a framework in VB (and people have) but the .NET platform is not and will never be dependent on the VB language (or F#) to make leaps.
    But if C# is late developing generics, .NET 2.0 doesn’t ship.
    If C# hasn’t figured out the shape and behavior of nullable value types those types can’t appear in any new APIs.
    If it’s late on LINQ, .NET 3.5 doesn’t ship.
    If async isn’t complete, .NET 4.5 can’t ship with new asynchronous APIs.
    If C# language design can’t converge on ref returns or nullable annotations the platform teams (like mscorlib) that depend on those features literally cannot ship their platforms for anyone.
    And for what it’s worth, C# is ALWAYS late on those things (a fact I learned too late) because getting it right takes all the time in the world.
    Which is why it’s insane (in hindsight) to envision an “ideal” world where you couple or serialize a language which does not fulfill that mission critical role with so many downstream dependencies and its customers’ productivity with one that does and expect good things for both of them.

    Extracto de: Un manual sobre por qué el sufrimiento crónico de la comunidad de VB.NET no es necesario ni una cuestión de gastos o practicidad

    Es decir, C# tiene que estar siempre actualizado ya que la plataforma .NET depende de C# (o casi). El casi es porque es el lenguaje de .NET que Microsoft tiene para poder usar las novedades que se agreguen a .NET.

    Y como ahora .NET ya no será una continua actualización de .NET Framework, si no de .NET Core (multiplataforma), es lógico que también deba incorporar las novedades enfocadas a ser utilizado tanto en Windows como en MacOS, Linux, iOS, Android, etcétera.

    ¿Debo olvidarme de Visual Basic y pasarme a C#?

    Esto no significa que a Visual Basic no se le deba seguir añadiendo nuevas características en el lenguaje, que según dice Anthony en su artículo es posible hacerlo si Microsoft dedica un par de profesionales a seguir manteniendo el lenguaje, que de otra parte puede recibir ayuda de la comunidad, como ya lo ha hecho con la última incorporación al lenguaje: Comentarios permitidos en más lugares dentro de las instrucciones que precisamente la ha agregado un participante de la comunidad: Paul1956 (Paul M Cohen).

    Lo que sí tendrá Visual Basic son nuevas funcionalidades en el editor de Visual Studio (ver figura 1), pero no tendrá, por ejemplo el equivalente a record (registro) o init (establecedor de solo inicialización) en las propiedades.

    Figura 1. Mostrar Inline parameters (parámetros en línea)

    Así que… si quieres tener un lenguaje de programación para .NET que esté siempre actualizado a las novedades de la plataforma .NET, debes decantarte por C#.

    Si no te gusta programar en C# pero sí en Visual Basic, recuerda que este último se quedará estancado en la versión 16.0, mientras que C# seguirá avanzando.
    Eso no significa que no puedas seguir usando Visual Basic.

    Pero si eres de los que quiere usar .NET 5.0 o las versiones que sigan apareciendo (cada año habrá una nueva y por tanto tendrá cosas nuevas), recuerda que podrás hacerlo, pero con las cosas que actualmente tiene Visual Basic.

    Y si eres de los que no quieren usar nada relacionado con .NET / .NET Core / .NET Standard, podrás seguir usando Visual Basic en .NET Framework 4.8 (o anteriores), aunque este último seguirá estando disponible mientras Windows exista.

    Resumiendo:
    No te quedarás obsoleto si sigues usando Visual Basic. Pero si quieres poder usar en tu código las novedades agregadas a .NET tendrás que plantearte el cambio a C#, aunque sea para poder crear alguna biblioteca de clases que utilice esas novedades de .NET y las pongas a disposición de tu código de Visual Basic (la cuestión es querer arreglar las cosas 😉 ).

    Aprender C#

    Y si quieres pasarte a C#, ya sabes que en elGuille.info (y en este blog) tienes un montón de código en C# con su equivalente en Visual Basic (o viceversa), ya que desde enero de 2001 (sí, hace ya 19 añitos de nada) todo (o prácticamente todo) lo que he ido publicando para Visual Basic (trucos, API, utilidades, WPF/XAML, etc.) está con el código para los dos lenguajes. Y, lo más importante: ¡TODO GRATIS! (aunque también puedes hacer una donación con PayPal 😉 ).

    Por supuesto también puedes apuntarte a algunos de los muchos cursos que hay en las plataformas de enseñanza online y aprender (pagando) el lenguaje C#.

    Cómo lo hagas, si decides hacerlo, es cuestión tuya.

    Por mi parte, seguiré usando Visual Basic como lenguaje de programación principal, sin olvidarme de C# e ir aprendiendo las cosas nuevas que vayan apareciendo.
    Tanto de uno como de otro lenguaje, iré publicando artículos para que te sirva de aprendizaje o para que te aclares un poco más

    En un próximo artículo te explicaré algunas de las novedades de C# 9.0 como son los tipos de registro (record), inicializadores en las propiedades (init) o instrucciones de nivel superior (Top-level statements).

    Nos vemos.
    Guillermo

    P.S.
    Traducción (automatizada del párrafo en inglés):

    C# avanza la plataforma .NET.
    No les estoy regateando ni envidiándoles ese papel, pero reconozco que eso es lo que siempre ha hecho el lenguaje, donde VB se centra tradicionalmente en la innovación en la experiencia.
    No es que no pueda escribir una biblioteca o un marco de trabajo en VB (y la gente lo ha hecho), pero la plataforma .NET no depende y nunca dependerá del lenguaje VB (o F #) para avanzar.
    Pero si C# desarrolla genéricos tarde, .NET 2.0 no sale.
    Si C# no ha descubierto la forma y el comportamiento de los tipos de valores que aceptan valores NULL, esos tipos no pueden aparecer en ninguna API nueva.
    Si llega tarde en LINQ, .NET 3.5 no se distribuye.
    Si async no está completo, .NET 4.5 no se puede enviar con nuevas API asincrónicas.
    Si el diseño del lenguaje C# no puede converger en devoluciones de referencia o anotaciones que aceptan valores NULL, los equipos de la plataforma (como mscorlib) que dependen de esas características, literalmente, no pueden enviar sus plataformas a nadie.
    Y por si sirve de algo, C# SIEMPRE llega tarde en esas cosas (un hecho que aprendí demasiado tarde) porque hacerlo bien lleva todo el tiempo del mundo.
    Es por eso que es una locura (en retrospectiva) imaginar un mundo «ideal» en el que se acopla o serializa un lenguaje que no cumple esa función crítica con tantas dependencias posteriores y la productividad de sus clientes con uno que sí y espera cosas buenas para ambos.