Buscar este blog

domingo, 30 de enero de 2011

Nuevo sistema de ayuda en Visual Studio 2010

Acabo de instalar el nuevo Visual Studio 2010 y lo primero que hice fue abrir la ayuda ya que mientras lo instalaba note que ya no se instala la MSDN como en las versiones anteriores, ahora la ayuda se muestra en el navegador de Internet mostrando páginas que se cargan desde un servidor web local que inicia el Visual Studio.
Francamente me pareció un mal cambio lo primero que note es que ya no tiene índice ahora se tiene que usar la función de búsqueda para encontrar los temas, además esta búsqueda es un poco lenta y se tiene que buscar en los temas encontrados. Al principio pensé que se mostraba esta ayuda debido a que la versión de Visual Studio es la de prueba pero investigando un poco encontré que en todas las versiones de Visual Studio 2010 se usa este sistema nuevo.
Aquí esta la imagen del nuevo sistema:


Afortunadamente el equipo de la MSDN lanzo un visor de ayuda (Microsoft Help Viewer Power Tool (Beta)) que muestra los temas desde el mismo servidor usando un programa un poco más completo que el navegador simplemente este programa esta hecho en SilverLight y funciona de manera predeterminada mostrándose en el navegador por defecto, aunque tambien se puede configurar para funcionar como aplicación independiente.
Aquí esta la imagen funcionando sobre Firefox.



Esta opción esta mucho mejor incluye un índice y se acerca un poco a la versión anterior de la MSDN pero francamente todavía le falta mucho para igualarla: le faltan herramientas y el índice es un poco lento.
Bueno si quieren probarla (esta en etapa Beta) la pueden bajar de la siguiente página:
Microsoft Help Viewer Power Tool (Beta)

miércoles, 27 de octubre de 2010

Comprimir Web Services

Llamar un web service de manera que la respuesta nos llegue comprimida es muy sencillo pero de entrada nos podemos tardar un poco en encontrar la forma de hacerlo de hacerlo por eso publico esta entrada.
Es muy sencillo solo tenemos que poner la propiedad EnableDecompression de nuestra instancia cliente a verdadero y listo tendremos nuestro web service comprimido (siempre y cuando la compresión este habilitada en IIS por supuesto).

WSInstance client = WSClient.Client();
client.EnableDecompression = true;

viernes, 10 de septiembre de 2010

Añadiendo controles a un control de usuario heredado de otro control de usuario

Este problema me tuvo parado un rato.
Usando visual studio tenemos un control de usuario al que le añadimos un contenedor, por ejemplo un panel, hacemos otro control de usuario que hereda del primero y tratamos de añadir controles en el área libre del panel anterior visual studio no lo permite.
La solución es simple pero no muy intuitiva solo debemos marcar como publico o protegido el panel que añadimos en el control base, esto se hace en la ventana de propiedades del panel en la sección que dice diseño.

domingo, 18 de abril de 2010

Threads en Windows.Forms usando el componente BackgroudWorker

Usar threads en Windows.Forms se simplifica mucho usando el componente BackgroundWorker que nos permite llevar a cabo una tarea en el fondo sin preocuparnos de tareas como la administración del thread o el acceso a controles desde un thread diferente al del form.
Les presento este pequeño tutorial que nos presenta una tarea muy sencilla que llevaremos a cabo en un trhread.

Primero que nada crearemos el formulario añadiendo los siguientes componentes:

Un NumericUpdown llamado hasta
un botón llamado inicio
un botón llamado fin
un BackgroundWorker llamado thread, con las propiedades SupportCancellation y ReportProgress en verdadero
una ProgressBar llamado progreso
una etiqueta llamada status

El formulario se vera como en la imagen:



Lo primero que hacemos es añadir el código para comenzar la tarea como no deseamos que el usuario pueda cambiar los parámetros del mismo mientras se ejecuta deshabilitaremos los controles adecuados, también noten que pasamos un parámetro al proceso esto es necesario ya que en el thread no podemos accesar los controles del formulario o tendremos un error:

private void inicio_Click(object sender, EventArgs e) {
            inicio.Enabled = false;
            fin.Enabled = true;
            hasta.Enabled = false;
            thread.RunWorkerAsync(hasta.Value);
        }

Podemos cancelar el proceso en cualquier momento usando el método CancelAsync del BackwroundWorker:

private void fin_Click(object sender, EventArgs e) {
            thread.CancelAsync();
        }

