Mostrando las entradas con la etiqueta ListBox. Mostrar todas las entradas
Mostrando las entradas con la etiqueta ListBox. Mostrar todas las entradas

miércoles, 22 de noviembre de 2017

El Manual del Día: Windows Forms 3.5

MSDN - Manual de Windows Forms

Titulo: Manual de Windows Forms 3.5
Fuente Original: Microsoft Developer Network (MSDN)
Compilado Por: Luis Dueñas Huaroto (Lduenas)
Año de Compilación: 2008
Número de Páginas: 324

Indice del Manual de Windows Forms

1. Lo Nuevo en Formularios Windows Forms para .NET Framework 3.5
2. Adiciones a Formularios Windows Forms para .NET Framework 2.0
  2.1. Nuevas Adiciones a las Características Existentes en los Formularios Windows Forms
3. Introducción a los Formularios Windows Forms
  3.1. Información General sobre Formularios Windows Forms
  3.2. Crear un Nuevo Formulario Windows Forms
    3.2.1. Coordenadas de Formularios Windows Forms
    3.2.2. Tutorial: Crear un Formulario Windows Forms Sencillo
    3.2.3. Tutorial: Introducción al Diseñador de Windows Forms
    3.2.4. Cómo: Crear una Aplicación de Windows Forms desde la Línea de Comandos
    3.2.5. Cómo: Crear un proyecto de aplicación para Windows
    3.2.6. Cómo: Agregar Formularios Windows Forms a un Proyecto
    3.2.7. Cómo: Elegir el Formulario de Inicio en una Aplicación para Windows
    3.2.8. Cómo: Mostrar Formularios Windows Forms en el Diseñador
    3.2.9. Cómo: Mantener un Formulario Windows Forms en Primer Plano
    3.2.10. Cómo: Compilar y Ejecutar un Ejemplo de Código Completo de Formularios Windows Forms utilizando Visual Studio
  3.3. Crear Controladores de Eventos en Formularios Windows Forms
    3.3.1. Información General sobre Eventos
    3.3.2. Información General sobre Controladores de Eventos
    3.3.3. Cómo: Crear Controladores de Eventos en Tiempo de Ejecución
    3.3.4. Cómo: Conectar Varios Eventos con un Unico Controlador de Eventos
    3.3.5. Orden de Eventos en los Formularios Windows Forms
    3.3.6. Cómo: Crear Controladores de Eventos con el Diseñador
    3.3.7. Cómo: Crear Controladores de Eventos Predeterminados en el Diseñador
  3.4. Ajustar el Tamaño y la Escala de Formularios Windows Forms
    3.4.1. Cómo: Cambiar el Tamaño de Formularios Windows Forms con el Diseñador
    3.4.2. Cómo: Cambiar el Tamaño de los Formularios Windows Forms
    3.4.3. Tutorial: Crear un Formulario Windows Forms de Entrada de Datos de Tamaño Variable
    3.4.4. Ajuste Automático de Escala en Formularios Windows Forms
    3.4.4.1. Cómo: Responder a los Cambios de las Combinaciones de Fuentes en una Aplicación de Windows Forms
  3.5. Cambiar la Apariencia de Formularios Windows Forms
    3.5.1. Cómo: Cambiar los Bordes de Formularios Windows Forms
    3.5.2. Cómo: Agregar Imágenes de Fondo a Formularios Windows Forms
    3.5.3. Cómo: Cambiar los Bordes de Formularios Windows Forms mediante el Diseñador
    3.5.4. Cómo: Crear Formularios Windows Forms Transparentes
    3.5.5. Cómo: Crear Formularios Windows Forms No Rectangulares
    3.5.6. Cómo: Mostrar Formularios Windows Forms Modales y No Modales
    3.5.7. Cómo: Habilitar Estilos Visuales en Windows XP
    3.5.8. Cómo: Hacer Invisible un Formulario Windows Forms de Inicio
    3.5.9. Cómo: Establecer la Ubicación en Pantalla de Formularios Windows Forms
  3.6. Controles de Formularios Windows Forms
    3.6.1. Insertar Controles en Formularios Windows Forms
      3.6.1.1. Cómo: Agregar Controles a Formularios Windows Forms
      3.6.1.2. Cómo: Agregar Controles sin una Interfaz de Usuario a Formularios
      3.6.1.3. Cómo: Agregar o Quitar Controles de una Colección en Tiempo de Ejecución
      3.6.1.4. Tutorial: Rellenar Automáticamente el Cuadro de Herramientas con Componentes Personalizados
      3.6.1.5. Cómo: Agregar Controles ActiveX a Formularios Windows Forms
      3.6.1.6. Consideraciones al Alojar un Control ActiveX en un Formulario
    3.6.2. Organizar Controles en Formularios Windows Forms
      3.6.2.1. Cómo: Alinear Varios Controles en Formularios Windows Forms
      3.6.2.2. Cómo: Delimitar Controles en Formularios Windows Forms
      3.6.2.3. Cómo: Copiar Controles Entre Formularios Windows Forms
      3.6.2.4. Cómo: Acoplar Controles en Formularios Windows Forms
      3.6.2.5. Cómo: Disponer Objetos en Capas en Formularios Windows Forms
      3.6.2.6. Cómo: Bloquear Controles en Formularios Windows Forms
      3.6.2.7. Cómo: Colocar los Controles en Formularios Windows Forms
      3.6.2.8. Cómo: Cambiar el Tamaño de los Controles en Formularios Windows
      3.6.2.9. Cómo: Establecer Opciones de Cuadrícula para Todos los Formularios Windows Forms
      3.6.2.10. Cómo: Establecer el Orden de Tabulación en Formularios Windows
      3.6.2.11. Tutorial: Organizar Controles en Formularios Windows Forms Mediante Líneas de Ajuste
      3.6.2.12. Cómo: Organizar Controles con las Líneas de Ajuste y la Cuadrícula en Formularios Windows Forms
      3.6.2.13. Cómo: Reasignar Controles Existentes en un Elemento Primario Diferente
      3.6.2.14. Tutorial: Diseñar Controles de Formularios Windows Forms con Relleno, Márgenes y la Propiedad AutoSize
    3.6.3. Asignar Etiquetas a Controles Individuales de Formularios Windows Forms y Proporcionar Accesos Directos a los Mismos
      3.6.3.1. Cómo: Establecer el Texto Mostrado por un Control de Formulario
      3.6.3.2. Cómo: Establecer el Texto Mostrado por un Control de Formularios Windows Forms mediante el Diseñador
      3.6.3.3. Cómo: Establecer la Imagen que Muestra un Control de Formulario
      3.6.3.4. Cómo: Establecer la Imagen Mostrada por un Control de Formularios Windows Forms mediante el Diseñador
      3.6.3.5. Cómo: Crear Teclas de Acceso para Controles de Windows Forms
      3.6.3.6. Cómo: Crear Teclas de Acceso para Controles de Formularios Windows Forms mediante el Diseñador
      3.6.3.7. Proporcionar Información de Accesibilidad de Controles en un Formulario Windows Forms
    3.6.4. Controles que se Utilizan en Formularios Windows Forms
      3.6.4.1. Controles de Formularios Windows Forms por Función
      3.6.4.2. Controles Compatibles con Dibujos Propietarios Integrados
      3.6.4.3. Controles de Formularios Windows Forms Usados para Mostrar Opciones
        3.6.4.3.1. Cuándo Utilizar un control ComboBox de Formularios Windows Forms en lugar de un Control ListBox
        3.6.4.3.2. Cómo: Obtener Acceso a Elementos Específicos de un Control ComboBox, CheckedListBox o ListBox
        3.6.4.3.3. Cómo: Agregar y Quitar Elementos de un Control ComboBox, CheckedListBox o ListBox
        3.6.4.3.4. Cómo: Crear una Tabla de Búsqueda para un Control ComboBox, ListBox o CheckedListBox
        3.6.4.3.5. Cómo: Enlazar un Control ComboBox o ListBox de Formularios Windows Forms a Datos
        3.6.4.3.6. Cómo: Ordenar el Contenido de un Control ComboBox, CheckedListBox o ListBox
    3.6.5. Desarrollar Controles Personalizados de Formularios Windows Forms con .NET Framework
      3.6.5.1. Información General sobre cómo Utilizar Controles en los Formularios
      3.6.5.2. Variedades de Controles Personalizados
        3.6.5.2.1. Recomendaciones sobre Tipos de Controles
      3.6.5.3. Fundamentos de Desarrollo de Controles de Formularios Windows
      3.6.5.4. Propiedades de los Controles de Formularios Windows Forms
        3.6.5.4.1. Definir una Propiedad en los Controles
        3.6.5.4.2. Definir Valores Predeterminados con los Métodos ShouldSerialize y Reset
        3.6.5.4.3. Eventos de Cambio de Propiedades
        3.6.5.4.4. Cómo: Exponer Propiedades de Controles Constituyentes
        3.6.5.4.5. Implementación de Métodos en Controles Personalizados
      3.6.5.5. Eventos de los Controles de Formularios Windows Forms
        3.6.5.5.1. Reemplazar el Método OnPaint
        3.6.5.5.2. Controlar la Introducción de Datos por el Usuario
        3.6.5.5.3. Definir un Evento en los Controles de Formularios Windows
      3.6.5.6. Atributos en Controles de Formularios Windows Forms
      3.6.5.7. Dibujo y Representación Personalizados de Controles
        3.6.5.7.1. Representar un Control de Formularios Windows Forms
        3.6.5.7.2. Controles Dibujados por el Usuario
        3.6.5.7.3. Controles Constituyentes
        3.6.5.7.4. Cómo: Hacer un Control No Visible en Tiempo de Ejecución
        3.6.5.7.5. Cómo: Proporcionar un Fondo Transparente a un Control
        3.6.5.7.6. Representar Controles con Estilos Visuales
          3.6.5.7.6.1. Cómo: Utilizar una Clase de Representación de Controles
          3.6.5.7.6.2. Cómo: Representar un Elemento de Estilo Visual
      3.6.5.8. Diseño de los Controles de Formularios Windows Forms
        3.6.5.8.1. Información General sobre la Propiedad AutoSize
        3.6.5.8.2. Cómo: Alinear un Control con los Bordes de los Formularios
        3.6.5.8.3. Márgenes y Relleno en Controles de Formularios Windows
        3.6.5.8.4. Cómo: Crear un Borde Alrededor de un Control con Relleno
        3.6.5.8.5. Cómo: Implementar un Motor de Diseño Personalizado
      3.6.5.9. Subprocesamiento Múltiple en los Controles de Formularios Windows
        3.6.5.9.1. Cómo: Realizar Llamadas Seguras para Subprocesos en Controles de Formularios Windows Forms
        3.6.5.9.2. Cómo: Utilizar un Subproceso en Segundo Plano para Buscar Archivos
    3.6.6. Desarrollar Controles de Formularios Windows Forms en Tiempo de Diseño
      3.6.6.1. Tutorial: Crear un Control Compuesto con Visual Basic
      3.6.6.2. Tutorial: Heredar de un Control de Formularios Windows Forms con Visual Basic
      3.6.6.3. Tutorial: Realizar Tareas Comunes utilizando Etiquetas Inteligentes
      3.6.6.4. Tutorial: Serializar Colecciones de Tipos Estándar con DesignerSerializationVisibilityAttribute
      3.6.6.5. Tutorial: Depurar Controles Personalizados en Tiempo de Diseño
      3.6.6.6. Cómo: Crear Controles de Formularios Windows Forms
      3.6.6.7. Cómo: Crear Controles Compuestos
      3.6.6.8. Cómo: Heredar de una Clase UserControl
      3.6.6.9. Cómo: Heredar de Controles de Formularios Existentes
      3.6.6.10. Cómo: Heredar de una Clase de Control
      3.6.6.11. Cómo: Alinear un Control con los Bordes de los Formularios en Tiempo de Diseño
      3.6.6.12. Cómo: Mostrar un Control en el Cuadro de Diálogo Personalizar Cuadro de Herramientas
      3.6.6.13. Cómo: Proporcionar un Mapa de Bits del Cuadro de Herramientas para un Control
      3.6.6.14. Cómo: Comprobar el Comportamiento de un Control de Usuario en Tiempo de Ejecución
      3.6.6.15. Errores en Tiempo de Diseño en el Diseñador de Windows Forms
      3.6.6.16. Solución de Problemas Relacionados con la Creación de Controles y Componentes
  3.7. Datos Proporcionados por el Usuario en Formularios Windows Forms
    3.7.1. Datos Introducidos por el Usuario en una Aplicación de Formularios
    3.7.2. Entradas mediante Teclado en una Aplicación de Windows Forms
      3.7.2.1. Funcionamiento de las Entradas mediante Teclado
      3.7.2.2. Utilizar Eventos de Teclado
      3.7.2.3. Cómo: Modificar las Entradas mediante Teclado en un Control Estándar
      3.7.2.4. Cómo: Determinar qué Tecla Modificadora se Presionó
      3.7.2.5. Cómo: Controlar los Datos Introducidos mediante el Teclado en el Formulario
    3.7.3. Entradas Mediante el Mouse en una Aplicación de Windows Forms
      3.7.3.1. Funcionamiento de la Entrada del Mouse en los Formularios Windows
      3.7.3.2. Eventos del Mouse en Formularios Windows Forms
      3.7.3.3. Cómo: Distinguir Operaciones de Clic y Doble Clic
      3.7.3.4. Punteros del Mouse en Formularios Windows Forms
      3.7.3.5. Captura del Mouse en Formularios Windows Forms
      3.7.3.6. Funcionalidad de Arrastrar y Colocar en Formularios Windows Forms
    3.7.4. Cómo: Simular Eventos del Mouse y del Teclado en el Código
    3.7.5. Validación de los Datos Proporcionados por el Usuario en Formularios
  3.8. Cuadros de Diálogo en Formularios Windows Forms
    3.8.1. Cómo: Mostrar Cuadros de Mensaje
    3.8.2. Cómo: Crear Cuadros de Diálogo en Tiempo de Diseño
    3.8.3. Cómo: Recuperar Información del Formulario Primario de un Cuadro de Diálogo
    3.8.4. Cómo: Recuperar la Información de un Cuadro de Diálogo Selectivamente mediante Múltiples Propiedades
    3.8.5. Cómo: Recuperar el Resultado de los Cuadros de Diálogo
    3.8.6. Cómo: Cerrar Cuadros de Diálogo y Conservar Datos Introducidos por Usuario
    3.8.7. Introducción de Datos por el Usuario en los Cuadros de Diálogo
    3.8.8. Tutorial: Recuperar la Información de un Cuadro de Diálogo Colectivamente mediante Objetos
  3.9. Enlace de Datos en Formularios Windows Forms
    3.9.1. Enlace de Datos y Formularios Windows Forms
    3.9.2. Orígenes de Datos Compatibles con Formularios Windows Forms
    3.9.3. Interfaces Relacionadas con el Enlace de Datos
    3.9.4. Notificación de Cambios en el Enlace de Datos de Windows Forms
    3.9.5. Cómo: Desplazarse por Datos en Formularios Windows Forms
    3.9.6. Cómo: Implementar la Interfaz INotifyPropertyChanged
    3.9.7. Cómo: Aplicar el Modelo PropertyNameChanged
    3.9.8. Cómo: Garantizar que Varios Controles Enlazados al mismo Origen de Datos Permanezcan Sincronizados
    3.9.9. Cómo: Garantizar que la Fila Seleccionada de una Tabla Secundaria Conserva la Posición Correcta
    3.9.10. Cómo: Crear un Control con Enlace Simple en un Formulario Windows Forms
    3.9.11. Cómo: Crear un Control Enlazado y Aplicar Formato a los Datos Mostrados
  3.10. Seguridad en los Formularios Windows Forms
    3.10.1. Información General sobre la Seguridad en Formularios Windows Forms
    3.10.2. Acceso más Seguro a Archivos y Datos en Formularios Windows Forms
    3.10.3. Impresión más Segura en Formularios Windows Forms
    3.10.4. Consideraciones de Seguridad Adicionales en Formularios Windows Forms
  3.11. Cómo: Obtener Acceso a Colecciones con Claves en Formularios Windows Forms
