El método OnPaint() y gráficos en un formulario.

31. March 2008 04:07 by Oscar.SS in Desarrollo Windows  //  Tags:   //   Comments (3)

Hace unas semanas hablábamos sobre la persistencia de gráficos en los controles de un formulario. Ahora vamos a comentar como dibujar sobre un formulario.

En este caso, para que los gráficos persistan, no es necesario crear un mapa de bits, aunque también es posible hacerlo. Bastará con que implementemos todas las instrucciones de dibujo en el evento Paint() de nuestro formulario (o de nuestros controles). Así de fácil.

Dado que dibujar utilizando el evento Paint() no necesita muchas explicaciones, vamos a ver otra técnica basada en dibujar con el método virtual OnPaint().

¿Dónde está definido el método OnPaint()?. El método virtual OnPaint() pertenece a la clase Control del espacio de nombres System.Windows.Forms.

¿Cómo está definido el método OnPaint()?. Como ya he comentado antes es un método virtual. Esto quiere decir que puede ser redefinido (override) en las clases derivadas de la clase base. Estos conceptos son de POO y por lo tanto, profundizaremos en ellos en otro artículo.

¿Qué hace el método OnPaint()?. Simplemente provoca el evento Paint() del formulario.

¿Por qué utilizar el método OnPaint()?. Como se puede ver en la definición MSDN del método OnPaint(), este contiene un parámetro “e” del tipo PaintEventArgs que proporciona datos de eventos. Más concretamente, proporciona la propiedad Graphics y la propiedad ClipRectangle sobre la que se va a dibujar. Es decir, que con el parámetro “e” tenemos toda la información necesaria para poder dibujar directamente.

Solo queda aclarar que al redefinir este método, Visual Studio genera automáticamente una llamada al método OnPaint() de la clase base. Es decir;

base.OnPaint(e);

Esto es necesario para evitar problemas por ejemplo con los estilos virtuales de los sistemas operativos.

¡Pasemos a la acción!. Abramos el editor de Visual Studio y dibujemos sobre el formulario un triangulo que será rellenado por un color especificado.

Aquí os dejo el código de esta sencilla aplicación que no merece más que algunos comentarios. Como siempre al final veremos una imagen con el resultado de ejecutar nuestra aplicación.

 

namespace Gráficos_OnPaint
{
    
public partial class Form1 : Form
    {
        
public Form1()
        {
            InitializeComponent()
;
        
}
        
protected override void OnPaint(PaintEventArgs e)
        {
            
//Llamada al método de la clase base.
            
base.OnPaint(e);

            
//Establecemos los vértices de un triángulo.
            
Point Vertice1 = new Point(50200);
            
Point Vertice2 = new Point(250200);
            
Point Vertice3 = new Point(15050);

            
//Cargamos en memoria (instanciar) un objeto GraphicsPath. 
            
GraphicsPath ruta = new GraphicsPath();

            
//Establecemos una secuencia de lineas sobre el objeto "ruta".
            
ruta.AddLine(Vertice1, Vertice2);
            
ruta.AddLine(Vertice2, Vertice3);
            
ruta.AddLine(Vertice3, Vertice1);

            
//Dibujamos la secuencia de lineas.
            
e.Graphics.DrawPath(new Pen(Color.Black, 4), ruta);

            
//Rellenamos con un color el interior de la secuencia de lineas.
            
e.Graphics.FillPath(new SolidBrush(Color.Orange), ruta);
        
}
    }
}


¿Un título?...imprescindible.

28. March 2008 03:47 by Oscar.SS in Formación  //  Tags: ,   //   Comments (0)

La primera vez que vi este libro en la estantería de una librería le eche un vistazo rápido y lo volví a dejar. Enseguida me di cuenta que era un libro de lenguaje puro, solo C# y nada más. Nada del entorno de desarrollo Visual Studio. Solo aplicaciones de consola.

Menos mal que algunas semanas después volví a la librería y lo estudie con más detenimiento. Este libro es algo más que un libro dedicado C#, es un curso de programación muy completo utilizando muchas de las librerías de .NET Framework.

 

Título: Microsoft C#. Curso de Programación.
Autor: CEBALLOS, F.J.
Editorial: Ra-Ma.
I.S.B.N.: 84-7897-737.6
Fecha publicación: Octubre 2006.
Nº páginas: 886.
Nº capítulos: 19.
Precio: 46.90 euros.



Elogios:

Es un libro muy completo. Los primeros 9 capítulos están dedicados a lo básico. Desde ¿qué es un programa?, hasta métodos y colecciones. Tiene muchos ejemplos básicos y gran cantidad de textos explicativos.

Los capítulos del 10 al 15 tienen por misión dejar claro que es la abstracción en C# o la POO. Aquí los ejemplos de código se complican un poco más. En todos los capítulos del libro hay ejercicios resueltos y ejercicios propuestos.

En los últimos 4 capítulos es donde se hace más hincapié en eso de “curso de programación”. Aquí el autor ofrece algo que no suele encontrarse en todos los libros: listas lineales, listas circulares, arboles binarios, algoritmos de programación (búsquedas, ordenación, etc) y programación con hilos.

El libro contiene 4 apéndices. A destacar el que está dedicado a las novedades de C# 3.0 cerrando de esta forma la edición del libro totalmente actualizada a la última versión del lenguaje.

 

Críticas:

En algunas ocasiones da la sensación, durante la lectura, que el autor va muy deprisa. Es como si diera cosas por sentadas. Aunque es un libro que comienza con lo básico también es verdad que quizás no sea el más recomendado para empezar de cero absoluto.

Quizás no me guste mucho el orden de los capítulos dedicados a la POO. Pero esto tan solo es cuestión de gustos.

 

Resumiendo:

Si tienes pocos conocimientos de programación con C# y buscas un libro para profundizar, este es tu libro. También puede servir se consulta a más de uno (yo mismo), se exponen la mayoría de las clases e interfaz de uso común (algunas no tan comunes) de la librería .NET.

El libro viene con CD en el que se incluyen todas las aplicaciones realizadas en el libro y lo necesario para que “corrar” en tu máquina (.NET Framework SDK).

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.


Recent Comments

Comment RSS

Month List