Lexico
...el poder de lo simple...
Abril.14.2010

Aplicacion dirigida por eventos con interfaz gráfica

Qué es una aplicación Lote, Batch o de Consola ?


Es una aplicación formada por un solo algoritmo que comanda la secuencia de acciones del computador. En ella están prescritas el tipo y el momento en que deben ocurrir acciones externas para proporcionar datos a la aplicación. El agente externo con el que interactúa, generalmente un usuario final, no tiene más que atender los requerimientos del programa en el orden y tipos exigidos. El programa es un dictador que no admite que el usuario tome la iniciativa. Al ejecutarse efectúa las instrucciones prescritas y termina.

Qués es una aplicación dirigida por eventos ?


Es una aplicación que permanece abierta espectante a acciones externas y ante las cuales reacciona en consecuencia. Las acciones externas son conocidas como eventos. Generalmente los eventos los desencadena un usuario final al manipular la interfaz gráfica de la aplicación. Las ocurrencias de los eventos son establecidos por el agente externo a la aplicación o usuario en el momento que lo desee y el tipo que quiera debe existir entre los tipos de eventos previstos por el programador. Es una gran diferencia con las aplicaciones batch donde tanto el tipo de evento y el momento se su ocurrencia son establecidos por el programador pues es él quien en el único algoritmo ordena cuando deben ocurrir los eventos y de cual tipo.

En una aplicación orientada por eventos el programador establece los tipos de eventos que permitirá escuchar la aplicación y diseña los correspondientes algoritmos que los atenderán o que reaccionarán ante su ocurrencia. Tales algoritmos son conocidos como controladores o manejadores de eventos pues su función es generar una consecuencia o reacción ante la ocurrencia de un evento en particular activado en el entorno. Entonces una aplicación bajo ésta modalidad estará formada por muchos algoritmos especializados en funciones particulares que serán ejecutados en el momento necesario generalmente como reacción a las iniciativas del usuario. La aplicación inicia pero no termina automáticamente sino por la voluntad del usuario generalmente. Ella al iniciar su funcionamiento queda espectante a las acciones del usuario o del entorno.


Manejo de eventos en una aplicación


Cómo lograr facilmente incorporar la infraestructura de la plataforma para el manejo de eventos en una aplicación ?

Se puede hacer creando una clase que represente la aplicación y heredando la infraestructura ya programada en la clase Form de la plataforma .NET

Debido a que las máquinas físicas son únicas en una instalación pero son usadas por varias aplicaciones es necesaria la coordinación de su uso. Ésta función la desempeña el Sistema Operativo encargándose de detectar las acciones externas en cuanto a tipo, momento de ocurrencia y destinatario. Luego envía el mensaje apropiado a la cola de mensajes de la aplicación destinataria para que ella los vaya tomando de allí y los vaya procesando. Lo anterior significa que en un ambiente de multiprogramación, donde están corriendo varios programas, se forma entre el Sistema Operativo y las aplicaciones un diálogo de intercambio de datos.

La creación y disparo de eventos puede ocurrir en cualquier aplicación. Miraremos primero, por ser lo fundamental, una forma de atender mensajes enviados por el Sistema Operativo ante la presencia de los principales eventos ocurridos en la máquina física.


Control de principales eventos

Un evento es un suceso que ocurre en el entorno donde funciona una aplicación y para su atención se debe programar en ella un método que controle las acciones necesarias para responderle a cada tipo de evento que se necesite. A diferencia de la programación secuencial, batch por lotes o tipo consola (en la que el programador exige una secuencia estricta de aparición de los eventos), no se sabe cual será el orden de aparición de ellos pues normalmente son el usuario o el sistema operativo quienes los generan según su intención y necesidades. La aplicación debe adoptar, entonces, la forma de intérprete o de máquina de estados para que esté atenta a reaccionar según sea el caso. En éste tipo de aplicaciones es el usuario quien toma la iniciativa. Cuando se ejecuta la aplicación (se ejecuta su método constructor) queda espectante a lo que pueda ocurrir en su entorno y reaccionar ejecutando el método apropiado que debe haber sido programado para ello.
 
El sistema operativo ya existe pero debe invocar un método (enviar un mensaje a la aplicación) que solo ahora la persona programa.  Recuérdese la forma de enviar un mensaje a un objeto, es decir ordenarle al objeto ejecute uno de sus algoritmos o métodos en particular:

    Objeto.AlgoritmoSinArgumentos                                    o
    Objeto.Algoritmo(lista de argumentos separados con comas)

Primero haga la siguiente reflexión: El Sistema Operativo fue construido hace años, nuestra aplicación solo ahora: Cómo hacer que se comuniquen si el primero "no sabe" cómo se llaman nuestros algoritmos o métodos que debe echar a andar para atender los respectivos eventos ?

Se logra así:

En el Sistema Operativo se establece un protocolo de comunicación y en la aplicación se usa ese protocolo.

1. El Sistema Operativo detecta la ocurrencia del evento
2. El Sistema Operativo detecta que viene dirigido a nuestra aplicación (digamos que es Mi Clase)
3. El Sistema Operativo envía un mensaje con los detalles del evento: Mi Clase.Nombre_del_método(doy tal, doy Pascual)
4. El mensaje queda en la cola de mensajes de nuestra aplicación en espera de ser atendido

Por ello el programador debe hacer dos cosa cada que desee que la aplicación atienda, controle o maneje un tipo de evento en particular:
 
1. Elaborar el método o algoritmo (mensaje que la aplicación entenderá) que se ejecutará ante la aparición de un tipo de evento .
2. Inscribir ese método como un controlador o manejador dentro de la aplicación para que el sistema operativo sepa qué invocar.
 