4. Mejorar las Aplicaciones de Windows Forms
  4.1. Configuración de la Aplicación en Formularios Windows Forms
    4.1.1. Introducción a la Configuración de la Aplicación
    4.1.2. Arquitectura de Configuración de la Aplicación
    4.1.3. Atributos de Configuración de la Aplicación
    4.1.4. Configuración de la Aplicación para Controles Personalizados
    4.1.5. Utilizar Valores de Configuración de Aplicación y de Usuario
      4.1.5.1. Cómo: Crear un Nuevo Valor de Configuración en Tiempo de Diseño
      4.1.5.2. Cómo: Cambiar el Valor de una Opción de Configuración Existente en Tiempo de Diseño
      4.1.5.3. Cómo: Cambiar el Valor de una Opción de Configuración entre Sesiones de Aplicación
    4.1.6. Cómo: Validar la Configuración de la Aplicación
    4.1.7. Cómo: Crear la Configuración de la Aplicación
    4.1.8. Cómo: Crear una Configuración de Aplicación mediante el Diseñador
    4.1.9. Cómo: Enlazar una Propiedad a un Valor de Aplicación Existente mediante el Diseñador
    4.1.10. Cómo: Modificar un Enlace de Propiedades para la Configuración de la Aplicación mediante el Diseñador
    4.1.11. Depurar Aplicaciones de Windows Forms que Utilizan la Configuración de Aplicación con Visual Studio
  4.2. Funcionalidad para Imprimir en Formularios Windows Forms
    4.2.1. Cómo: Crear Trabajos de Impresión Estándar de Formularios Windows Forms
    4.2.2. Cómo: Capturar Datos Proporcionados por el Usuario de un Componente PrintDialog en Tiempo de Ejecución
    4.2.3. Cómo: Seleccionar las Impresoras Conectadas al Equipo de un Usuario
    4.2.4. Cómo: Imprimir Gráficos en Formularios Windows Forms
    4.2.5. Cómo: Imprimir un Archivo de Texto de Varias Páginas en Formularios
    4.2.6. Cómo: Completar Trabajos de Impresión de Formularios Windows Forms
    4.2.7. Cómo: Imprimir en Formularios Windows Forms Usando la Vista Preliminar
  4.3. Compatibilidad con las Operaciones de Arrastrar y Colocar y con el Portapapeles
    4.3.1. Tutorial: Llevar a cabo una Operación de Arrastrar y Colocar en Formularios
    4.3.2. Cómo: Agregar Datos al Portapapeles
    4.3.3. Cómo: Recuperar Datos del Portapapeles
    4.3.4. Cómo: Llevar a cabo Operaciones de Arrastrar y Colocar entre Aplicaciones
  4.4. Funciones de Red en las Aplicaciones de Windows Forms
    4.4.1. Tutorial: Llamar a los Servicios Web XML Desde un Formulario Windows Forms
  4.5. Globalizar Formularios Windows Forms
    4.5.1. Fuentes Internacionales en Formularios Windows Forms y Controles
    4.5.2. Visualización de Caracteres Asiáticos con la Propiedad ImeMode
    4.5.3. Compatibilidad Bidireccional en las Aplicaciones de Windows Forms
    4.5.4. Codificación y Globalización de Formularios Windows Forms
    4.5.5. Tutorial: Adaptar Formularios Windows Forms
    4.5.6. Tutorial: Crear un Diseño que Ajuste las Proporciones para la Localización
    4.5.7. Cómo: Admitir la Localización en Formularios Windows Forms mediante AutoSize y el Control TableLayoutPanel
    4.5.8. Cómo: Mostrar Texto de Derecha a Izquierda en Formularios Windows Forms para la Globalización
    4.5.9. Cómo: Establecer la Referencia Cultural y la Referencia Cultural de la Interfaz de Usuario para la Globalización de Formularios Windows Forms
    4.5.10. Cómo: Crear Cuadros de Mensaje en Formularios Windows Forms Bidireccionales
    4.5.11. Cómo: Crear Controles y Formularios Windows Forms Reflejados
    4.5.12. Implementación y Localización de ClickOnce
  4.6. Información del Sistema y Formularios Windows Forms
  4.7. Administración de Energía en Formularios Windows Forms
  4.8. Características de Windows XP y Controles de Formularios Windows Forms
  4.9. Herencia Visual de Formularios Windows Forms
    4.9.1. Cómo: Heredar Formularios Windows Forms
    4.9.2. Cómo: Heredar Formularios mediante el Cuadro de Diálogo Selector de Herencia
    4.9.3. Efectos de Modificar la Apariencia de un Formulario Base
    4.9.4. Tutorial: Demostración de la Herencia Visual
    4.9.5. Cómo: Utilizar las Propiedades Modifiers y GenerateMember
  4.10. Aplicaciones de Interfaz de Múltiples Documentos (MDI)
    4.10.1. Cómo: Crear Formularios Principales MDI
    4.10.2. Cómo: Crear Formularios MDI Secundarios
    4.10.3. Cómo: Determinar el Formulario Secundario MDI Activo
    4.10.4. Cómo: Enviar Datos al Formulario Secundario MDI Activo
    4.10.5. Cómo: Organizar Formularios MDI Secundarios
  4.11. Integrar la Ayuda de Usuario en Formularios Windows Forms
    4.11.1. Cómo: Proporcionar Ayuda en una Aplicación para Windows
    4.11.2. Cómo: Mostrar Ayuda Emergente
    4.11.3. Controlar la Ayuda mediante Información sobre Herramientas
  4.12. Accesibilidad de Formularios Windows Forms
    4.12.1. Tutorial: Crear una Aplicación Accesible basada en Windows
    4.12.2. Propiedades de los Controles de Formularios Windows que Admiten las Directrices de Accesibilidad.