El proceso simplemente desde cero hasta el número del NumericDown que recuperamos desde el argumento que pasamos al proceso, nos dentendremos un segundo entre cada número.
Para cancelar el proceso debemos verificar constantemente la propiedad CancelationPending cuando esta sea verdadera detendremos la cuenta.
Para reportar el progreso usamos el método ReportProgress que acepta un porcentaje entero y un argumento de tipo object en el que podemos incluir otra información relevante al progreso:

private void thread_DoWork(object sender, DoWorkEventArgs e) {
            decimal total = (decimal)e.Argument;
            for(decimal i = 0; i < total; i++) {
                if(thread.CancellationPending)
                    break;
                System.Threading.Thread.Sleep(1000);
                int porcentaje = (int)((i / total) * 100);
                thread.ReportProgress(porcentaje, porcentaje.ToString() + "%");
            }
        }
Para reportar el progreso usamos el evento ProgressChanged, noten el uso del argumento pasado anteriormente:

private void thread_ProgressChanged(object sender, ProgressChangedEventArgs e) {
            progreso.Value = e.ProgressPercentage;
            status.Text = (string)e.UserState;
        }

Cuando se termina el proceso podemos rehabilitar los controles y agregar directamente una notificación:

private void thread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
            inicio.Enabled = true;
            fin.Enabled = false;
            hasta.Enabled = true;
            status.Text += " Terminado";
        }

Finalmente igual que deshabilitamos los controles durante el proceso nos aseguramos que no se cierre la ventana durante el mismo:

private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            if(thread.IsBusy) {
                MessageBox.Show("Deten el proceso antes de salir");
                e.Cancel = true;
            }
        }

A continuación esta el código completo:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

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

        private void inicio_Click(object sender, EventArgs e) {
            inicio.Enabled = false;
            fin.Enabled = true;
            hasta.Enabled = false;
            thread.RunWorkerAsync(hasta.Value);
        }
        private void fin_Click(object sender, EventArgs e) {
            thread.CancelAsync();
        }
        private void thread_DoWork(object sender, DoWorkEventArgs e) {
            decimal total = (decimal)e.Argument;
            for(decimal i = 0; i < total; i++) {
                if(thread.CancellationPending)
                    break;
                System.Threading.Thread.Sleep(1000);
                int porcentaje = (int)((i / total) * 100);
                thread.ReportProgress(porcentaje, porcentaje.ToString() + "%");
            }
        }
        private void thread_ProgressChanged(object sender, ProgressChangedEventArgs e) {
            progreso.Value = e.ProgressPercentage;
            status.Text = (string)e.UserState;
        }
        private void thread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
            inicio.Enabled = true;
            fin.Enabled = false;
            hasta.Enabled = true;
            status.Text += " Terminado";
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            if(thread.IsBusy) {
                MessageBox.Show("Deten el proceso antes de salir");
                e.Cancel = true;
            }
        }
    }
}

Formateando codigo para Internet

Aquí les dejo la dirección de la página que uso para formatear el código que presento en este blog tiene un resultado muy vistoso y soporta varios lenguajes:

http://www.manoli.net/csharpformat/

Tamaño de la pantalla con Windows.Forms

Medir el tamaño de la pantalla con .Net es muy sencillo.
Para esto tenemos la clase Screen que nos provee de métodos para encontrar las dimensiones ya sea el tamaño total o del área de trabajo que hay que notar que no incluye el área ocupada por la barra de tareas, aquí esta el ejemplo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace ProbadorConsola {
    class Program {
        static void Main(string[] args) {
            Rectangle wArea = Screen.GetWorkingArea(new Point(1, 1));
            Rectangle bounds = Screen.GetBounds(new Point(1, 1));
            Console.WriteLine("Area de trabajo "
                + "Superior: {0}, Izquierda: {1}, Alto: {2}, Abajo: {3}, "
                + "Ancho: {4} Derecha {5}",
                wArea.Top, wArea.Left, wArea.Height, wArea.Bottom, wArea.Width
                , wArea.Right);
            Console.WriteLine("Total "
                + "Superior: {0}, Izquierda: {1}, Alto: {2}, Abajo: {3}, "
                + "Ancho: {4} Derecha {5}",
                bounds.Top, bounds.Left, bounds.Height, bounds.Bottom,
                bounds.Width, bounds.Right);
            Console.ReadLine();
        }
    }
}

La salida es esta:
Area de trabajo Superior: 0, Izquierda: 249, Alto: 900, Abajo: 900, Ancho: 2631 Derecha 2880
Total Superior: 0, Izquierda: 0, Alto: 900, Abajo: 900, Ancho: 2880 Derecha 2880