Para lo primero debe seguirse un protocolo o firma del método que case con lo que ya existe programado en el Sistema Operativo. Constará de un nombre y dos parámetros de entrada pues él enviará información a la aplicación sobre el control en el que ocurrió el evento y un paquete con datos relevantes a ese tipo de evento. La forma de los métodos manejadores de eventos será, entonces:
 
     Nombre_del_método(deme NC, deme detalles es un TipoDeArgumentosDeEvento)
         {
              /*  ...aquí irá la lógica del control y puede utilizar la información enviada en detalles por el Sistema Operativo....
                     (el TipoDeArgumentosDeEvento que se recibe varía dependiendo del tipo de evento) */
         }
 
Para lo segundo, debe instruir al Sistema Operativo sobre el control donde interesa la ocurrencia del evento, el tipo de evento y el método que lo atenderá, mediante el uso del método Lexico llamado manejador, así por ejemplo cuando exista el botón BOT en la aplicación Mi Clase y se desee atender el evento Click con el algoritmo  MiAlgoritmo  se programará en su constructor:
 
       Mi Clase .manejador(BOT. Click,  MiAlgoritmo)
 
Hay muchos eventos ya reconocidos por el sistema operativo y quizás los más utilizados sean:
Paint                : Pintura se genera cada vez que el S.O. detecta la necesidad de restaurar la imagen de un formulario
KeyDown        : TeclaPresionada por el usuario (o simulada por algún programa)
MouseDown    : Un botón del ratón ha sido presionado (o simulado).
Tick                 : Un temporizador ha generado un aviso o alarma
MouseUp        : Un botón del ratón ha sido liberado (o simulado).
MouseMove    : El ratón ha sido movido (o simulado).
Click                : Se ha pulsado con un botón del ratón sobre un control.
...


Recuerde para cada tipo de evento que quiera controlar:

1.  Utilizar el siguiente protocolo cada vez que vaya a programar un algoritmo controlador o manejador de un tipo de evento:

Nombre_del_algoritmo_manejador(deme Dónde_ocurrió_el_evento, deme detalles_del_evento es un TipoDeArgumentosDeEvento)
    {
    .....aquí irá la lógica que reacciona, controla o maneja el evento
    }

2. Registrar ante el sistema operativo en el algoritmo constructor de la clase el Nombre_del_algoritmo_manejador que haya establecido para reacionar, controlar o manejar un tipo de evento:

   
Mi Clase .manejador(Objeto_donde_el_evento_se_controlaráTipo_de_evento,  Nombre_del_algoritmo_manejador)


(antes recuerde 
Cómo  hacer una clase ?)


Un ejemplo:

Se controlará con el algoritmo
mi_controlador_de_teclado el tipo de evento KeyDown cuando ocurra en la aplicación ventana, se recibirá del Sistema Operativo un objeto que llamaremos chismoso y trae los detalles del evento que, en éste caso, es del tipo KeyEventArgs. El control simplemente será mostrar cuando hayan pulsado una de las 7 teclas A B 1 2 Flech-dereca Flecha-izquierda Esc:

clase ventana derivada_de Form
{
publicos:
mensajes:

mi_controlador_de_teclado(entra objeto_enviador, entra chismoso es un KeyEventArgs)
               {
               es chismoso.KeyCode=Keys.A ? si: muestre "Pulsada la tecla A"
               es chismoso.KeyCode=Keys.B ? si: muestre "Pulsada la tecla B"
               es chismoso.KeyCode=Keys.D1 ? si: muestre "Pulsada la tecla 1"
               es chismoso.KeyCode=Keys.D2 ? si: muestre "Pulsada la tecla 2"
               es chismoso.KeyCode=Keys.Right ? si: muestre "Pulsada Flecha Derecha"
               es chismoso.KeyCode=Keys.Left ? si: muestre "Pulsada Flecha Izquierda"
               es chismoso.KeyCode=Keys.Escape ?
            si:    {
                muestre "Pulsada la tecla Esc ==> cerraré la aplicación"
                ventana.Close
                }
               }

ventana
    {
    copie " Mi quinta ventana" en ventana.Text
    ventana.manejador(sale ventana.KeyDown, sale mi_controlador_de_teclado)
    }
}


Ejemplo: Cómo manejar el evento Paint (pintura) ?

/* Mob122_ControlEventoPaint.lx */

clase ventana derivada_de Form
publicos:
    el objeto graficador es un Graphics no_crear
    el objeto lápiz es un Pen(doy Color.Green, doy 2)
    el objeto pincel es un SolidBrush(sale Color.Blue)
    el objeto pincel2 es un SolidBrush(sale Color.White)
    el objeto tipo_de_letra es un Font(sale "Verdana", sale 20, FontStyle.Regular)

mensajes:
mi_controlador_de_pintura(entra objeto_enviador, entra chismoso es un PaintEventArgs)
    {
    copie chismoso.Graphics en graficador

      /* Aquí se programan las acciones pictóricas necesarias */
    graficador.DrawLine(doy lápiz, doy 20, doy 30, doy 77, doy 88)
    graficador.DrawString( sale "Hola amigos", sale tipo_de_letra, sale pincel, sale 22, sale 62 )
    graficador.DrawString( sale "Hola amigos", sale tipo_de_letra, sale pincel2, sale 20, sale 60 )
    }

ventana
    {
    copie " Mi segunda ventana" en ventana.Text
    ventana.manejador(sale "ventana.Paint", sale " mi_controlador_de_pintura")
    }