Descarga
MSDN_Manual_Windows_Forms_3.5

viernes, 26 de septiembre de 2014

El Demo del Día: Visor de Imágenes con Zoom en WinForms

Visor de Imágenes con Zoom en WinForms

Este post es a pedido de un alumno que quiere una aplicación en Windows Forms que muestre una secuencia de Imágenes y pueda realizar el Zoom.

Crear la Aplicación Windows Forms

Primero crearemos una aplicación en Windows Forms en C# llamada: "VisorImagenesZoom".
Cambiar de nombre al formulario por el de "frmVisor", luego diseñar la pantalla como se muestra en la siguiente figura:


Nota: También hay que incluir un Timer llamado "tmrPreview" que cada 3 segundos muestre las imágenes del directorio seleccionado.

Escribir el siguiente código en el formulario:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;

namespace VisorImagenesZoom
{
    public partial class frmVisor : Form
    {
        private int c;
        private int n;
        private Point punto1;

        public frmVisor()
        {
            InitializeComponent();
        }

        private void abrirDirectorio(object sender, EventArgs e)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            if (fbd.ShowDialog().Equals(DialogResult.OK))
            {
                txtDirectorio.Text = fbd.SelectedPath;
                IEnumerable<string> archivos = Directory.EnumerateFiles(fbd.SelectedPath, "*.jpg");
                lstArchivo.Items.Clear();
                lstArchivo.BeginUpdate();
                foreach (string archivo in archivos)
                {
                    lstArchivo.Items.Add(Path.GetFileNameWithoutExtension(archivo));
                }
                lstArchivo.EndUpdate();
                txtTotalArchivos.Text = lstArchivo.Items.Count.ToString();
                tmrPreview.Enabled = true;
                tmrPreview.Start();
            }
        }

