Manejar valores de configuración.

23. March 2008 02:58 by Oscar.SS in Desarrollo Windows  //  Tags:   //   Comments (0)

¿Qué son los valores de configuración?. Supongamos una aplicación de tipo Windows (Windows Applications) donde el usuario tiene la opción de establecer el tamaño de la ventana de nuestra aplicación. Bien, puede interesar que la próxima vez que se ejecute la aplicación, esta,” recuerde” el tamaño de la ventana que estableció el usuario la última vez. Incluso puede interesar que la “recuerde” para un usuario en concreto.

Esto son los valores de configuración. Todas aquellas propiedades de nuestra aplicación (formularios y controles) que deseemos queden registradas para la próxima ejecución del programa.

Los valores de configuración se dividen en dos niveles:

1- Valores de configuración a nivel usuario. Son de lectura y escritura. Pueden ser establecidos para un usuario en concreto.

2- Valores de configuración a nivel aplicación. Solamente son de lectura. Y son comunes a todos los usuarios de la aplicación.

¿Donde se guardan los valores de configuración?. Quedan registrados en un archivo de nuestro proyecto cuyo nombre es Settings.Designer.cs. Lo cierto es que este archivo pertenece al espacio de nombres “nombre_proyecto.Properties”. Para registrar los valores de configuración utilizaremos el método Save() de la clase Settings que pertenece a este espacio de nombres.

Para ser más exactos podemos decir que la definición de las propiedades de configuración se encuentra en el fichero nombre_proyecto.exe.config, el cual está ubicado en el directorio bin\Debug. Este fichero es de formato XML.

Lo mejor es que pasemos a la acción. Antes de empezar, decir que como siempre, existen diferentes técnicas para hacer lo mismo. Aquí veremos, bajo mi modesta opinión, la que considero más sencilla, clara y funcional.

Comencemos. Esta es una de esas cosas que son fáciles de hacer pero difíciles de explicar. ¡Haber que tal lo hago!.

Descripción del procedimiento general:

1- Definir las propiedades de configuración por medio del IDE de Visual Studio.

2- En el evento Load de nuestro formulario establecemos las propiedades de los controles (o del formulario) asignándole el valor guardado en las “propiedades de configuración”. Ejemplo:

textBox1.BackColor = Properties.Settings.Default.configuracion_color;

3- En el evento FormClosing del formulario guardamos los valores de las propiedades de los controles (o del formulario) en las propiedades de configuración. Seguidamente guardamos estos valores. Ejemplo:

Properties.Settings.Default.configuracion_color = textBox1.BackColor;

Properties.Settings.Default.Save();

En el paso 2 del procedimiento anterior lo que se pretende es que cuando la aplicación se inicie, todas las propiedades de los controles recuperen los valores que están guardos.

En cambio, en el paso 3, lo que se pretende es que todos los cambios que hagamos en nuestra aplicación durante la ejecución del mismo, se guarden en las propiedades de configuración. Evidentemente este paso no tendremos que tenerlo en cuenta cuando trabajemos con valores de configuración a nivel de aplicación. Como se comento antes, estos valores son de solo lectura y por lo tanto no podremos cambiarlos durante la ejecución del programa.

Ahora sí que empezamos…jeje.

Abrimos el editor de Visual Studio con una aplicación Windows (Windows Applications) y creamos una interfaz parecida a esta:

 

 

 

 

Nota: La propiedad PasswordChar del textBox contraseña tiene establecido su valor en “#”.

Una vez creada la interfaz pasamos a definir las propiedades de configuración. Para ello debemos abrir la ventana Propiedades de nuestro proyecto. Hacemos click con el botón secundario del ratón sobre el nombre de nuestro proyecto en el explorador de soluciones. En el menú contextual que aparece elegimos Propiedades.

 



Aunque la forma más rápida de abrir la ventana Propiedades es haciendo doble click sobre el fichero Properties de nuestro proyecto. En la ventana Propiedades elegimos la ficha Configuración. Este es aspecto que tiene esta ficha (ventana):

 

 

 

Expliquemos que cometido tiene cada uno de los campos de esta ventana.

Nombre: es el nombre que tiene nuestra propiedad de configuración. Con este nombre accederemos al valor que contenga por medio del código.

Tipo: tipo de datos que contiene nuestra propiedad de configuración.

Ámbito: Se ha comentado antes. Ámbito de usuario o ámbito de aplicación.

Valor: Valor predeterminado para esta propiedad de configuración (valor de configuración) en concreto.

Rellenamos los campos como se muestra en la siguiente imagen:

 

 