Ejemplo: Cómo reaccionar frente al evento MouseDown ?

clase ventana derivada_de Form
{
publicos:
mensajes:

mi_controlador_de_raton(entra objeto_enviador, entra chismoso es un MouseEventArgs)
{
es chismoso.Button=MouseButtons.Left ? si: muestre "Pulsado el botón izquierdo"
es chismoso.Button=MouseButtons.Right ? si: muestre "Pulsadael botón derecho"
es chismoso.Button=MouseButtons.Middle ? si: muestre "Pulsada el botón central"
}

ventana
    {
    copie " Mi sexta ventana" en ventana.Text
    ventana.manejador(sale "ventana.MouseDown", sale " mi_controlador_de_raton")
    }
}


Ejemplo: Cómo controlar el evento Tick de un temporizador ?

clase ventana derivada_de Form
{
publicos:
el objeto temporizador es un Timer
mensajes:

mi_controlador_de_temporizador(entra objeto_enviador, entra chismoso es un EventArgs)
{
muestre "Ya fuí avisado por el temporizador"
copie falso en temporizador.Enabled
ventana.Close
}

ventana
{
copie " Mi séptima ventana" en ventana.Text
ventana.manejador(sale "temporizador.Tick", sale "mi_controlador_de_temporizador")
copie 5000 en temporizador.Interval
copie verdadero en temporizador.Enabled
    }
}


Ejemplo: Cómo controlar el evento Click de un botón ?

clase Botarchi derivada_de Form
publicos
el objeto botón es un Button

mensajes
Botarchi
{
Botarchi.manejador(botón.Click, creararchivo)
Botarchi.AgregarControl(botón)
}

creararchivo(deme nn, deme chisme es un EventArgs)
{
el objeto archisalida es un StreamWriter("ArchivoTexto.txt")
archisalida.WriteLine("Línea 1")
archisalida.WriteLine("Línea 2")
archisalida.WriteLine("Línea 3")
archisalida.Close

System.Diagnostics.Process.Start("ArchivoTexto.txt", "")
}


Ejemplo: Cómo programar en Lexico un Skin (piel, máscara o fachada) ?

clase skin derivada_de Form
publicos
el objeto boton es un Button
el objeto pincel es un SolidBrush(doy Color.Blue)

mensajes
pulsado(deme nn, deme detalles es un EventArgs)
{
muestre "Cliqueado el botón, ciao...."
skin.Close
}

skin
{
copie "Salir" en boton.Text
copie Color.Yellow en boton.BackColor
skin.AgregarControl(doy boton)
skin.manejador(doy boton.Click, doy pulsado)

copie Color.Peru en skin.BackColor
copie Color.Peru en skin.TransparencyKey

el objeto fondo es un Bitmap(doy "transparente.PNG")
fondo.MakeTransparent
copie fondo en skin.BackgroundImage
copie FormBorderStyle.None en skin.FormBorderStyle
}



Ejemplo: Cómo agregar un menú a una ventana clásica ?

clase Editor derivada_de Form

privados:
el objeto menu es un MainMenu
los objetos archivo, edicion, proceso, ayuda son MenuItem
el objeto salir es un MenuItem

publicos:
mensajes:
Editor
{
    copie "EL" en Editor.text

    copie "&Archivo" en archivo.Text
    menu.MenuItems.Add(archivo)

    copie "&Edición" en edicion.Text
    menu.MenuItems.Add(edicion)

    copie "&Proceso" en proceso.Text
    menu.MenuItems.Add(proceso)

    copie "&Ayuda" en ayuda.Text
    menu.MenuItems.Add(ayuda)

    copie menu en Editor.menu

    Editor.manejador("archivo.Click", "clic_archivo")
    Editor.manejador("edicion.Click", "clic_edicion")
    Editor.manejador("proceso.Click", "clic_proceso")
    Editor.manejador("ayuda.Click",   "clic_ayuda")
}

clic_archivo(entra enviador, entra ch es un EventArgs)
    {
    muestre "archivo"
    }

clic_edicion(entra enviador, entra e es un EventArgs)
    {
    muestre "edicion"
    }

clic_proceso(entra enviador, entra e es un EventArgs)
    {
    muestre "proceso"
    }

clic_ayuda(entra enviador, entra e es un EventArgs)
    {
    muestre "ayuda"
    }


Ejemplo: Cómo animar un rectángulo ?

clase ventana derivada_de Form
publicos:
el objeto temporizador es un Timer
el objeto x es una cantidad

mensajes:
mi_controlador_de_temporizador(entra objeto_enviador, entra chismoso es un EventArgs)
{
copie x + 1 en x
ventana.Refresh
}

mi_controlador_de_pintura(entra objeto_enviador, entra chismoso es un PaintEventArgs)
{
el objeto g es un Graphics no_crear
copie chismoso.Graphics en g
el objeto crayola es un Pen(sale color.Gray, sale 2)

g.DrawRectangle(sale crayola, sale x, sale 10, sale 40, sale 20)
}

ventana
{
copie " Temporizador" en ventana.Text
ventana.manejador(sale "temporizador.Tick", sale "mi_controlador_de_temporizador")
ventana.manejador(sale "ventana.Paint", sale " mi_controlador_de_pintura")
copie verdadero en temporizador.Enabled
copie 0 en x
}


Ejemplo: Cómo generar un movimiento oscilatorio ?

clase ventana derivada_de Form
publicos:
el objeto temporizador es un Timer
los objetos x, ancho_del_recorrido son cantidades
el objeto sentido es un caracter