        private void mostrarImagenes(object sender, EventArgs e)
        {
            lstArchivo.SelectedIndex = c;
            string archivo = Path.Combine(txtDirectorio.Text, lstArchivo.Items[c].ToString() + ".jpg");
            picPreview.LoadAsync(archivo);
            c++;
            if (c == lstArchivo.Items.Count) c = 0;
        }

        private void configurarZoom(object sender, MouseEventArgs e)
        {
            if (e.Button.Equals(MouseButtons.Left))
            {
                if (n == 0)
                {
                    punto1 = e.Location;
                    tmrPreview.Stop();
                    tmrPreview.Enabled = false;
                }
                else
                {
                    if (n == 1)
                    {
                        Point punto2 = e.Location;
                        string archivo = Path.Combine(txtDirectorio.Text,
                                                   lstArchivo.Items[c].ToString() + ".jpg");
                        Bitmap bmp = new Bitmap(picPreview.Image);
                        Bitmap bmpZoom = new Bitmap(bmp.Width, bmp.Height);
                        Graphics g = Graphics.FromImage(bmpZoom);
                        float ratioX = (bmp.Width/picPreview.Width);
                        float ratioY = (bmp.Height / picPreview.Height);
                        int posX = (int)(ratioX * punto1.X);
                        int posY = (int)(ratioY * punto1.Y);
                        int ancho = (int)(ratioX*(punto2.X-punto1.X));
                        int alto = (int)(ratioY * (punto2.Y - punto1.Y));
                        Rectangle srcRect = new Rectangle(posX, posY, ancho, alto);
                        Rectangle dstRect = new Rectangle(0, 0, bmpZoom.Width, bmpZoom.Height);
                        g.DrawImage(bmp, dstRect, srcRect, GraphicsUnit.Pixel);
                        picPreview.Image = bmpZoom;
                        tmrPreview.Enabled = true;
                        tmrPreview.Start();
                    }
                }
                n++;
                if (n == 2) n = 0;
            }
        }
    }
}

