none
Cambiar Configuración Regional VB (Aplicación para Windows 10) RRS feed

  • Pregunta

  • Buenas tardes estoy tratando de cambiar la configuración regional de mi aplicación con:

    Dim Config As Globalization.CultureInfo
    Config = Application.CurrentCulture.Clone
    Config.NumberFormat.NumberGroupSeparator = ","
    Config.NumberFormat.CurrencyGroupSeparator = ","
    Config.NumberFormat.NumberDecimalSeparator = "."
    Config.NumberFormat.CurrencyDecimalSeparator = "."
    Config.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy"
    Application.CurrentCulture = Config

    Le hago una parada para ver el   Application.CurrentCulture.NumberFormat.NumberDecimalSeparator   y me arroja que es "." lo cual es correcto según el código anterior, el problema esta en que no me cambia el separador decimal de las variables Double, es decir   el valor de la variable 11,45  no lo cambia por 11.45.

    Si pudieran ayudarme se los agradecería mucho, Gracias


    miércoles, 6 de septiembre de 2017 18:50

Respuestas

  • "colososhark" escribió:

    > Dim Config As Globalization.CultureInfo
    > Config = Application.CurrentCulture.Clone
    > Config.NumberFormat.NumberGroupSeparator = ","
    > Config.NumberFormat.CurrencyGroupSeparator = ","
    > Config.NumberFormat.NumberDecimalSeparator = "."
    > Config.NumberFormat.CurrencyDecimalSeparator = "."
    > Config.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy"
    > Application.CurrentCulture = Config
    >
    > ... lo que sucede, y no se por qué, es que cuando se llama a un BackgroundWorker
    > el código que está en ese subProceso pierde la configuración regional que se coloca
    > al principio.  Por lo tanto para solucionar el problema fue llamar al método de la
    > configuración regional en el BackgroundWorker_DoWork para que tomara en cuenta la
    > misma y listo.

    Hola:

    Si le asignas el objeto CultureInfo que representa la variable llamada 'Config' a la propiedad compartida Application.CurrentCulture, lo que estás haciendo es modificar la referencia cultural del subproceso actual, que en principio será aquel que ha iniciado tu aplicación: el subproceso principal.

    Si desde ese subproceso principal posteriormente inicias otros subprocesos diferentes (como bien puede ser aquel generado por el control BackgroundWorker), su referencia cultura será por defecto la que tengas instalada en la configuración regional de tu sistema operativo, no la del objeto Application.CurrentCulture (aunque la palabra "Application" de indicios que se trata de la aplicación actual) que como he indicado anteriormente, será la referencia cultural del subproceso principal, por tanto, tendrás que asignarle al nuevo subproceso iniciado la misma referencia cultural de aquella que tiene el subproceso principal.

    >  No se si existe alguna otra forma de solucionar ese caso en específico.

    No has indicado en qué parte de tu aplicación se ejecuta el código fuente que has publicado en tu primera pregunta. Vamos a suponer que se ejecuta en el evento Load del formulario de inicio de la aplicación. Si es así, en lugar de definir la variable local a nivel del procedimiento Load:

        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

            Dim Config As Globalization.CultureInfo

            ' resto del código fuente

        End Sub

    Defínela como un campo del propio formulario que contiene el control BackgroundWorker para que dicha variable se la puedas asignar posteriormente al control BackgroundWorker en su evento DoWork, tal y como muestra el siguiente ejemplo:

    Public Class Form1
    
        Private Config As Globalization.CultureInfo
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            ' Clonamos la información de referencia cultural del subproceso actual. 
            Config = DirectCast(Application.CurrentCulture.Clone, Globalization.CultureInfo)
    
            Config.NumberFormat.NumberGroupSeparator = ","
            Config.NumberFormat.CurrencyGroupSeparator = ","
            Config.NumberFormat.NumberDecimalSeparator = "."
            Config.NumberFormat.CurrencyDecimalSeparator = "."
            Config.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy"
    
            Application.CurrentCulture = Config
    
        End Sub
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    
            ' A la referencia cultural del subproceso actual le
            ' asignamos el valor que tiene actualmente el campo
            ' del formulario llamado 'Config'.
            '
            Threading.Thread.CurrentThread.CurrentCulture = Config
    
            Dim d As Double = 11.45D
            MessageBox.Show(d.ToString())
    
            ' Resto del código que se ejecuta en el evento DoWork
            '
            ' ...
            ' ...
    
        End Sub
    
    End Class

    Y aquí tiene la captura de pantalla del cuadro de mensaje que se ejecuta en el evento DoWork, donde se observa que el carácter separador decimal es el punto decimal (.) en lugar de la coma decimal (,):

    ¿Que el procedimiento de inicio de tu aplicación no es un formulario si no el procedimiento Sub Main de un Module? Entonces declara el campo como amigable (Friend) en el Module y lo configuras en el método Sub Main:

    Public Module NombreModulo
    
        Friend Config As Globalization.CultureInfo
    
        Public Sub Main()
    
            Application.EnableVisualStyles()
    
            ' Clonamos la información de referencia cultural del subproceso actual. 
            Config = DirectCast(Application.CurrentCulture.Clone, Globalization.CultureInfo)
    
            Config.NumberFormat.NumberGroupSeparator = ","
            Config.NumberFormat.CurrencyGroupSeparator = ","
            Config.NumberFormat.NumberDecimalSeparator = "."
            Config.NumberFormat.CurrencyDecimalSeparator = "."
            Config.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy"
    
            Application.CurrentCulture = Config
    
            Application.Run(New Form2())
    
        End Sub
    
    End Module

    ¡Pues, bien! Explicado los motivos por el cual el objeto BackgroundWorker no toma la referencia cultural del subproceso de inicio de la aplicación, no voy a ser yo el que te aconseje modificar la referencia cultural de tu aplicación para que ésta sea distinta a la existente en el propio sistema operativo, porque lo único que puede ocurrir es que el usuario de tu aplicación esté todo el día quejándose cuando observe que en los distintos controles aparecen los valores decimales separados con el carácter del punto decimal (12,223.34) en lugar de aparecer separados con el carácter de la coma decimal (12.223,34), máxime si tiene instalado en su equipo una configuración regional de español de España, o de cualquier otro país donde el carácter separador decimal sea la coma decimal (,). Aparte, que si el usuario escribe en un control TextBox un número con la coma decimal, ¿cómo interpretaría tu aplicación dicho número cuando ésta trabaja con una configuración numérica de inglés de Estados Unidos? ¿Será un número válido o no válido? Para el usuario sería totalmente válido, ya que él está acostumbrado a escribir así los números decimales.

    Como suelo decir, es obligación del programador adaptarse en todo momento a la configuración regional que tenga el usuario establecida en su sistema operativo, y no al contrario. ;-)

    Un saludo


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    jueves, 7 de septiembre de 2017 15:37
    Moderador