mensajes:
mi_controlador_de_temporizador(entra objeto_enviador, entra chismoso es un EventArgs)
{
es sentido="derecho" ?
   si: es x<ancho_del_recorrido ?
          si: copie x + 1 en x
        no:copie "izquierdo" en sentido

   no: es x>0 ?
     si: copie x-1 en x
     no:copie "derecho" en sentido

ventana.Refresh
}

mi_controlador_de_pintura(entra objeto_enviador, entra chismoso es un PaintEventArgs)
{
el objeto g es un Graphics no_crear
copie chismoso.Graphics en g
el objeto crayola es un Pen(sale color.Gray, sale 2)

g.DrawRectangle(sale crayola, sale x, sale 10, sale 40, sale 20)
}

ventana
{
copie " Temporizador" en ventana.Text
ventana.manejador(sale "temporizador.Tick", sale "mi_controlador_de_temporizador")
ventana.manejador(sale "ventana.Paint", sale "mi_controlador_de_pintura")
copie verdadero en temporizador.Enabled
copie 0 en x
copie 80 en ancho_del_recorrido
copie "derecho" en sentido
}



Ejemplo: Cómo crear un trazo con el ratón ? (corre tambien sobre Windows Mobile)

clase trazador derivada_de system.windows.forms.Form
publicos:
los objetos GX, GY son Collections.ArrayList
el objeto l es un Pen(Color.Blue, 2)
los objetos i, x, y son cantidades

mensajes:

trazador
{
copie "trazador" en trazador.text
trazador.Manejador("trazador.Paint", "pintura")
trazador.Manejador("trazador.MouseDown", "ratón")
}
/**********************************************/

pintura(deme nn, deme ch es un PaintEventArgs)
variando i desde 0 hasta GX.Count-1 haga:
    ch.Graphics.DrawEllipse(l, System.Convert.ToInt32(GX[i]), System.Convert.ToInt32(GY[i]), 3, 3)

ratón(deme nn, deme ch es un MouseEventArgs)
{
GX.Add(ch.X)
GY.Add(ch.Y)
trazador.Refresh
}


Ejemplo: Cómo minimizar una ventana ?

clase v derivada_de Form
publicos
mensajes
teclas(entra nn, entra ch es un KeyEventArgs)
        {
        es ch.KeyCode=Keys.Escape ? si: v.Close
        es ch.KeyCode=Keys.Down ?
             si: {
                  muestre "OJO: minimizará"
                  copie FormWindowState.Minimized en v.WindowState
                  }
        }

v {
   copie "   ========>   Use la Flecha Hacia abajo y Esc" en v.Text
   v.manejador(doy "v.KeyDown", doy "teclas")
   }


Ejemplo: Cómo manipular características de ventana ?

clase v derivada_de Form
publicos
mensajes:
v
{
copie FormStartPosition.Manual en v.StartPosition     /*para que tome la posición dada en Location, */

/* copie FormStartPosition.CenterScreen en v.StartPosition  ==> para que tome la posición centrada*/
/* http://msdn.microsoft.com/es-es/library/hw8kes41(VS.80).aspx */

copie FormBorderStyle.Fixed3D en v.FormBorderStyle     /*para fijar el tamaño (no dejar modificar tamaño) */
/* http://msdn.microsoft.com/es-es/library/hw8kes41(VS.80).aspx */
}


Ejemplo: Cómo maximizar una ventana y conocer tamaños ?

/*
  Con base en (Alejandro Rúa)
  http://ojarami.com/riosur.net/modules.php?name=Forums&file=viewtopic&p=557#557

  La clase SystemInformation entrega información sobre la configuración del entorno del sistema actual
  http://msdn.microsoft.com/es-es/library/system.windows.forms.systeminformation(VS.80).aspx
*/

clase ventana derivada_de Form
publicos:
mensajes:

ventana {
   /*Establecemos el estado inicial de la ventana como maximizada*/
   copie FormWindowState.maximized en ventana.WindowState

   /*Obtenemos la resolución actual del monitor*/

muestre
"# monitores= ", SystemInformation.MonitorCount,
"\nAncho monitor= ", SystemInformation.PrimaryMonitorSize.Width,
"\nAlto  monitor= ", SystemInformation.PrimaryMonitorSize.Height,
"\nAncho ventana maximizada= ", SystemInformation.PrimaryMonitorMaximizedWindowSize.Width,
"\nAlto  ventana maximizada= ", SystemInformation.PrimaryMonitorMaximizedWindowSize.Height

}


Ejemplo: Cómo abrir una segunda ventana transparente para ayudas ?

/*
  Con base en
  http://ojarami.com/riosur.net/modules.php?name=Forums&file=viewtopic&p=1300#1300
*/
clase a derivada_de Form
publicos
el objeto p es una SolidBrush(doy Color.Green)
el objeto f es una Font(doy "Arial", doy 20)
el objeto op es una cantidad
mensajes
pintura(deme nn, deme ch es un PaintEventArgs)
{
ch.Graphics.DrawString(doy "haga varios Clicks aquí", doy f, doy p, doy 20, doy 20)
}

suba (deme nn, deme ch es un MouseEventArgs)
{
copie op+5 en op
copie op/100 en a.Opacity
}

a
{
copie "Clicks en el área de usuario" en a.Text
a.manejador(doy "a.Paint",doy " pintura")
a.manejador(doy "a.MouseDown",doy "suba")
copie 15 en op
copie op/100 en a.Opacity
copie Color.Yellow en a.BackColor
   copie FormWindowState.maximized en a.windowState
}
/****************************************/