Nota: Para programar el Zoom se ha asociado al evento MouseClick del PictureBox llamado "picPreview" donde en el primer clic se captura la ubicación del punto y se guarda en una variable "punto1" y en el segundo clic se captura el punto2 y se crea un rectangulo con la imagen para el Zoom. Solo hay que tener en cuenta que el Rectangulo debe ser en base a la imagen (Bitmap) del PictureBox y No al tamaño del control (con propiedad SizeMode en StrechImage), por lo cual se crea las variables ratios.

Probar la Aplicación Creada

Grabar el proyecto y ejecutarlo con F5. Seleccionar un directorio donde se encuentren archivos jpg y se mostraran en la lista tal como aparece en la siguiente figura:


Cada 3 segundos cambiara la imagen y se seleccionara en la lista el archivo que se esta mostrando, dar el primer clic sobre la imagen y luego el segundo clic mostrará el preview de la imagen, tal como sigue:


Comentario Final

En este post hemos visto como mostrar una secuencia de imágenes usando un Timer y también como realizar el Zoom de una Imagen usando el método DrawImage de la clase Graphics para dibujar un rectángulo con la imagen especificada al dar dos clics, uno para marcar el punto de inicio y otro para marcar el punto final.

Descarga:
Demo19_VisorImagenesZoom