Expliquemos que cometido tiene, para nuestra aplicación en concreto, cada una de las propiedades de configuración que acabamos de definir.

VConfig_Usuario: almacena el nombre del usuario introducido por pantalla.

VConfig_Contraseña: almacena la contraseña del usuario.

VConfig_Recordar: almacena el estado del CheckBox. Si esta seleccionado o no.

Localización_Form: almacena la posición inicial de la ventana cuando se carga, dado que es un valor de configuración a nivel de aplicación, será siempre el mismo valor (450;250) y no podremos cambiarlo.

Tan solo queda escribir el código de nuestra aplicación siguiendo las pautas del procedimiento general descrito anteriormente.

 

namespace Valores_Config
{
    
public partial class Form1 : Form
    {
        
//Defenimos una constante que tiene el mismo valor que el la Propiedad De
        //Configuración VConfig_Recordar establecido en la ficha Configuración de
        //propiedades del proyecto.

        
const bool CheckBox_Inicial = false;

        public 
Form1()
        {
            InitializeComponent()
;
        
}

        
private void Form1_Load(object sender, EventArgs e)
        {
            
//Cuando carga el formulario esteblecemos las propiedades de los controles
            //con los valores guardados en las Propiedades De Configuración.

            
textBox1.Text Properties.Settings.Default.VConfig_Usuario;
            
textBox2.Text Properties.Settings.Default.VConfig_Contraseña;

            
checkBox1.Checked Properties.Settings.Default.VConfig_Recordar;

            this
.Location Properties.Settings.Default.Localizacion_Form;
        
}

        
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            
//Cuando se cierra el formulario comprobamos si el CheckBox esta
            //seleccionado, en ese caso, guardamos las propiedades de los controles
            //TextBox en los Valores De Configuración.

            
if (checkBox1.Checked == true)
            {
                Properties.Settings.Default.VConfig_Usuario 
textBox1.Text;
                
Properties.Settings.Default.VConfig_Contraseña textBox2.Text;
            
}
            
else
            
{
                Properties.Settings.Default.VConfig_Usuario 
= string.Empty;
                
Properties.Settings.Default.VConfig_Contraseña = string.Empty;
            
}

            
//Asignamos el estado del CheckBox en los Valores De Configuración.
            
Properties.Settings.Default.VConfig_Recordar checkBox1.Checked;

            
//Salvamos, almacenamos o guardamos todos los Valores De Configuración.
            
Properties.Settings.Default.Save();
        
}

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

        
private void Cancelar_Click(object sender, EventArgs e)
        {
            checkBox1.Checked 
CheckBox_Inicial;
            this
.Close();
        
}

    }
}

 

Para ver los efectos de los valores de configuración podemos ejecutar (F5) nuestra aplicación y mover la ventana de sitio. Cerramos la aplicación y volvemos ejecutarla para comprobar que la ventana siempre aparece en el mismo sitio.

También podemos escribir en los textBox y elegir “Recordar en este equipo”. Pulsamos “Aceptar”. Volvemos a ejecutar la aplicación para comprobar que se han guardado y recuperado todos los cambios efectuados.

 

El objeto Bipmap y la persistencia de gráficos.

15. March 2008 02:25 by Oscar.SS in Desarrollo .NET, Desarrollo Windows  //  Tags: ,   //   Comments (0)

Está claro que dibujar con .NET es fácil. El problema, como siempre reside en las infinitas clases que disponemos en .NET. ¡Aprender lleva mucho tiempo en .NET!.

Cuando se comienza a dibujar suele resultar complicado el tema de la persistencia de gráficos. ¿Que es esto de la "persistencia de gráficos"?.

Supongamos que tenemos una ventana (formulario) abierta en la pantalla. Supongamos también que minimizamos la ventana y a continuación la volvemos a maximizar. ¿Que a ocurrido?.

En realidad la ventana vuelve a redibujarse por completo. Es decir, todos los gráficos y controles que tenga esta ventana, además de la propia ventana, vuelven a dibujarse. Esto es posible porque toda la información de la ventana está cargada en memoria.

Con lo cual, cuando realizamos gráficos en .NET los debemos cargar en memoria para que vuelvan a dibujarse si el formulario se minimiza o es cubierto por otro formulario en pantalla. La forma de hacer esto es por medio de la clase Bitmap del espacio de nombres System.Drawing.

También es posible hacerlo por medio del evento Paint de la clase Control. E incluso "más elegante", sobrescribiendo el método OnPaint(). Pero todo esto...queda para otro artículo.

De momento creemos un proyecto de tipo "Aplicación de Windows Form". En el formulario, agregamos un botón. Desde el IDE establecemos las siguientes propiedades del objeto button1:

-BackColor: GradientActiveCaption
-Location: 20 ; 20
-Size: 240 ; 240
-Text: Pulsar aquí para didujar

Hacemos doble click sobre el botón para acceder a su controlador de evento. A continuación, dentro del método button1_click escribimos el código que realizará el dibujo sobre el propio botón. Para poder dibujar hay que agregar una directiva using al espacio de nombres System.Drawing que es donde se encuentran los objetos de dibujo más usuales.


//Pasos a seguir para la PERSISTENCIA DE GRÁFICOS.

namespace Persitencia_de_Gráficos
{
    
public partial class Form1 : Form
    {
        
public Form1()
        {
            InitializeComponent()
;
        
}

        
private void button1_Click(object sender, EventArgs e)
        {
            
//1- Cargamos un mapa de bits en la memoria del mismo tamaño que el control.
            
Bitmap miMapa = new Bitmap(this.button1.Width, this.button1.Height);

            
//2- El mapa de bits se lo asignamos a la propiedad Image del control
            //(BackgroupImage para Form) sobre el se mostrará la imagen. Es decir,
            //indicamos cual es la imágen que debe mostrar el control.
            
button1.Image miMapa;

            
//3- Creamos la superficie de dibujo. Es decir, le indicamos a un objeto
            //Graphics (miDibujo) donde tiene que dibujar, que dibuje sobre el mapa bits.
            
Graphics miDibujo Graphics.FromImage(miMapa);

            
//4- Dibujamos con el objeto miDibujo

            //Creamos una estructura de puntos. Representan las esquinas de un rectangulo.
            
PuntosDeEsquinas Esquina = new PuntosDeEsquinas();

            
Esquina.superiorX = this.button1.Location.X + 10;
            
Esquina.superiorY = this.button1.Location.Y + 10;
            
Esquina.inferiorX = this.button1.Width - (* (10 20));
            
Esquina.inferiorY = this.button1.Height - (* (10 20));

            
//Creamos un rectangulo con las dimensiones establecidas por las esquinas.
            
Rectangle unRectangulo = new Rectangle(Esquina.superiorX, Esquina.superiorY,
              Esquina.inferiorX, Esquina.inferiorY)
;

            
//Dibujamos un círculo delimitado por el rentengulo (unRectangulo);
            
miDibujo.DrawEllipse(new Pen(Color.BlueViolet, 10), unRectangulo);
        
}

        
struct PuntosDeEsquinas
        {
            
public int superiorX,
              superiorY,
              inferiorX,
              inferiorY
;
        
}
    }
}


Esta es la representación mostrada al ejecutar nuestra aplicación.

Para comprobar la persistencia de los gráficos dibujados solo tenemos que minimizar el formulario, o cubrirlo con otra ventana. Cuando volvamos a mostrar nuestro gráfico comprobaremos felizmente que todo está correctamente dibujado.

Resolver ecuaciones de segundo grado.

6. March 2008 02:02 by Oscar.SS in Desarrollo Windows  //  Tags:   //   Comments (0)

Esta pequeña aplicación de consola puede resultarle útil a alguien. Bien porque estudie matemáticas, o como parte de una calculadora casera, o por…¡que se yo!. El caso es que resuelve ecuaciones de segundo grado.

El proyecto costa de dos clases separadas en dos archivos, uno “Program.cs” que es el principal de la aplicación, el que contiene el método Main(). Y otra clase en un archivo “ECgrado2.cs”.

Este es el código de la clase ECgrado2:

 

class ECgrado2 //Definición de la clase que realiza los calculos de la ecuación
{
    
private double A, B, C;

    
//Definición de un constructor de clase que recibe como parámetros los valores
    //introcucidos por pantalla (coeficientes de la ecuación)
    
public ECgrado2(double a, double b, double c)
    {
        A 
a;
        
b;
        
c;
    
}

    
public double masSqrt() //Método que resuelve la raiz positiba
    
{
        
double result ((-B + System.Math.Sqrt(B * B - * A * C)) / (* A));
        return 
result;
    
}

    
public double menosSqrt() //Método que resuelve la raiz negativa
    
{
        
double result ((-B - System.Math.Sqrt(B * B - * A * C)) / (* A));
        return 
result;
    
}
}
Y este es el código, sensible de ser mejorado, del cuerpo principal del programa:

class Program
    {
        
static void Main(string[] args)
        {
            
//Inicialización de las variables que contienen los valores (coeficientes)
            //introducidos por pantalla
            
double coefA 0, coefB 0, coefC 0;

            
/*Comienzo de la repetición del cuerpo pricipal del programa. Este bucle 
             *se repite cuando al final del programa, despúes de realizar y mostrar
             *todos los calculos, se le pregunta al usuario si quiere seguir calculando
             */
            
bool control = true;
            while 
(control == true)
            {
                Console.Clear()
;
                
Console.WriteLine("Resolver ecuaciones de segundo grado.");
                
Console.WriteLine("Ecuaciones del tipo: Ax^2 + Bx + C = 0");

                
/*En primer lugar se comprueba (bloque try{}) que los valores de los 
                 * coeficientes sean del tipo correcto. En el caso que no lo sean, se
                 * captura la excepción producida (bloque catch{}) y se repite todo
                 * el bloque try/catch hasta que los datos introducidos por el usuario
                 * sean del formato correcto
                 */
                
bool repTryCatch = true;
                while 
(repTryCatch == true)
                {
                    
try
                    
{
                        Console.WriteLine(
"\nIntroducir coeficiente A:");
                        
coefA Double.Parse(Console.ReadLine());

                        
Console.WriteLine("\nIntroducir coeficiente B:");
                        
coefB Double.Parse(Console.ReadLine());

                        
Console.WriteLine("\nIntroducir coeficiente C:");
                        
coefC Double.Parse(Console.ReadLine());

                        
repTryCatch = false;
                    
}
                    
catch (FormatException)
                    {
                        Console.Clear()
;
                        
Console.WriteLine("¡ERROR!. Introducir solo valores numéricos.");
                        
repTryCatch = true;
                    
}
                }

                
//Valores internos de la raiz cuadrada
                
double Bcuadrado coefB * coefB;
                double 
cuatroAC * coefA * coefC;
                
//Comprobación de que las operaciones con los valores internos de la raiz
                //no dan un resultado negativo. No existe la raiz de un número negativo
                
if (Bcuadrado < cuatroAC && coefA > && coefC > 0)    
                {
                    Console.Clear()
;
                    
Console.WriteLine("La ecuación no tiene solución." 
                        
"\nSe ha intentado la raiz de un valor negativo.");
                
}
                
else
                
{
                    
//Llamada al constructor de la clase ECgrado2
                    
ECgrado2 ecuacion = new ECgrado2(coefA, coefB, coefC);
                    
//Llamada a los métodos de calculo de clase ECgrado2
                    
Console.WriteLine("\nValor 1 = {0}",
                        ecuacion.masSqrt().ToString())
;
                    
Console.WriteLine("Valor 2 = {0}",
                        ecuacion.menosSqrt().ToString())
;
                
}

                Console.WriteLine(
"\n¿Desea seguir calculando? (y/n)");

                
//Este último bloque se repite siempre que el usuario no introduzca el
                //formato correcto (y/n) para la pregunta anterior
                
bool repSwitch = true;
                while 
(repSwitch == true)
                {
                    
string SioNO Console.ReadLine();
                    switch 
(SioNO)
                    {
                        
case "y"case "Y":
                            control 
= true; //Repite el bloque principal del programa
                            
repSwitch = false;
                            break;
                        case 
"n"case "N":
                            control 
= false; //Termina el bucle principal del programa
                            
repSwitch = false;
                            break;
                        default
:
                            Console.WriteLine(
                                
"\nLa entrada no es correcta. Pulse \"y\" o \"n\".");
                            
repSwitch = true;
                            break;
                    
}
                }
            }
        }
    }

A continuación dejo algunas salidas por pantalla.


Array de parámetros opcionales

29. February 2008 17:36 by Oscar S.S. in Lenguajes  //  Tags:   //   Comments (0)

Aquí tenemos un pequeño y sencillo ejemplo de cómo pasarle a un mismo método diferentes matrices con longitudes diferentes. Al definir los parámetros del método como params podemos tener un mismo método (con diferentes llamadas) que ejecute operaciones con diferentes longuitudes de matrices.

 

    class Params
    {
        
static void Main(string[] args)
        {
            
//Creamos dos matrices con longuitudes distintas.
            
byte[] pares = new byte[4] { 246};
            byte
[] impares = new byte[5] { 1357};

            
//Llamamos al mismo método Mostrar() pasandole como argumento
            //matrices con diferente longitud y una serie numérica.

            
Console.WriteLine("Matriz de pares");
            
Mostrar(pares);

            
Console.WriteLine("\nMatriz de impares");
            
Mostrar(impares);

            
Console.WriteLine("\nSerie numérica");
            
Mostrar(234354657645342334);

            
Console.ReadLine();
        
}

        
static void Mostrar(params byte[] mtzArgs)
        {
            
foreach (byte in mtzArgs)
                Console.WriteLine(i.ToString())
;
        
}
    }

 