clase aplicación derivada_de Form
publicos
el objeto b es un Button

mensajes
aplicación
{
copie "Click en Botón para ayuda" en aplicación.Text
copie "Ayuda" en b.Text
aplicación.AgregarControl(b)
aplicación.Manejador(b.Click, abrir_ayuda)
}

abrir_ayuda(deme xx, deme det es un EventArgs)
{
el objeto ayuda es un a
ayuda.Show
}


Ejemplo: Cómo colocar N etiquetas ?

clase ventana derivada_de Form
publicos:
mensajes:

ventana
{
el objeto N es una cantidad
entre N
copie N.DemeCaracteres # " etiquetas !" en ventana.Text
el objeto i es una cantidad
variando i desde 1 hasta N haga
    {
    el objeto e es un Label
    ventana.agregarcontrol(e)
    copie i.DemeCaracteres en e.Text
    el objeto sitio es un Point(10, 25*i)
    copie sitio en e.Location
    }

muestre "El ArrayList Controls tiene ", ventana.Controls.Count, " controles"
}


Ejemplo: Cómo controlar el evento Click en N botones ?

clase ventana derivada_de Form
publicos:
mensajes:

ventana
{
el objeto N es una cantidad
entre N
copie N.DemeCaracteres # " botones !" en ventana.Text
el objeto i es una cantidad
es N<27 ? si:
variando i desde 1 hasta N haga
    {
    el objeto e es un Button
    ventana.agregarcontrol(e)
    copie i.DemeCaracteres en e.Text
    el objeto sitio es un Point(10, 25*i)
    copie sitio en e.Location
    copie Color.FromArgb(255, 0, 0, 10*(i-1)) en e.BackColor
    copie Color.Yellow en e.ForeColor
    ventana.manejador(e.Click lePegaron)
    }

muestre "El ArrayList Controls tiene ", ventana.Controls.Count, " controles"
}

lePegaron(deme nombreControl, deme chisme es un EventArgs)
{
muestre "Le pegaron al ", nombreControl.ToString
}


Ejemplo: Cómo conocer la hora ?

/* http://msdn.microsoft.com/es-es/library/system.datetime(VS.80).aspx */
clase ventana derivada_de Form
publicos:
el objeto segundos es una cantidad
el objeto t es un Timer
mensajes:
ventana
{
ventana.manejador(t.Tick, ya)
copie 1000 en t.Interval
t.Start
}

ya(deme xx, deme yy es un EventArgs)
{
copie DateTime.Now.Second en segundos
copie DateTime.Now.ToString en ventana.Text
copie ventana.Text # " --> " # DateTime.Now.Second.ToString # "=" # segundos.DemeCaracteres en ventana.Text
}


Ejemplo: Cómo validar (no admitir entrada numérica) ?

/*
Windows Mobile
http://msdn.microsoft.com/es-es/library/system.windows.forms.keys(VS.80).aspx
http://www.eggheadcafe.com/conversation.aspx?messageid=33966786&threadid=33947653
*/
clase tb derivada_de Form
publicos:
el objeto caja es un TextBox
el objeto pulsadoDígito es un Caracter

mensajes:
tb
{
copie "No admite dígitos" en tb.Text
tb.AgregarControl(caja)
tb.Manejador(caja.KeyDown, pulsada)
tb.Manejador(caja.KeyPress, presionada)
}

pulsada(entra nc, entra t es un KeyEventArgs)
{
copie "no" en  pulsadoDígito
es t.KeyCode>=Keys.D0 & t.KeyCode<=Keys.D9 ?
    si: copie "si" en pulsadoDígito
}

presionada(entra nc, entra t es un KeyPressEventArgs)
{
es pulsadoDígito = "si" ?
    si: copie Char.IsNumber(t.KeyChar) en t.Handled

copie caja.Text en tb.Text
}



Ejemplo: Cómo utilizar ícono y cursor ?

/* http://ojarami.com/riosur.net/modules.php?name=Forums&file=viewtopic&p=309#309 */

clase v derivada_de Form
publicos
el objeto ic es un Icon(sale "C:\\Archivos de programa\\riosur-junio-15-2009\\riosur\\iconos\\lx.ico")
el objeto icur es un Cursor(sale "C:\\WINDOWS\\Cursors\\pen_i.cur")
el objeto g es un Graphics no_crear
mensajes:
pinte(entra Q, entra CH es un PaintEventArgs)
{
copie CH.Graphics en g
g.DrawIcon(sale ic, sale 100, sale 200)
}

v
{
v.manejador(sale v.Paint, sale pinte)
copie ic en v.Icon
copie icur en v.Cursor
}



Ejemplo: Cómo suprimir parpadeo utilizando un PictureBox ?

clase ventana derivada_de Form
publicos:
los objetos grupoX, grupoY son ArrayList
los objetos i, x, y, ancho son cantidades
el objeto lápiz es un Pen (doy Color.Black)
el objeto graficador es un Graphics  no_crear

el objeto bitmap es un Bitmap(sale 1024, sale 768)
el objeto BMPgraficador es un Graphics no_crear

el objeto cuadro es un PictureBox                         /*NUEVO*/


mensajes:
algoritmo_pintura(entra E, entra chismoso es un PaintEventArgs)
  {
  copie chismoso.Graphics en graficador
  graficador.DrawImage(sale bitmap, sale 0, sale 0)
  }