lunes, 23 de junio de 2014

El Demo del Día: Comparación de Rendimiento al Llenar Listas en WinForms

Comparación de Rendimiento al Llenar Listas en WinForms

En este post, compararemos el rendimiento de diferentes técnicas para llenar listas en Windows Forms desde un arreglo. En WinForms los controles ListBox, ComboBox, CheckedListBox y ListView tienen una colección de Items que representan los elementos del control. Aprenderemos varias formas de mejorar la performance o rendimiento al llenar controles de tipo listas.

Problema al Llenar Listas en WinForms

Si tenemos un arreglo con datos y queremos llenar un control de tipo lista en WinForms, muchos programadores crean un bucle (for, foreach, while) y leen del arreglo cada elemento y lo agregan al control lista. Si son muchos registros a agregar el tiempo aumenta considerablemente en proporción a la cantidad de filas y se nota un parpadeo al momento de pintar el control.

Solución al Problema de Llenar Listas en WinForms

Existen 2 formas de solucionar el problema del rendimiento al llenar un control lista desde un arreglo:

1. Usar el método AddRange de la colección de Items del control lista y agregar directamente el arreglo.

2. Usar el método BeginUpdate antes del bucle para congelar la actualización en pantalla de fila x fila y al final del bucle llamar al método EndUpdate para actualizar el pintado del control lista.