Todas las respuestas

  • Buenas tardes ya conseguí cual era el problema, efectivamente el código que coloqué arriba si funciona bien, lo que sucede, y no se por qué, es que cuando se llama a un BackgroundWorker el código que está en ese subProceso pierde la configuración regional que se coloca al principio.  Por lo tanto para solucionar el problema fue llamar al método de la configuración regional en el BackgroundWorker_DoWork para que tomara en cuenta la misma y listo.  No se si existe alguna otra forma de solucionar ese caso en específico.
    miércoles, 6 de septiembre de 2017 21:15
  • "colososhark" escribió:

    > Dim Config As Globalization.CultureInfo
    > Config = Application.CurrentCulture.Clone
    > Config.NumberFormat.NumberGroupSeparator = ","
    > Config.NumberFormat.CurrencyGroupSeparator = ","
    > Config.NumberFormat.NumberDecimalSeparator = "."
    > Config.NumberFormat.CurrencyDecimalSeparator = "."
    > Config.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy"
    > Application.CurrentCulture = Config
    >
    > ... lo que sucede, y no se por qué, es que cuando se llama a un BackgroundWorker
    > el código que está en ese subProceso pierde la configuración regional que se coloca
    > al principio.  Por lo tanto para solucionar el problema fue llamar al método de la
    > configuración regional en el BackgroundWorker_DoWork para que tomara en cuenta la
    > misma y listo.

    Hola:

    Si le asignas el objeto CultureInfo que representa la variable llamada 'Config' a la propiedad compartida Application.CurrentCulture, lo que estás haciendo es modificar la referencia cultural del subproceso actual, que en principio será aquel que ha iniciado tu aplicación: el subproceso principal.

    Si desde ese subproceso principal posteriormente inicias otros subprocesos diferentes (como bien puede ser aquel generado por el control BackgroundWorker), su referencia cultura será por defecto la que tengas instalada en la configuración regional de tu sistema operativo, no la del objeto Application.CurrentCulture (aunque la palabra "Application" de indicios que se trata de la aplicación actual) que como he indicado anteriormente, será la referencia cultural del subproceso principal, por tanto, tendrás que asignarle al nuevo subproceso iniciado la misma referencia cultural de aquella que tiene el subproceso principal.

    >  No se si existe alguna otra forma de solucionar ese caso en específico.

    No has indicado en qué parte de tu aplicación se ejecuta el código fuente que has publicado en tu primera pregunta. Vamos a suponer que se ejecuta en el evento Load del formulario de inicio de la aplicación. Si es así, en lugar de definir la variable local a nivel del procedimiento Load:

        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

            Dim Config As Globalization.CultureInfo

            ' resto del código fuente

        End Sub

    Defínela como un campo del propio formulario que contiene el control BackgroundWorker para que dicha variable se la puedas asignar posteriormente al control BackgroundWorker en su evento DoWork, tal y como muestra el siguiente ejemplo:

    Public Class Form1
    
        Private Config As Globalization.CultureInfo
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            ' Clonamos la información de referencia cultural del subproceso actual. 
            Config = DirectCast(Application.CurrentCulture.Clone, Globalization.CultureInfo)
    
            Config.NumberFormat.NumberGroupSeparator = ","
            Config.NumberFormat.CurrencyGroupSeparator = ","
            Config.NumberFormat.NumberDecimalSeparator = "."
            Config.NumberFormat.CurrencyDecimalSeparator = "."
            Config.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy"
    
            Application.CurrentCulture = Config
    
        End Sub
    
        Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    
            ' A la referencia cultural del subproceso actual le
            ' asignamos el valor que tiene actualmente el campo
            ' del formulario llamado 'Config'.
            '
            Threading.Thread.CurrentThread.CurrentCulture = Config
    
            Dim d As Double = 11.45D
            MessageBox.Show(d.ToString())
    
            ' Resto del código que se ejecuta en el evento DoWork
            '
            ' ...
            ' ...
    
        End Sub
    
    End Class

    Y aquí tiene la captura de pantalla del cuadro de mensaje que se ejecuta en el evento DoWork, donde se observa que el carácter separador decimal es el punto decimal (.) en lugar de la coma decimal (,):

    ¿Que el procedimiento de inicio de tu aplicación no es un formulario si no el procedimiento Sub Main de un Module? Entonces declara el campo como amigable (Friend) en el Module y lo configuras en el método Sub Main:

    Public Module NombreModulo
    
        Friend Config As Globalization.CultureInfo
    
        Public Sub Main()
    
            Application.EnableVisualStyles()
    
            ' Clonamos la información de referencia cultural del subproceso actual. 
            Config = DirectCast(Application.CurrentCulture.Clone, Globalization.CultureInfo)
    
            Config.NumberFormat.NumberGroupSeparator = ","
            Config.NumberFormat.CurrencyGroupSeparator = ","
            Config.NumberFormat.NumberDecimalSeparator = "."
            Config.NumberFormat.CurrencyDecimalSeparator = "."
            Config.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy"
    
            Application.CurrentCulture = Config
    
            Application.Run(New Form2())
    
        End Sub
    
    End Module

    ¡Pues, bien! Explicado los motivos por el cual el objeto BackgroundWorker no toma la referencia cultural del subproceso de inicio de la aplicación, no voy a ser yo el que te aconseje modificar la referencia cultural de tu aplicación para que ésta sea distinta a la existente en el propio sistema operativo, porque lo único que puede ocurrir es que el usuario de tu aplicación esté todo el día quejándose cuando observe que en los distintos controles aparecen los valores decimales separados con el carácter del punto decimal (12,223.34) en lugar de aparecer separados con el carácter de la coma decimal (12.223,34), máxime si tiene instalado en su equipo una configuración regional de español de España, o de cualquier otro país donde el carácter separador decimal sea la coma decimal (,). Aparte, que si el usuario escribe en un control TextBox un número con la coma decimal, ¿cómo interpretaría tu aplicación dicho número cuando ésta trabaja con una configuración numérica de inglés de Estados Unidos? ¿Será un número válido o no válido? Para el usuario sería totalmente válido, ya que él está acostumbrado a escribir así los números decimales.

    Como suelo decir, es obligación del programador adaptarse en todo momento a la configuración regional que tenga el usuario establecida en su sistema operativo, y no al contrario. ;-)

    Un saludo


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.


    jueves, 7 de septiembre de 2017 15:37
    Moderador
  • Gracias Enrique por tu comentario, el cambio de configuración regional yo lo realizo en un método de un módulo, dicho método lo llamo en el load del formulario cuando abre la aplicación, en el caso del BackgroundWorker lo que hice fue llamar nuevamente al método dentro del BackgroundWorker para que cambiara la configuración regional.

    Con respecto a que "es obligación del programador adaptarse en todo momento a la configuración regional que tenga el usuario establecida en su sistema operativo, y no al contrario." es discutible, ya que si tratas de realizar eso y te topas con una configuración regional que no tienes contemplada entonces y solo entonces el sistema puede fallar, a diferencia de forzar al sistema a trabajar con una configuración regional específico, con lo cual ya se sabe de antemano que no va a fallar sin importar que configuración regional pueda tener el Sistema Operativo.  

    También sería importante en cuanto a líneas de código: ¿Cuántas líneas puede tomar la validación de las configuraciones regionales para adaptarse al que posee el Sistema Operativo?, ya que el cambio de configuración regional del sistema no toma mas de 10 líneas.

    Me gustaría saber su opinión, Saludos y Abrazos

     
    viernes, 22 de septiembre de 2017 14:03
  • "colososhark" escribió:

    > Con respecto a que "es obligación del programador adaptarse en todo momento a la
    > configuración regional que tenga el usuario establecida en su sistema operativo,
    > y no al contrario." es discutible, ya que si tratas de realizar eso y te topas
    > con una configuración regional que no tienes contemplada entonces y solo entonces
    > el sistema puede fallar, a diferencia de forzar al sistema a trabajar con una
    > configuración regional específico, con lo cual ya se sabe de antemano que no va
    > a fallar sin importar que configuración regional pueda tener el Sistema Operativo. 
    >
    > Me gustaría saber su opinión

    No voy a entrar en discusiones, y por supuesto, respeto tu opinión sobre que el tema es discutible, pero desde luego, no la comparto. Como escribes que te gustaría conocer mi opinión, solo comentarte que el sistema operativo está instalado en mi PC, y está configurado a mi manera y a mis preferencias personales. Cualquier programa que yo instale y observe que me modifica la configuración regional que yo tengo configurada sin mi autorización, y no la restaura al finalizar la ejecución del mismo, te puedo asegurar que en un abrir y cerrar de ojos ese programa está desinstalado de mi sistema operativo: no le doy ningún plazo de gracia.

    Debes de tener en cuenta que la configuración regional afecta a TODOS LOS PROGRAMAS instalados en el sistema operativo, y no solamente a aquel que la ha modificado, por lo que las modificaciones efectuadas pueden afectar a la presentación de los resultados realizados por otros programas que sí han realizado bien su trabajo teniendo en cuenta la configuración regional que actualmente tiene el usuario instalada en su sistema operativo.

    Si yo estoy acostumbrado a escribir y leer los números decimales con el separador de la coma decimal, entre otros caracteres como puede ser el símbolo de moneda, ¿por qué "narices" los voy a tener que escribir y leer con el separador del punto decimal, o con el símbolo de moneda que tenga la configuración regional que el desarrollador del programa me ha querido IMPONER por no realizar bien su trabajo, bien por dejadez o por ignorancia supina? Cuando haga bien su trabajo, lo mismo vuelvo a instalar su programa. ;-)

    Y en cuanto a lo que comentas sobre que "el sistema puede fallar", entiendo que te referirás a que puede fallar tu sistema. Si es así, no me queda más que pensar que algo no has hecho bien, porque si te hubieras adaptado a la configuración regional que el usuario tiene establecida, ¿por qué motivo va a fallar entonces?

    > También sería importante en cuanto a líneas de código: ¿Cuántas líneas puede tomar
    > la validación de las configuraciones regionales para adaptarse al que posee el
    > Sistema Operativo?, ya que el cambio de configuración regional del sistema no toma
    > mas de 10 líneas.

    ¡Buf! Si te soy sincero, no me acuerdo de los años que hace ya que me olvidé de contar las líneas de código, porque deberías de saber que una cosa es lo que tú escribas y otra muy diferente lo que el compilador escriba después. Lo mismo te estás ahorrando en escribir 20 líneas de código y el compilador las sustituye después por 100 líneas, creándote a lo mejor hasta clases privadas intermedias que ignoras por completo que ello haya podido suceder, hasta que te das cuenta cuando analizas el código del  Lenguaje Intermedio de Microsoft (más conocido como código MSIL o IL) existente en el archivo ejecutable de tu aplicación.

    No me acuerdo en estos momentos el nombre de la persona que escribió algo parecido a que ya hay muchos sistemas rápidos pero inseguros. Si programamos teniendo siempre en mente la seguridad, no hay que estar pensando en ahorrar líneas de código creyendo que el programa se va a ejecutar más rápido, al menos, así es como yo lo pienso. ;-)

    NOTA:

    Quisiera aclarar que cuando escribo sobre que los cambios en la configuración regional afectan a todos los programas instalados, me refiero a los cambios de valores de la configuración regional existente en las opciones de Region del Panel de Control de Windows realizados desde nuestra aplicación mediante llamadas a la función SetLocaleInfo de la API de Windows, ya que si solamente nos limitamos a utilizar en nuestro programa un objeto System.Globalization.CultureInfo concreto diferente al de la cultura actual, esto no afecta para nada a los restantes programas, ya que no se modifican los valores de la configuración regional del sistema operativo.

    Afectaría solamente a la presentación y conversión de aquellos valores numéricos, de moneda o de fecha y hora que se muestran al usuario formateados, o se recaban del mismo, desde nuestra propia aplicación, lo cual, tampoco estoy muy de acuerdo que digamos en que se modifique la cultura del subproceso actual. ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.



    viernes, 22 de septiembre de 2017 17:07
    Moderador
  • Gracias por tu opinión, es muy importante para mí, todo lo que uno pueda aprender es bueno, saludos 

    viernes, 22 de septiembre de 2017 23:22
  • En este tema yo opino:

    En el teclado con teclado numérico extendido, el punto es el que está más accesible, si debemos ingresar valores con decimales lo más rápido sería utilizar dicho punto.

    En el tema fecha lo que cambia más en el ingreso de información es el día luego el mes y al final el año, entonces lo más conveniente para ingresarla es utilizar ddmmaaaa, y permitir sobre-escribirla desde la izquierda, o sea que la persona escribiria solo lo que cambia y luego enter, otra opción es solo ingresar el día: dd (previamente elegimos mm-aaaa)

    Y en el caso de ingresar el día solo, limitarlo a 2 digitos, o sea que al escribir el segundo automaticamente pase al textbox siguiente (me ahorro el enter)

    En el caso de ingresar horas y minutos, digamos en un programa de personal las entradas y salidas usaria hh:mm en este caso ofreceria la hora en que deberia ingresar y luego de enter los minutos, si ingresa 2 digitos de hora paso directamente a los minutos sin esperar el enter.

    En todo ingreso de información el utilizar el teclado numérico de la derecha y las teclas : flechas, ins, sup, avpag repag con las teclas ctrl y alt de la izquierda y las funciones f2, f3, f4, f5 y espacio, tab, shift-tab

    minimizando el ingreso de letras y el uso de mouse => incrementa el ingreso de información, la velocidad y disminuye el cansancio.

    Con el mouse utilizamos 2 dedos con el teclado utilizamos 10 y 10>2.

    En cuanto a la impresión de listados podria configurar en los mismos el uso de , por . y el formateo de fechas de acuerdo a los deseos del usuario.

    Yo recomiendo el uso de teclados extendidos tipo gamer, si utilizan una notebook les recomiendo un teclado externo muy barato y facil de sustituir en caso de roturas, con teclas que se sientan debajo de los dedos, nunca un teclado plano tipo notebook.

    En cuanto al mouse tirarlo bien lejos.

    Yo priorizo la velocidad y exactitud por sobre lo bonito.


    Hugo González (Macgyber)

    domingo, 24 de septiembre de 2017 16:07