algoritmo_movido_raton(entra E, entra chismoso es un MouseEventArgs)
      {
      copie chismoso.X-10 en x
      copie chismoso.Y-30 en y
      grupoX.RemoveAt(doy 0)
      grupoY.RemoveAt(doy 0)
      grupoX.Add(doy x)
      grupoY.Add(doy y)

       BMPgraficador.Clear(sale color.White)

  variando i desde 0 hasta grupoX.Count-1 haga:
      {
      copie 2*i en ancho
      copie grupoX[i] en x
      copie grupoY[i] en y
      BMPgraficador.DrawEllipse(sale lápiz, sale x, sale y, sale ancho, sale ancho)
      }

      copie bitmap en cuadro.Image                                              /*NUEVO*/

      ventana.Refresh
      }

ventana
      {
      copie " mover el mouse" en ventana.Text
      ventana.manejador(sale "ventana.Paint", sale "algoritmo_pintura")
      ventana.manejador(sale "cuadro.MouseMove", sale "algoritmo_movido_raton")/*NUEVO*/
      variando i desde 0 hasta 50 haga:
           {
            grupoX.Add(doy i)
            grupoY.Add(doy i)
           }

       el objeto tamaño es un Size(doy 1024, doy 768)          /*NUEVO*/
       copie tamaño en cuadro.Size                                           /*NUEVO*/
       ventana.AgregarControl(sale "cuadro")               /*NUEVO*/
       copie Graphics.FromImage(sale bitmap) en BMPgraficador
}


Ejemplo: Cómo programar persistencia de objetos ?

/* http://msdn.microsoft.com/es-co/library/ms229335(VS.80).aspx */
clase figura
{
privados
los objetos x, y, Id son cantidades
/*el objeto color es un System.Drawing.Color */
el objeto lápiz es un System.Drawing.Pen(doy color.Black)
el objeto pincel es un System.Drawing.SolidBrush(doy color.Black)
el objeto letra es un System.Drawing.Font(doy "Arial", doy 12, FontStyle.Regular)
el objeto nombre es un caracteres

publicos
mensajes
figura(deme xe, deme ye, deme num)
{
copie xe en x
copie ye en y
copie num en Id
copie Id.DemeCaracteres en nombre
}
figura nop
píntese(deme g es un System.Drawing.Graphics)
{
g.DrawRectangle(doy lápiz, doy x, doy y, doy 40, doy 20)
g.DrawString(doy nombre, doy letra, doy pincel, doy x, doy y)
}
deme_posicion(doy x, doy y) nop
vaya_a(deme xe, deme ye)
{
copie xe en x
copie ye en y
}
deme_sus_datos(doy x, doy y, doy Id) nop
}
/****************************************************************^^^^************/
clase ventana derivada_de Form
{
publicos:

los objetos xfig, yfig, x_del_clic, y_del_clic, i, a, b, xt, yt, total son cantidades
los objetos d1, d2, d3 son cantidades
el objeto con_arrastre es un caracteres

el objeto grupo es un System.Collections.ArrayList
los objetos graficador, otrog son System.Drawing.Graphics no_crear
/*el objeto color es un System.Drawing.Color */
el objeto lapiz es un System.Drawing.Pen(sale color.Black)
/*el objeto tipo_boton es una System.Windows.Forms.MouseButtons */
el objeto bitmap es un System.Drawing.Bitmap (doy 1024, doy 768)
el objeto picture es un System.Windows.Forms.PictureBox

el objeto actual es una figura no_crear

mensajes:
clic_en_boton_del_raton(entra enviador, entra raton es un System.Windows.Forms.MouseEventArgs)
{
es raton.Button=MouseButtons.Left ?
si: variando i desde 0 hasta grupo.Count-1 haga:
{
el objeto yy es una figura no_crear
copie grupo[i] en yy
yy.deme_posicion(deme xfig, deme yfig)
es (raton.x > xfig) & (raton.x < xfig+40) & (raton.y > yfig) & (raton.y < yfig+20) ?
si:{
copie grupo.Count en i /* ...para obligar a suspender el ciclo pues ya sabe cual figura es */
copie yy en actual
copie "si" en con_arrastre
copie raton.x - xfig en x_del_clic
copie raton.y - yfig en y_del_clic
}
}
es raton.Button=MouseButtons.Right ?
si:{
copie raton.X en a
copie raton.Y en b
copie total + 1 en total
el objeto nuevo es una figura(doy a, doy b, doy total)
grupo.Add(doy nuevo)
}
ventana.Refresh
}

movido_el_raton(entra enviador, entra raton es un System.Windows.Forms.MouseEventArgs)
{
es con_arrastre="si" ?
si:{
copie raton.x - x_del_clic en xfig
copie raton.y - y_del_clic en yfig
actual.vaya_a(doy xfig, doy yfig)
ventana.Refresh
}
}

soltado_el_boton_del_raton(entra enviador, entra raton es un System.Windows.Forms.MouseEventArgs)
{
copie "no" en con_arrastre
}

pintar(entra sender, entra chismoso es un System.Windows.Forms.PaintEventArgs)
{
/*copie chismoso.Graphics en graficador */
graficador.Clear(doy color.Yellow)

variando i desde 0 hasta grupo.Count-1 haga:
{
el objeto xx es una figura no_crear
copie grupo[i] en xx
xx.píntese(doy graficador)
}
copie bitmap en Picture.Image
}

cerrando(entra enviador, entra ch es un System.ComponentModel.CancelEventArgs)
{
el objeto arch es un System.IO.StreamWriter(doy "Archivo con objetos.txt")
variando i desde 0 hasta grupo.Count-1 haga:
{
el objeto ss es una figura no_crear
copie grupo[i] en ss
ss.deme_sus_datos(deme d1, deme d2, deme d3)
arch.WriteLine(doy d1)
arch.WriteLine(doy d2)
arch.WriteLine(doy d3)
}
arch.Close
}

ventana
{
copie " Clic derecho: crea nuevo rectángulo. Arrastre con click izquierdo presionado" en ventana.text

ventana.manejador(sale "picture.Paint", sale "pintar")
ventana.manejador(sale "picture.MouseDown", sale "clic_en_boton_del_raton")
ventana.manejador(sale "picture.MouseMove", sale "movido_el_raton")
ventana.manejador(sale "picture.MouseUp", sale "soltado_el_boton_del_raton")
ventana.manejador(ventana.Closing, cerrando)
copie "no" en con_arrastre
el objeto lector es un System.IO.StreamReader(doy "Archivo con objetos.txt")
los objetos t1, t2, t3 son caracteres
mientras lector.Peek >0 haga:
{
copie lector.ReadLine en t1

copie lector.ReadLine en t2
copie lector.ReadLine en t3

copie t1.DemeCantidad en d1
copie t2.DemeCantidad en d2
copie t3.DemeCantidad en d3

el objeto hoy es una figura(doy d1, doy d2, doy d3)
grupo.Add(doy hoy)
}
lector.Close

copie grupo.Count en total
copie Graphics.FromImage(doy bitmap) en graficador
ventana.AgregarControl(Doy "picture")
el objeto tamaño es un System.Drawing.Size(doy 1024, doy 768)
copie tamaño en picture.Size
/*
EL OBJETO piopio es un "System.Diagnostics.Process"
piopio.Start(doy "Archivo con objetos.txt")
*/
}
}