La salida de consola es la siguiente:

 

Cambiar el tamaño de una matriz.

18. January 2008 16:59 by Oscar S.S. in Lenguajes  //  Tags:   //   Comments (0)

El propósito de este código es mostrar cómo se cambia el tamaño de una matriz en C#.

Antes de seguir con el código, es necesario tener conocimientos previos sobre declaración e inicialización de matrices, así como de los métodos y propiedades de la clase Array. Aquí os dejo unos links de la documentación MSDN:

1- Declarar e inicializar matrices.

2- Utilizar Foreach en matrices.

3- Métodos y propiedades de la clase Array.

En realidad cambiar el tamaño de una matriz no tiene mucho misterio. Supongamos una matriz de tipo int llamada miMatriz:

int[] miMatriz = { 1, 2, 3 };

Supongamos ahora que queremos ampliarla en 4 elementos, es decir, conseguir una matriz de 7 elementos. Es muy sencillo:

miMatriz = new int[miMatriz.Length + 4];

Todo correcto. Ahora tenemos una matriz de tipo int llamada miMatriz que puede contener 7 elementos. Pero ahora vienen las preguntas:

¿Qué ha ocurrido con los datos de la matriz original { 1, 2, 3 }?.

¿La nueva matriz contiene los datos originales?.

La respuesta es que los datos originales { 1, 2, 3 } se han perdido al obtener una nueva matriz de 7 elementos “vacios”, es decir, la nueva matriz contiene { 0, 0, 0, 0, 0, 0, 0 }. Veámoslo en el código.

 

using System;
using 
System.Collections.Generic;
using 
System.Text;

namespace 
ConsoleApplication1
{
    
class Program
    {
        
static void Main(string[] args)
        {
            
// Declarar e inicilizar una matriz de tipo int
            
int[] miMatriz 12};

            
// Mostrar el contenido de MiMatriz
            
Console.WriteLine("Esta es miMatriz original...");
            foreach 
(int in miMatriz)
                Console.WriteLine(x)
;

            
Console.WriteLine();

            
// Ampliamos miMatriz y mostramos su contenido
            
miMatriz = new int[miMatriz.Length + 4];
            
Console.WriteLine("Esta es miMatriz ampliada...");
            foreach 
(int in miMatriz)
                Console.WriteLine(x)
;

            
Console.ReadLine();
        
}
    }
}

 

Como podemos observar los datos de la matriz se han perdido. ¿Qué debemos hacer para ampliar una matriz en C# sin perder los datos?. La única forma de conseguirlo es creando una copia de la matriz que queremos ampliar. Para clarificarlo sigamos estos 4 pasos:

PASO 1. Declarar e inicializar una matriz “de copia” con el mismo tamaño que la matriz original.

PASO 2. Copiar el contenido de la matriz original en la matriz “copia”.

PASO 3. Aumentar el tamaño de la matriz original.

PASO 4. Copiar el contenido de la matriz “copia” en la matriz original ya ampliada.

Veamos el código de estos 4 pasos.

 

class Program
    {
        
static void Main(string[] args)
        {

            
// Declarar e inicilizar una matriz de tipo int
            
int[] miMatriz 12};

            
// Mostrar el contenido de MiMatriz
            
Console.WriteLine("Esta es miMatriz original...");
            foreach 
(int in miMatriz)
                Console.WriteLine(x)
;

            
Console.WriteLine();

            
// PASO 1:
            // Declarar e inicializar una matriz llamada Micopia
            
int[] miCopia = new int[miMatriz.Length];

            
// PASO 2:
            // Copiar el contenido de miMatriz en miCopia
            
miMatriz.CopyTo(miCopia, 0);

            
// PASO 3:
            // Cambiar el tamaño de miMatriz (en este caso lo aumentamos en 4)
            
miMatriz = new int[miMatriz.Length + 4];

            
// PASO4:
            // Copiar el contenido de miCopia en miMatriz ya ampliada
            
miCopia.CopyTo(miMatriz, 0);

            
// Mostrar el contenido de miMatriz ampliada
            
Console.WriteLine("Esta es miMatriz ampliada...");
            foreach 
(int in miMatriz)
                Console.WriteLine(x)
;

            
Console.ReadLine();

        
}
    }
De esta forma obtenemos una matriz ampliada conservando los datos pero en definitiva este comportamiento es muy pobre. Es recomendable trabajar con ArrayList.

Recent Comments

Comment RSS

Month List