Diseño de la Aplicación WinForms

Crear una aplicación WinForms llamada: "Comparacion_Rendimiento_Listas" en C# y cambiar de nombre al formulario por "frmLista", luego agregar los siguientes controles:
- Un Control Label llamado "lblTiempoProcesamiento"
- Un Control ListBox llamado "lstNumero"
- Cinco Controles Button llamados: "btnLlenarArreglo", "btnLlenarListaForItemsAdd",
  "btnLlenarListaAddRange", "btnLlenarListaForItemsAddBU" y "btnLlenarListaAddRangeBU".


Código Fuente de la Aplicación WinForms

En el código he creado un método "ejecutarMetodo" que tiene como parámetro un método gracias al tipo "Action" lo que me permite crear una rutina que permita "medir el tiempo de procesamiento de cualquier método" para poder comparar los tiempos en cada caso, para lo cual usamos la clase "Stopwatch" de "System.Diagnostics".
Además usamos un arreglo de cadenas, el cual lo llenamos con 10000 registros para poder ser pasados al control ListBox con las diferentes técnicas.

using System.Windows.Forms;
using System.Diagnostics;

namespace Comparacion_Rendimiento_Listas
{
    public partial class frmLista : Form
    {
        private string[] lista;

        public frmLista()
        {
            InitializeComponent();
        }