Ejemplo: Cómo detectar evento ocurrido en otras ventanas dependientes ?

clase auxiliar derivada_de Form
publicos
mensajes
auxiliar(deme nombre es un caracter) copie ":) soy " # nombre en auxiliar.Text
/***********************************************************/

clase v derivada_de Form
publicos
el objeto otra es una auxiliar("Uno")
el objeto aquella es una auxiliar("Dos")
el objeto ésta es una auxiliar("Tres")

mensajes:
v
{
copie "Soy la ventana principal" en v.Text
otra.Show aquella.Show ésta.Show
v.Manejador(otra.MouseDown, avisar)
v.Manejador(aquella.MouseDownavisar)
v.Manejador(ésta.MouseDownavisar)
}

avisar(deme nc, deme ch es un MouseEventArgs)
{
copie "punto (" # ch.X # ", " # ch.Y # ") en la otra " # nc.ToString en v.Text
}


Ejemplo: Cómo desplazar continuamente un grupo de varias imágenes ?

clase Di derivada_de Form
 publicos:
    el objeto T es una Timer
    el objeto ima es un ArrayList
    los objetos x0, i, ancho son cantidades

 mensajes:
Di{
 Di.Manejador(T.Tick,  Avance)
 Di.Manejador(Di.Paint, Pinte)
 copie 0 en i, x0
 copie 50 en ancho

    /*Creo las imágenes para no usar ya existentes*/
      los objetos f1, f2, f3, f4, f5 son Bitmap(ancho, 100)
    los objetos g1, g2, g3, g4, g5 son Graphics no_crear
    copie g1.FromImage(f1) en g1
    copie g1.FromImage(f2) en g2
    copie g1.FromImage(f3) en g3
    copie g1.FromImage(f4) en g4
    copie g1.FromImage(f5) en g5

    g1.FillRectangle(Brushes.Red, 0, 0, 49, 99)
    ima.Add(f1)

    g2.DrawEllipse(Pens.Blue, 0, 0, 49, 99)
    ima.Add(f2)

    g3.FillEllipse(Brushes.Green, 0, 0, 49, 99)
    ima.Add(f3)

    g4.DrawRectangle(Pens.Black, 20, 20, 29, 29)
    ima.Add(f4)

    g5.DrawLine(Pens.Peru, 0, 0, 49, 99)
    ima.Add(f5)
T.Start
 }

Avance(deme cc, deme ch es un EventArgs)
{
es x0 > -ancho ?
    si: copie x0 - 1 en x0
    no: {ima.Add(ima[0])    ima.RemoveAt(0)    copie 0 en x0}

Di.Refresh
}

Pinte(deme cc, deme ch es un PaintEventArgs)
{
variando i desde 0 hasta ima.Count-1 haga:
    {
    el objeto imagen es un Bitmap(1, 1)
    copie ima[i] en imagen
    ch.Graphics.DrawImage(imagen, x0 + i*ancho, 50)
    }
}


Ejemplo: Cómo  hacer ZOOM a una colección de puntos ?

clase V derivada_de Form

Publicos
los objetos x, y, dx, dy son arraylist
los objetos punto, paso, Npasos, xc, yc, aux, i, xt, yt, dxt, dyt son cantidades
El objeto b es un Button

mensajes

V{
 V.manejador(v.Paint,        pinte)
 V.manejador(v.MouseDown,    raton)
 V.manejador(b.Click,        boton)
 v.AgregarControl(b)
 copie "ZOOM" en b.Text
 copie "Mouse (LEFT: nuevo punto; RIGTH: listo !)" en v.Text
 entre Npasos
 }

pinte(deme cc, deme ch es un paintEventArgs )
variando i desde 0 hasta x.count-1 haga:
 {
 copie X[i] en xt
 copie Y[i] en yt
 ch.graphics.drawEllipse(pens.black, xt, yt, 1, 1)
 }

raton(deme cc, deme ch es un MouseEventArgs )
{
es ch.Button=MouseButtons.left?
    si:    {
        x.Add(ch.X)
        y.Add(ch.Y)
        }
    no: v.calculeDeltas
v.Refresh
}

boton(deme cc, deme ch es un EventArgs )
{
v.recalcule
v.refresh
}

calculeDeltas
{
copie 0 en xc, yc
variando i desde 0 hasta x.Count-1 haga:
 {
 copie x[i] en xt
 copie xt + xc en xc
 copie y[i] en yt
 copie yt + yc en yc
 }
copie xc/x.count en xc
copie yc/y.count en yc
variando i desde 0 hasta x.Count-1 haga:
 {
 copie x[i] en xt
 copie y[i] en yt
 dx.add((xt - xc)/Npasos)
 dy.add((yt - yc)/Npasos)
 }
}

recalcule
variando i desde 0 hasta x.Count-1 haga:
 {
 copie x[i] en xt
 copie y[i] en yt

 copie dx[i] en dxt
 copie xt + dxt en aux
 x.removeAT(i)
 x.insert(i, aux)

/* copie dyt[i] en dyt No puede aplicar indice con [] a una expresión de tipo RIOSUR.Cantidad: dyt[i] !*/
 copie dy[i] en dyt
 copie yt + dyt en aux
 y.removeAT(i)
 y.insert(i, aux)
 }


Ejemplo: Cómo  simular que el usuario presionó una tecla ?

/*
Modificado de versión lx2:
http://ojarami.com/riosur.net/modules.php?name=Forums&file=viewtopic&p=1584#1584
http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys(VS.71).aspx
*/
clase SendKeys01 derivada_de Form
publicos:
mensajes:
teclado(deme ee, deme paquete es un KeyEventArgs)
{
muestre "Pulsada la tecla ", paquete.KeyCode,"\n...ó... me estás engañando ?"
}

raton(deme ee, deme paquete es un MouseEventArgs)
{
SendKeys.Send(doy "a")
}

SendKeys01
{
copie "1. Pulse una tecla...2. Haga un click" en SendKeys01.text

SendKeys01.manejador(doy SendKeys01.KeyDown, doy teclado)
SendKeys01.manejador(doy SendKeys01.MouseDown, doy raton)
}



Ejemplo: Cómo simular una colisión con ángulo de incidencia ?

clase dir derivada_de Form
publicos:
los objetos x, y, alfa, velocidad, radianes, límite son cantidades
el objeto t es un Timer
el objeto sentido es un caracter

mensajes:
avisado(deme ee, deme paquete es un EventArgs)
{
es sentido = "derecha"?
si: es x < límite ?
     si:    {
        copie x + velocidad*Math.Cos(radianes) en x
        copie y + velocidad*Math.Sin(radianes) en y
        }
     no:    {
        copie "izquierda" en sentido
        copie (180-alfa)*Math.PI/180 en radianes
copie radianes.DemeCaracteres en dir.Text
        }
no:     {
    copie x + velocidad*Math.Cos(radianes) en x
    copie y + velocidad*Math.Sin(radianes) en y
    }

dir.Refresh
}

pinte(deme ee, deme paquete es un PaintEventArgs)
{
paquete.Graphics.DrawEllipse(Pens.Red, x, y, 2, 2)
paquete.Graphics.DrawLine(Pens.Black, límite, 40, límite, 260)
}

dir
{
copie 55 en alfa
dir.manejador(dir.Paint, pinte)
dir.manejador(t.Tick, avisado)

copie 270 en límite
copie 200 en x
copie 40 en y
copie 5 en velocidad
copie alfa*Math.PI/180 en radianes
copie radianes.DemeCaracteres en dir.Text

copie 100 en t.Interval
t.Start
copie "derecha" en sentido
}


EjemploCómo maximizar una ventana ?   ?

clase v derivada_de Form
publicos
mensajes
v copie FormWindowState.Maximized en v.WindowState


Ejemplo: Cómo  sensar el teclado cuando un control tiene el foco de atención ?

clase v derivada_de Form
publicos
los objetos bot1, bot2 son Button

mensajes
t(deme nn, deme ch es un KeyEventArgs)
{
muestre "Tecla pulsada: ", ch.KeyCode
}

v{
copie " Tiene botones y....sí sensa teclas con el foco en algún botón. Use Tab para cambiar el foco" en v.Text
/*v.manejador(doy "v.KeyDown", doy "t") SOBRA*/

v.AgregarControl(bot1)
v.manejador(bt1.KeyDown, t)

el objeto tamaño es un Size(doy 40, doy 20)
el objeto posición es un Point(doy 100, doy 0)
copie tamaño en bot2.Size
copie posición en bot2.Location
v.AgregarControl(bot2)
v.manejador(bot2.KeyDown, t)
}


Ejemplo: Cómo usar la rueda del ratón ?

/*
http://msdn.microsoft.com/es-es/library/system.windows.forms.control.mousewheel(v=VS.80).aspx
http://msdn.microsoft.com/es-es/library/system.windows.forms.mouseeventargs.delta(v=VS.80).aspx
*/

clase v derivada_de Form
publicos
los objetos i, t son cantidades
mensajes
v{
es SystemInformation.MouseWheelPresent = verdadero ?
    si: muestre "SI tiene rueda el ratón"
    no: muestre "NO tiene rueda el ratón"

v.Manejador(v.MouseWheel, ratón)
copie 0 en i
}

ratón(deme NC, deme detalles es un MouseEventArgs)
{
copie i + 1 en i
copie detalles.Delta.ToString # " ==> " # i.DemeCaracteres en v.Text
}

Ejemplo: Cómo  hacer una clase ?

NNNN