        public string ejecutarMetodo(Action metodo)
        {
            Stopwatch oReloj = new Stopwatch();
            oReloj.Start();
            metodo();
            oReloj.Stop();
            return (String.Format("Tiempo de Procesamiento: {0:n0} msg",
            oReloj.Elapsed.TotalMilliseconds));
        }

        private void llenarArreglo()
        {
            lista=new string[10000];
            for (int i = 0; i < lista.Length; i++)
            {
                lista[i] = i.ToString();
            }
        }

        private void btnLlenarArreglo_Click(object sender, EventArgs e)
        {
            lblTiempoProcesamiento.Text = ejecutarMetodo(llenarArreglo);
        }

        private void llenarListaForItemsAdd()
        {
            lstNumero.Items.Clear();
            for (int i = 0; i < lista.Length; i++)
            {
                lstNumero.Items.Add(lista[i]);
            }
        }

        private void btnLlenarListaForItemsAdd_Click(object sender, EventArgs e)
        {
            lblTiempoProcesamiento.Text = ejecutarMetodo(llenarListaForItemsAdd);
        }

        private void llenarListaAddRange()
        {
            lstNumero.Items.Clear();
            lstNumero.Items.AddRange(lista);
        }

        private void btnLlenarListaAddRange_Click(object sender, EventArgs e)
        {
            lblTiempoProcesamiento.Text = ejecutarMetodo(llenarListaAddRange);
        }

        private void llenarListaForItemsAddConBeginUpdate()
        {
            lstNumero.BeginUpdate();
            lstNumero.Items.Clear();
            for (int i = 0; i < lista.Length; i++)
            {
                lstNumero.Items.Add(lista[i]);
            }
            lstNumero.EndUpdate();
        }

        private void btnLlenarListaForItemsAddBU_Click(object sender, EventArgs e)
        {
            lblTiempoProcesamiento.Text = ejecutarMetodo(llenarListaForItemsAddConBeginUpdate);
        }

        private void llenarListaAddRangeConBeginUpdate()
        {
            lstNumero.BeginUpdate();
            lstNumero.Items.Clear();
            lstNumero.Items.AddRange(lista);
            lstNumero.EndUpdate();
        }

        private void btnLlenarListaAddRangeBU_Click(object sender, EventArgs e)
        {
            lblTiempoProcesamiento.Text = ejecutarMetodo(llenarListaAddRangeConBeginUpdate);
        }
    }
}

Ejecución y Pruebas de la Aplicación WinForms

Si ejecutamos la aplicación y damos clic al botón "Llenar Arreglo" notamos que el tiempo de procesamiento es de 2 msg (mili segundos), si damos clic al botón "Llenar Lista For Items Add" el tiempo de procesamiento es de 3306 msg (este puede variar cada vez que se da clic entre 2500 y 3500 aproximadamente), además en todo este tiempo se nota la aplicación en espera y con parpadeo.


Si damos clic al botón "Llenar Lista AddRange" o los otros 2 últimos botones (es decir las 3 formas de mejor rendimiento) notamos que el tiempo de procesamiento es de 69 msg (puede variar entre 60 y 80 msg).


Comentario Final

Después de hacer las comparaciones de rendimiento nos damos cuenta que la diferencia es extremadamente abismal, para 10000 filas el método clásico del bucle demora mas de 3000 msg mientras que las otras 3 técnicas solo 70 msg, es decir una diferencia de 3000, la cual aumenta con el aumento de los registros.

Después de esto, espero que ningún programador se olvide de colocar "BeginUpdate" antes del llenado de su lista y al final "EndUpdate" o use directamente el método AddRange.

Descarga:
Demo05_Rendimiento_Listas