Null World

Donde nada es lo que parece, especialmente los punteros
Cambiando de nombre a Window1

renamingFile

Uno de los primeros problemas con los que se encuentra un diseñador o programador de WPF es qué hacer con Window1. Como ventana principal de la aplicación, lo más común es que queramos darle otro nombre que deje clara su funcionalidad, pero no es tan sencillo. El primer paso es renombrar el fichero desde el Explorador de soluciones. Después tenemos que modificar el nombre del archivo en 3 sitios distintos:

  • Window1.xaml. Tendremos que modificar el x:Class, que hace referencia al nombre completo de la clase parcial donde se almacena el código de la ventana.
  • Window1.xaml.cs. Tanto el nombre de la clase como su constructor deben ser modificados.
  • App.xaml. Este es el punto que la mayoría de la gente olvida y que más problemas termina dando, puesto que no se nos ocurre pensar en las referencias a Window1 fuera de la propia clase. Además, el proyecto compilará perfectamente, pero nos dará una IOException diciendo que no puedo encontrar el recurso window1.xaml. La razón es que dentro de App.xaml especificamos la ventana principal de la aplicación con el atributo StartupUri que, si no lo modificamos, conservará el valor Window1.xaml.

Una vez modificados estos tres ficheros, nuestro proyecto funcionará perfectamente y no tendremos que volver a ver Window1 por ningún sitio.


Rock Tip. Dudo mucho que un grupo como AC/DC necesite introducción, menos aun después del impresionante concierto de este viernes en el Vicente Calderón, así que os dejaré con uno de sus grandes éxitos, You Shook Me All Night Long. Enjoy!!

Publicado 10/6/2009 10:54 por Francisco Martinez | 7 comment(s)

Archivado en:

Teclado en pantalla con WPF

ScreenKeyboardEn algunas de nuestras aplicaciones es posible que necesitemos controlar de forma muy fina la entrada de datos por parte del usuario, o que no dispongamos de un teclado físico. Con WPF podemos crear de forma sencilla un teclado en pantalla que se maneje con el ratón o de forma táctil. Lo primero de todo será crear nuestra aplicación WPF y añadirle un TextBox y varios botones.

La aplicación resultante la podéis ver aquí a la izquierda…os servirá para daros cuenta de que esto no va de diseño, sino de programación. Además al final del post hay un link para que podáis descargárosla y comprobar lo sencilla que es.

Es interesante utilizar un TextBox en lugar de otro control de texto como una Label o un TextBlock, puesto que así tendremos soporte para mostrarle al usuario la posición del cursor (caret) mientras edita el texto. Una vez hecho esto, necesitamos gestionar una serie de temas para que el teclado funcione correctamente. Lo primero de todo, manejaremos el click de los botones para añadir texto al TextBox:

private void KeyboardPanel_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)e.Source;
Text.AppendText(button.Content.ToString());
}

Una vez hecho esto, solo nos quedaría hacer que el campo de texto muestre la posición del cursor mientras se esta editando. Para ello, en el constructor de nuestra ventana añadiremos estas dos líneas después del InitializeComponent:

this.InitializeComponent();

Text.CaretIndex = 0;
Text.Focus();

La primera línea sitúa la posición del cursor en el 0, ya que de no hacerlo el TextBox no la gestionará correctamente. La segunda línea le da el foco de tal manera que muestre el cursor. Si probamos nuestra aplicación ahora veremos que aun nos queda un problema por resolver. Al hacer click en cualquiera de los botones para añadir texto, el TextBox perderá el foco, perdiendo así la funcionalidad del cursor. Para evitar esto hay varios métodos: hacer que los botones no puedan recibir el foco (Focusable=false), hacer que en cada click el TextBox recupere el foco…Lo que haremos será algo muy sencillo: evitar que el TextBox pierda el foco. Añadimos al constructor la siguiente linea:

Text.PreviewLostKeyboardFocus += new KeyboardFocusChangedEventHandler(Text_PreviewLostKeyboardFocus);

Manejando el evento PreviewLostKeyboardFocus podemos realizar las acciones que deseemos antes de que el control pierda el foco. Y lo que deseamos es…

void Text_PreviewLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
e.Handled = true;
}

Marcar el evento como manejado. Con algo tan simple como esto evitamos que el control pierda realmente el foco, y tenemos nuestro teclado listo para su uso.


Rock Tip. Poca gente hace canciones y videos tan divertidos como Electric Six. Lo mejor de todo es que además suenan realmente bien…y no tienen ninguna relación con el tema del post, para no perder la costumbre ;) Cierran hoy Electric Six con Danger! High Voltage. Enjoy!!!

Publicado 20/5/2009 10:32 por Francisco Martinez | 2 comment(s)

Archivado en:

Los secretos del casting al descubierto

Visto lo animada que estuvo la discusión en el anterior post sobre los diferentes casts en C#, no podía dejar pasar la oportunidad de explicar un poco en que consistía el acertijo. Como algunos comentabais en los comentarios, las dos operaciones, as y cast explicito, son distintas en funcionalidad y también internamente. Vamos a ver por qué:

concursante = (Concursante)o;

En esa línea, intentaremos convertir el objeto o a Concursante. Si podemos, devolveremos un objeto de tipo concursante, si no podemos lanzaremos una excepción.

concursante = o as Concursante;

En esta otra línea, comprobaremos primero si el objeto es convertible a Concursante. Si lo es, lo convertiremos y devolveremos, si no lo es devolveremos null. Internamente, el operador as se convierte en una instrucción de tipo isinst, mientras que el cast directo se convierte en una instrucción castclass. Pero dejémonos de teoría y vamos a lo que nos interesa. Con un sencillo programa podemos comprobar cual de los dos es más rápido. Por ejemplo, así:

Concursante concursante = null;
object o = new Concursante();

ArrayList array = new ArrayList();

Stopwatch watch = new Stopwatch();
Console.WriteLine("Begin casting");

for (int i = 0; i < 100; i++)
{
    watch.Start();

    for (int j = 0; j < 10000000; j++)
    {
        concursante = (Concursante)o;
        concursante.Nombre = "Rosa";
    }

    watch.Stop();

    array.Add(watch.ElapsedMilliseconds);
    watch.Reset();
}

float ms = 0;

for (int i = 0; i < array.Count; i++)
{
    ms += float.Parse(array[i].ToString());
}

ms = ms / array.Count;

Console.WriteLine("Median elapsed time: {0} ms", ms);

Si, el programa tiene un poco mas de miga, pero tiene su sentido. Hemos de recordar que un casting, de una forma u otra, es una operación con un coste muy, muy pequeño por si sola. Para poder medirla con un poco de precisión, realizaremos diez millones de casting cien veces, y calcularemos la media. Ejecutado en mi portátil mientras escribo esto, el resultado es de unos cuantos milisegundos (40, 50…) en cada uno de los casos. Recordemos que estamos hablando del tiempo de ejecución de 10.000.000 operaciones. Lo curioso es que al ejecutar el mismo código en modo release o en modo debug, con o sin optimizaciones, nos dará resultados distintos. Qué es lo que esta pasando?

Esa será la respuesta que dejaré sin responder, por una sencilla razón. Mi compañero Luis Guerrero me ha prometido realizar un interesantísimo post sobre este mismo tema, metiéndose hasta el fondo del asunto con WinDBG. Así pues, le paso el testigo ;)


Rock Tip. Ya he nombrado por aquí a los finlandeses Turisas, pero es justo que después de verles la semana pasada en directo por segunda vez, vuelva a recordarlos. Con vosotros, Battle Metal. Enjoy!!

Publicado 13/5/2009 16:51 por Francisco Martinez | con no comments

Archivado en: ,

Los secretos del casting

Y no estamos hablando de los castings de Operación Triunfo o Gran Hermano, no. Os propongo pasar la tarde de hoy pensando en una de esas cosas que no dejan de ser interesantes pese a servir para bastante poco ;)

Seguro que todos los días mientras programáis os encontráis con situaciones en las que tenéis que convertir objetos de un tipo a otro, lo que se conoce como un casting (que no tiene nada que ver con concursos, por suerte). En C# las dos formas más comunes de realizarlo son con un cast explicito o utilizando el operador as:

object o = new Concursante();
Concursante concursante;

concursante = (Concursante)o; //Explicito
concursante = o as Concursante; //Operador as

Visto esto ya no haré ningún comentario, y me limitare a lanzar mi pregunta. Basaros simplemente en lo que sabéis de ambas operaciones y en vuestra intuición vale? La pregunta es…cual de las dos formas de realizar un cast es más rápida?

La respuesta, en breve, en esta misma cadena…o no ;)


Rock Tip. Visto que todo lo que hemos tenido por el momento en estos rock tips ha sido música en inglés creo que por una vez, aprovechando el cambio de temática del post, podríamos buscar otro idioma…como el alemán. Hoy cierra el post Rammstein con una de sus mejores canciones (IMHO) acompañada de un gran videoclip: Ich Will. Enjoy!!

Publicado 29/4/2009 12:09 por Francisco Martinez | 9 comment(s)

Archivado en: ,

Un sencillo menú en WPF: Recursos (II)

Dado que en el post anterior hablábamos sobre estilos y plantillas, vamos a ver un poco mas en detalle ahora como podemos estructurarlos y acceder a ellos de la mejor manera posible. En el proyecto (adjunto en la primera parte) vemos que en la ruta /Themes/Default.xaml encontramos un diccionario de recursos.

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d">
    <!-- Resource dictionary entries should be defined here. -->
    <Style x:Key="ButtonFocusVisual">
        ...
    </Style>
    <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
        ...
    </LinearGradientBrush>
    <SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
    <Style x:Key="MenuButtonStyle" TargetType="{x:Type Button}">
        ...
    </Style>
</ResourceDictionary>

Como podemos ver, este diccionario de recursos contiene estilos, plantillas, brochas y demás recursos que utilizaremos a lo largo de toda nuestra aplicación. Es imprescindible que todos ellos tengan un atributo x:Key para poder ser referenciados desde nuestros elementos de interfaz. Para ello, primero necesitamos agregar a nuestro App.xaml una referencia al diccionario (o diccionarios) de recursos que queramos emplear.

<Application.Resources>
    <!-- Resources scoped at the Application level should be defined here. -->
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Themes\Default.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

Una vez hecho esto, solo necesitamos aplicar el recurso deseado mediante la extensión de marcado DynamicResource en la propiedad que nosotros elijamos:

<StackPanel x:Name="LayoutRoot" Width="600" Height="66">
    <StackPanel x:Name="ButtonStack" Width="Auto" Orientation="Horizontal" HorizontalAlignment="Right" Height="26" ButtonBase.Click="ButtonStack_Click">
        <Button Content="Home" x:Name="HomeButton" Width="70" Style="{DynamicResource MenuButtonStyle}" Height="24" MouseEnter="ButtonStack_MouseEnter"/>
        ...
    </StackPanel>

No es necesario que especifiquemos un path al recurso, como haríamos con un binding al uso, dado que automáticamente se buscará el recurso en los diccionarios de recursos cargados en ese momento cuando sea necesario mostrarlo. Esa es la diferencia entre DynamicResource y su hermana StaticResource: mientras que DynamicResource cargará el recurso en el momento en que se muestra el elemento que lo referencia, StaticResource realiza esa asignación en el momento en el que se carga XAML. Esto podemos aprovecharlo para cargar y modificar recursos en tiempo de ejecución, como veremos en un próximo post.

Otro punto interesante en este sencillo ejemplo de un menú es el acceso a recursos dentro de la plantilla aplicada a un elemento. En nuestro caso, la plantilla que aplicamos a nuestros botones define una Storyboard que queremos utilizar. La manera de hacerlo es la siguiente:

private void DoButtonMouseOver(Button origin)
{
    Storyboard mouseOver = (Storyboard)origin.Template.Resources["MouseOver"];
    mouseOver.Begin(origin, origin.Template);
}

Como vemos, necesitamos una referencia al objeto Button para acceder a los recursos de su plantilla y buscar la Storyboard que nos interesa, para después llamar a su método Begin. La particularidad aquí es que no es suficiente con pasarle como argumento el botón, puesto que la animación trabaja con objetos de la plantilla y no es capaz de encontrarlos, saludándonos con una bonita InvalidOperationException. Para ello existe una sobrecarga del método Begin que recibe tanto el elemento sobre el que se inicia la animación como la plantilla que la contiene.


Rock Tip. Siguiendo mi rutina habitual de añadir canciones sin ninguna relación con lo relatado, os presento hoy uno de los grupos que mejor capturan la esencia del Shock Rock abanderado por KISS, el conjunto liderado por Blackie Lawless W.A.S.P., con su canción (de genial videoclip) Wild Child. Enjoy!!

Publicado 22/4/2009 10:27 por Francisco Martinez | 1 comment(s)

Archivado en:

La nueva MSDN

O “Como obtener mas visitas en un blog gracias a un título levemente amarillista”. El caso es que no podemos hablar de una nueva MSDN, pero si de una nueva manera de acceder a su información de forma más sencilla y accesible. Microsoft mantiene diversas versiones de la MSDN para distintos soportes: dispositivos móviles, pantalla, impresión, etc. De un tiempo a esta parte se ha sumado una nueva versión “Low Bandwidth” creada para consumir menos ancho de banda. Para ello han eliminado gran cantidad de elementos pero intentando siempre mantener la información inalterable. El resultado? Una web mucho mas ligera y sencilla de consultar, como podéis comprobar vosotros mismos:

System.Object en la MSDN

System.Object en la MSDN Low Bandwidth

Para acceder a los artículos de MSDN de está forma solo tenéis que añadir a la URL la opción (loband) como en el segundo enlace, y además tendréis una opción en la esquina superior derecha de vuestras pantallas para establecerlo como modo por defecto.


Rock Tip. Danger Danger es un grupo de hard rock que por desgracia llego demasiado tarde, en esa triste época en la que aparecieron Nirvana y el grunge para acabar con todo lo bueno. Pese a todo, un grupo con un gran vocalista, un excelente guitarra y melodías muy pegadizas no puede quedar en el olvido (aunque de eso ya se encarga mi compañero Pablo Doval), así que rescatare para este post su clásico Rock America, que aunque suena bien en directo, suena mejor en un Corvette rojo descapotado…Enjoy!

Publicado 16/4/2009 12:05 por Francisco Martinez | 3 comment(s)

Archivado en: ,

Un sencillo menú en WPF: Estilos y Plantillas (I)

En el post anterior sobre la creación de un Motion Path desde Visual Studio, Julio Trujillo comentaba sobre la posibilidad de aplicar lo aprendido para la creación de un menú similar al de Silverlight.net. Lo que haremos será, en lugar de limitarnos a crear el menú, aprovecharlo para aprender alguna cosa nueva, en este caso, algo sobre estilos y plantillas.

Lo primero de todo es saber lo que es cada cosa. Un estilo (Style) no es mas que un conjunto de objetos de tipo Setter, pares de propiedad y valor, aplicados a los objetos de un tipo concreto. Es decir, un estilo nos permite definir un recurso compartido para mantener la coherencia de nuestra interfaz de usuario, abarcando tanto el aspecto visual (recursos, propiedades) como el comportamiento (triggers) de las instancias de un tipo concreto. Veámoslo con un ejemplo de nuestro proyecto.

    <Style x:Key="MenuButtonStyle" TargetType="{x:Type Button}">

<
Setter Property="HorizontalContentAlignment" Value="Center"/>
<
Setter Property="VerticalContentAlignment" Value="Center"/>
<
Setter Property="Padding" Value="1"/>
<
Setter Property="Template">
<
Setter.Value>
<
ControlTemplate TargetType="{x:Type Button}">
<
ControlTemplate.Resources>
<
Storyboard x:Key="MouseOver">…</Storyboard>
<
Storyboard x:Key="UnMouseOver">…</Storyboard>
<
Storyboard x:Key="Click">…</Storyboard>
<
Storyboard x:Key="UnClick">…</Storyboard>
</
ControlTemplate.Resources>
<
Grid x:Name="LayoutRoot">…</Grid>
</
ControlTemplate>
</
Setter.Value>
</
Setter>
</
Style>

Ahí podemos ver el estilo de los botones de nuestro menú (levemente editado para que no nos ocupe media página). Como vemos, le asignamos al estilo una clave (imprescindible para almacenarlo en un diccionario de recursos, como veremos después) y un tipo de destino, de manera que el estilo se aplicará automágicamente a todos los objetos de tipo Button. Además, establecemos las propiedades que queremos que compartan (alineación y padding entre otras) y la propiedad más interesante de todas: la plantilla (Template). Las plantillas controlan la estructura visual y el comportamiento de los controles en WPF, y son la clave de su flexibilidad a la hora de modificar el aspecto de nuestra aplicación. Si nos fijamos en el código anterior, dentro de la plantilla definimos una serie de recursos (storyboard) para su uso dentro de la misma, y le añadimos un Grid, con un contenido. En nuestro caso es el siguiente:

<Grid x:Name="LayoutRoot">
<
Rectangle Opacity="0" x:Name="MassiveGlow" StrokeThickness="0">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#00FFFFFF" Offset="0"/>
<
GradientStop Color="#BEFFFFFF" Offset="0.74"/>
<
GradientStop Color="#00FFFFFF" Offset="1"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
<
Rectangle Opacity="0" x:Name="Glow" StrokeThickness="0">
<
Rectangle.Fill>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#00FFFFFF" Offset="0"/>
<
GradientStop Color="#7FFFFFFF" Offset="0.74"/>
<
GradientStop Color="#00FFFFFF" Offset="1"/>
</
LinearGradientBrush>
</
Rectangle.Fill>
</
Rectangle>
<
Rectangle Opacity="0.795" HorizontalAlignment="Left" x:Name="LeftSeparator"
Width="1" Fill="#FFFFFFFF" Stroke="#FFFFFFFF" StrokeThickness="1"/>
<
Rectangle Opacity="0.795" HorizontalAlignment="Right" x:Name="RightSeparator"
Width="1" Fill="#FFFFFFFF" Stroke="#FFFFFFFF"/>
<
TextBlock HorizontalAlignment="Center" x:Name="NameTextBlockShadow"
VerticalAlignment="Center" FontSize="14" Foreground="#FF000000"
TextWrapping="Wrap" d:LayoutOverrides="Height"
Text="{TemplateBinding Content}" Margin="2,2,0,0"/>
<
TextBlock HorizontalAlignment="Center" x:Name="NameTextBlock"
VerticalAlignment="Center" FontSize="14" Foreground="#FFFFFFFF"
Text="{TemplateBinding Content}" TextWrapping="Wrap"/>
</
Grid>

Como podemos ver, dentro de ese Grid estamos redefiniendo por completo el aspecto visual de nuestro botón. Creamos dos rectángulos con un brillo para hacer efectos cuando el botón sea seleccionado, otros dos rectángulos como separadores laterales, y dos bloques de texto para el contenido del botón. Ya hemos visto como cambiar el aspecto visual de un elemento editando su estilo y su plantilla, y en el próximo post veremos como trabajar cómodamente con los recursos de nuestra aplicación.

 


 

Rock Tip. Aunque es muy común que un grupo musical realice versiones de otros temas adaptándolos con mayor o menor acierto a su estilo, no es tan común que un grupo metal, como los impactantes Turisas, se dedique a versionar a un grupo disco, como Boney M. Sin embargo, como de cambio de estilos precisamente estamos hablando, me parece mas que interesante resaltar este Rasputin. Enjoy!

Publicado 15/4/2009 10:53 por Francisco Martinez | 7 comment(s)

Archivado en:

Creando un Motion Path desde Visual Studio

En el post anterior vimos como crear un Motion Path desde Blend, y en este vamos a hacer lo mismo pero desde Visual Studio 2008, a base de código C#, como verdaderos programadores que somos. Comenzaremos creando un rectángulo idéntico al del ejemplo anterior.

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MotionPathVS.Window1"
x:Name="Window"
Title="Window1"
Width="640" Height="480">
<
Grid x:Name="LayoutRoot">
<
Rectangle HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="100"
Fill="#FFF50000" Stroke="#FF000000" x:Name="rect"/>
</
Grid>
</
Window>

Como vemos aquí, no necesitamos para nada el Path, que en nuestro primer ejemplo nos servía para establecer la ruta que seguiría el rectángulo. Y este será el único código XAML que veremos en este post, ya que toda la animación la construiremos, paso a paso, desde Visual Studio en C#. Así que empecemos. Lo primero que necesitamos es, valga la redundancia, crear la animación. Para ello crearemos un Storyboard al que añadiremos dos animaciones, una para desplazar el objeto por el eje X, otra para el eje Y.

Storyboard motion = new Storyboard();

DoubleAnimationUsingPath x = new DoubleAnimationUsingPath();
DoubleAnimationUsingPath y = new DoubleAnimationUsingPath();

motion.Children.Add(x);
motion.Children.Add(y);

Está animación tendrá que trabajar sobre la TranslateTransform del objeto que queremos desplazar, en este caso rect. Pero si nos fijamos en el código XAML, esa TranslateTransform no parece por ningún sitio, así que tendremos que crearla, asignársela a rect como RenderTransform y registrarla para que pueda ser utilizada por nuestra animación.

TranslateTransform translate = new TranslateTransform(0,200);
this.RegisterName("Translate", translate);
rect.RenderTransform = translate;

El próximo paso es construir el path que queremos que recorra nuestra animación. En este caso utilizaremos una Curva de Bézier, partiendo del punto (0, 200), finalizando en (500, 300) y con el punto de control en (150, 0). Esto generará de forma bastante sencilla una curva sobre la que desplazaremos el objeto entre los dos puntos.

PathGeometry geometry = new PathGeometry();
PathFigure figure = new PathFigure();
figure.StartPoint = new Point(0,200);
figure.Segments.Add(new QuadraticBezierSegment(new Point(150, 0), new Point(500, 300), false));
geometry.Figures.Add(figure);

Con esto tenemos los elementos básicos que necesitamos: la animación, la ruta y el objeto. Lo único que nos queda es relacionarlos entre sí. Utilizamos los métodos estáticos de la clase Storyboard para establecer en cada una de las animaciones el objeto y la propiedad del mismo con la que trabajaran. Con SetTargetName indicamos que ambas animaciones trabajaran sobre la transformación que registramos antes, y con SetTargetProperty hacemos que cada una de ellas trabaje con el eje correspondiente.

Storyboard.SetTargetName(x, "Translate");
Storyboard.SetTargetProperty(x, new PropertyPath(TranslateTransform.XProperty));
Storyboard.SetTargetName(y, "Translate");
Storyboard.SetTargetProperty(y, new PropertyPath(TranslateTransform.YProperty));

Después, añadimos a cada una de las animaciones el path que creamos anteriormente, y les indicamos que tendrán que utilizar como fuente el eje que les toque.

x.PathGeometry = geometry;
y.PathGeometry = geometry;

x.Source = PathAnimationSource.X;
y.Source = PathAnimationSource.Y;

Por último, añadimos una serie de atributos, más o menos esenciales, para dar forma a nuestra animación. Establecemos la duración de la misma en un segundo, hacemos que se repita indefinidamente para poder observar el efecto, y establecemos un ratio de deceleración de 0’3. Esto sirve para indicarle a la animación que el primer 70% del tiempo debe mantener una velocidad constante, y el 30% final debe decelerar, dándole un aspecto más real.

y.Duration = TimeSpan.FromMilliseconds(1000);
x.Duration = TimeSpan.FromMilliseconds(1000);

y.DecelerationRatio = 0.3;
x.DecelerationRatio = 0.3;

motion.RepeatBehavior = RepeatBehavior.Forever;

Con esto tenemos ya nuestra animación lista (podéis verla en el proyecto adjunto), y con el mismo método podemos crear todo tipo de animaciones para aplicar a nuestros objetos, sin necesidad de depender de Blend para nada.


Rock Tip. Ya que en el anterior hablábamos de Heavy Metal clásico, que mejor que traer hoy a los que son a juicio de muchos los más grandes del género, Manowar. Desde luego, tienen el honor de ser los que más ruido hacen encima de un escenario. De su último disco, Gods of War, llega este King of Kings para cerrar este post. Enjoy!

Publicado 1/4/2009 10:34 por Francisco Martinez | 2 comment(s)

Archivado en:

Creando un Motion Path desde Blend

Reconozcámoslo. No tengamos miedo. Sabemos que es algo para lo que no estamos preparados, pero es así: a veces tendremos que hacer trabajo de diseñadores. No hay mas que hablar, llegara un momento en el que tendremos que remangarnos y abrir Expression Blend, y no queda bien que un programador hecho y derecho se ponga a llorar como un bebe al verlo. Paletas de colores, elementos visuales...yuyu mayúsculo. Hoy haremos algo tremendamente sencillo, tanto que casi nos dará vergüenza al verlo.

Utilizaremos la opción “Convert to Motion Path” para crear una asociación entre un UIElement y un Path, de tal manera que el primero se desplace de forma automágica siguiendo la ruta marcada por el segundo. Empezamos creando un horrible rectángulo rojo, que llamaremos rect, y un sencillo path que sigue una línea recta.

canvas

Despues, seleccionamos el path y elegimos en el menú de Blend la opción Object –> Path –> Convert to Motion Path.

 menu

Fácil, sencillo y para toda la familia. Vamos a echarle un ojo al XAML que genera, a ver si vemos algo interesante.

<Storyboard x:Key="MotionPath">
<
DoubleAnimationUsingPath BeginTime="00:00:00" Duration="00:00:02" Storyboard.TargetName="rect"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Source="X">
<
DoubleAnimationUsingPath.PathGeometry>
<
PathGeometry Figures="M25.5,166.5 L171,40 361,181 499,166.5"/>
</
DoubleAnimationUsingPath.PathGeometry>
</
DoubleAnimationUsingPath>
<
DoubleAnimationUsingPath BeginTime="00:00:00" Duration="00:00:02" Storyboard.TargetName="rect"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)"
Source="Y">
<
DoubleAnimationUsingPath.PathGeometry>
<
PathGeometry Figures="M25.5,166.5 L171,40 361,181 499,166.5"/>
</
DoubleAnimationUsingPath.PathGeometry>
</
DoubleAnimationUsingPath>
</
Storyboard>

Como vemos, la opción Convert to Motion Path nos crea automágicamente un Storyboard, con una duración de dos segundos, y dos DoubleAnimationUsingPath, que actuaran respectivamente sobre TranslateTransform.X y TranslateTransform.Y del objeto rect (el rectángulo rojo que queremos desplazar). Lo más interesante es que una vez creado el Storyboard, el Path que seleccionamos para crearlo se copia en ambas animaciones, y ya no es necesario que lo mantengamos en el árbol visual. Esto también conlleva que, si queremos modificar la ruta que seguirá nuestro elemento, tendremos que modificar la animación, no el path original. Para ello no tenemos mas que abrir la animación y seleccionar el elemento animado.

animation

 

 

 

Vemos como tenemos una animación de traslación, que podemos extender en el tiempo si queremos, y como tenemos también una línea punteada que nos indica el path que se esta siguiendo actualmente. Si quisiéramos modificarlo, sería tan sencillo como utilizar la herramienta Pen y añadirle un par de nodos, para posteriormente desplazarlos con la herramienta de selección directa.

animation2

Y con esto, ya hemos aprendido a hacer…una tontería. Tontería que, sin embargo, os servirá a vosotros para construir de manera sencilla animaciones mucho mas complejas, y a mí para poder hacer otro post explicando como hacer lo mismo desde Visual Studio 2008, con mucho mas texto, muchas menos imágenes y mucha mas diversión ;)


Rock Tip. Mis compañeros Pablo Álvarez y Octavio Hernández tienen la buena costumbre de cerrar sus (magníficos) posts con un (no menos magnífico) Rock Tip, recomendando grandes temas a menudo olvidados. Como yo no puedo ser menos, aquí va el de hoy. No nos vamos a remontar muy atrás en el tiempo, con un disco de este mismo año, aunque parezca salido de los 80…heavy metal clásico, venido de Polonia, y cantado por una mujer, Doro style. Crystal Viper, con su “The Anvil of Hate” cierran el post de hoy. Enjoy!

Publicado 25/3/2009 22:43 por Francisco Martinez | 3 comment(s)

Archivado en: ,

Search Connectors en Windows 7

Una de las nuevas características de Windows 7 es el soporte a la denominada Federated Search que nos permite, por ejemplo, agregar proveedores de busqueda a Windows Explorer para realizar consultas sobre sitios web (Search Connectors). Gracias a esta característica, podemos integrar en Windows Explorer nuestras busquedas en servicios tan diversos como Google, flickr, Wikipedia, etc. sin falta de abrir una ventana de nuestro navegador web. Es más, una vez realizada la busqueda podemos no solo consultar los resultados, sino abrirlos, imprimirlos y demas operaciones básicas. Podríamos, por ejemplo, buscar "Las Meninas" en la página web de la Wikipedia e imprimir el resultado sin falta de abrir nuestro navegador en ningún momento!

Microsoft ha publicado una guia para implementar Search Connectors, eso si, en ingles, que nos ayudara a crear los nuestros sin mucha dificultad, ya que en el fondo no son mas que un archivo xml de pocas lineas. Para que veais lo sencillo que es, he creado uno para realizar busquedas aqui, en geeks.ms. Si lo descomprimis y abris el archivo .osdx con cualquier editor de texto os dareis cuenta de lo sencillo que es ;)

Y recordad, esto solo funciona en Windows 7! Enjoy!

Publicado 18/3/2009 17:03 por Francisco Martinez | 1 comment(s)

Archivado en:

Drag and drop en WPF (I)

Un requisito relativamente común en las aplicaciones actuales es la posibilidad de realizar un drag and drop (arrastrar y soltar) entre elementos. Nos permite representar fácilmente dos situaciones de la vida real, como son el desplazamiento de objetos (en el caso de arrastrar un elemento y soltarlo en su nueva posición) y el establecimiento de una relación entre objetos (en el caso de arrastrar un elemento y soltarlo sobre el elemento al que queremos enlazarlo).

Trabajando en WPF tenemos disponible un método muy útil como es UIElement.CaptureMouse. Mediante este método podemos hacer que cualquier UIElement se haga con el control exclusivo del ratón, y cualquier evento generado por el ratón en otro elemento será ignorado. Esto nos permite gestionar funcionalidad como el drag and drop sin interferir en otros elementos de la interfaz. Veamos un ejemplo de cómo gestionar el desplazamiento de un elemento sobre un canvas:

Primero escribimos un manejador para el evento de MouseLeftButtonDown del elemento que queremos arrastrar (en este caso una elipse):

        private void Ellipse_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

        {

            Ellipse ellipse = sender as Ellipse;

 

            if (ellipse != null)

            {

                ellipse.CaptureMouse();

            }

        }

En este manejador nos limitamos a capturar el ratón cuando el usuario hace click sobre nuestra elipse. Posteriormente, escribimos un manejador para el evento MouseLeftButtonUp, que hará el proceso inverso, es decir, liberar el ratón:

        private void Ellipse_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)

        {

            Ellipse ellipse = sender as Ellipse;

 

            if (ellipse != null)

            {

                ellipse.ReleaseMouseCapture();

            }

        }

Ahora la única tarea que nos queda es gestionar el movimiento de la elipse cuando movamos el ratón. Dado que tenemos capturados los eventos del ratón, únicamente tenemos que preocuparnos de mover la elipse cuando este se mueva, para lo que aprovechamos el evento MouseMove:

        private void Ellipse_MouseMove(object sender, MouseEventArgs e)

        {

            Ellipse ellipse = sender as Ellipse;

 

            if (ellipse != null && ellipse.IsMouseCaptured)

            {

                Canvas.SetLeft(ellipse, e.GetPosition(MovementCanvas).X);

                Canvas.SetTop(ellipse, e.GetPosition(MovementCanvas).Y);

            }

        }

Con este código tan sencillo hemos conseguido desplazar una elipse mediante una operación de drag and drop. Pese a que faltan multitud de comprobaciones para que el código sea optimo (la elipse puede salirse de los bordes del canvas, por ejemplo), sí que nos sirve para ilustrar nuestro primer ejemplo de drag and drop. En la segunda parte de este artículo, veremos cómo realizar un drag and drop que establezca una relación entre dos objetos.

Descarga el código completo


 

Publicado 12/5/2008 12:53 por Francisco Martinez | 4 comment(s)

Archivado en:

Dreamland / AJAX y la accesibilidad web. Tips & tricks

En el anterior post os comentaba los principales problemas que tiene AJAX a la hora de desarrollar aplicaciones accesibles. Ahora vamos a ver un par de pequeños consejos que, si bien no resuelven estos problemas en su totalidad, al menos disminuyen su impacto.

Deciamos que el primer problema era la dependencia que tienen las aplicaciones AJAX de JavaScript, y como este no se lleva bien con los lectores de pantalla. Pues bien, el primer consejo no podria ser mas simple: hacer que nuestras paginas sean capaces de funcionar con JavaScript deshabilitado. Tan simple (y tan complejo) como eso. Si somos capaces de ofrecer a nuestros usuarios la experiencia mejorada de AJAX solo si ellos la reclaman, cualquier persona podra elegir la manera que prefiera para acceder a nuestra aplicacion. Evidentemente, esto conlleva un trabajo extra para el desarrollador, y muchas veces se piensa que nadie estara interesado en ver una version "antigua" de nuestra web. pero...y si la version anterior es la unica que pueden utilizar?

Otro problema que teniamos era el hecho de que los lectores de pantalla no se dan por aludidos ante una actualizacion parcial de la pagina. De hecho, este problema no es exclusivo de los lectores de pantalla, sino que muchisimas personas no se dan cuenta de estos cambios al ser sumamente pequeños en ocasiones. Para esto, de nuevo, la mejor solucion es informar al usuario, Por una parte, deberiamos comunicarle que la informacion de la pagina se actualizara de forma dinamica, y tambien deberiamos darle la opcion de recibir una alerta (algo tan simple como un popup es mas que suficiente) cuando se produzca esta actualizacion. Y por otra parte esta la denominada "Yellow Fade Technique", popularizada por los chicos de 37signals, que no es mas que aplicar algun efecto a la zona modificada de manera que esta "resalte", y sea mucho mas sencillo para el usuario darse cuenta de las modificaciones.

En fin, no son mas que un par de consejos que nos permitiran, con mas o menos esfuerzo, seguir desarrollando con AJAX, pero teniendo en cuenta la accesibilidad. Pronto os colgare algun ejemplo practico de como llevar esto a cabo.
 

Publicado 16/1/2007 11:28 por Francisco Martinez | 2 comment(s)

Archivado en: ,,

Chainsaw Buffet / AJAX y la accesibilidad web

Actualmente estamos viviendo el auge de la llamada "web 2.0", que se nos vende como una web mucho mas rica en contenidos, mas dinamica, y basada en aplicaciones web mas que en webs tradicionales. AJAX no es mas que una parte (importante, eso si) en todo este lio de tecnologias que engloba la "web 2.0", y es simplemente un conjunto de estandares (JavaScript, XML, HTML, CSS...). AJAX es a dia de hoy muy popular entre los desarrolladores, y Microsoft, evidentemente, no lo ignora y lanza su propia vision del asunto, a la que llama ASP.NET/AJAX, y que nos permite añadir a nuestras aplicaciones ASP.NET "de toda la vida" el dinamismo de AJAX sin necesidad de mancharnos las manos con sucio JavaScript (al cual no fui el unico en dar por muerto, verdad Salgado?). La pregunta es, hasta que punto este dinamismo, sin cuestionar ya su utilidad, llega a todo el mundo? O preguntando de forma mas tecnica...es AJAX accesible?

La respuesta es no...por el momento. Y las razones son bien sencillas, y no son mas que la absoluta dependencia que tiene AJAX de JavaScript y el refresco parcial de las paginas, y la mala relacion que tienen ambas cosas con los lectores de pantalla. La mayoria de los discapacitados que necesitan ayuda para acceder a la web utilizan un lector de pantalla, que se limita a leer lo que el navegador esta mostrando en pantalla. De ahi la insistencia en el uso de texto alternativo en las imagenes, al ser uno de los elementos que un lector de pantalla no puede interpretar. Vamos a ver un poco en detalle en que consisten estos dos problemas:

  • Dependencia de JavaScript. Browsers como Lynx o Links, no soportan JavaScript. Muchos lectores de pantalla (por suerte, cada vez menos), funcionan sobre Lynx. Y aunque funcionen sobre un browser que si soporte JavaScript, no lo interpretan, sino que intentan extraer algo con el suficiente sentido como para ser leido a un usuario, lo cual no es facil. Cuanto menos JavaScript haya en una web, mas sencillo sera leerla con un lector de pantalla, y AJAX tiende a aumentar cada vez mas el uso de JavaScript.
  • El refresco parcial de las paginas. Los lectores de pantalla, simplemente, no saben cuando una pagina ha sido actualizada "parcialmente". Para ellos, o se produce una actualizacion (y entonces leeran de nuevo la pantalla al usuario), o no se produce (y entonces no haran nada). Esto supone que una de las principales ventajas de AJAX (si no la mayor) sea no solo inutil, sino contraproducente.

En resumen, AJAX no se lleva bien con la accesibilidad web. Podemos solucionarlo? Pues parcialmente si, y lo veremos en un proximo post ;)

Publicado 15/1/2007 10:47 por Francisco Martinez | 3 comment(s)

Archivado en: ,,

I Don't Feel Like Dancin' / Networking con Virtual PC

Aunque no lo parezca, conseguir tener en un mismo PC mas de uno y de dos Sistemas Operativos no es en absoluto dificil. Basta instalarte cualquier software de gestion de maquinas virtuales (VMWare o Virtual PC, por ejemplo), y puedes disponer, ademas de lo que hayas instalado en la maquina host (la unica maquina fisicamente visible, el cacharraco de encima de la mesa), un 2003 Server y un Windows XP donde instalar todas las betas, alphas y RC's que quieras sin miedo a cargarte nada.

La cosa se pone un poco mas peliaguda cuando lo que queremos es que esa maquina se conecte a internet, ya sea para descargar actualizaciones o ficheros de video de los servidores mas concurridos de la red...Aqui os muestro la manera mas sencilla que he encontrado yo para conseguirlo, y es hacer que la maquina virtual salga a internet compartiendo la conexion del host mediante el Microsoft Loopback Adapter. Partiendo de una maquina host con Windows Vista, y una maquina virtual con el sistema operativo X, en Virtual PC...

  • Nos vamos al Control Panel
  • Pulsamos sobre "Add Hardware"
  • Elegimos la opcion "Advanced", que nos permitira seleccionar el hardware en una lista
  • Nos vamos a "Network adapters", y elegimos como fabricante Microsoft, y como producto el Microsoft Loopback Adapter

Con esto ya tenemos hecha la primera parte del asunto, y es tener montado el Loopback. Ahora lo que necesitamos es decir que vamos a compartir nuestra conexion de red con otros equipos a traves de el. Para esto, hacemos lo siguiente...

  • Nos vamos al Network and Sharing Center
  • Pulsamos sobre la opcion "View Status" de nuestra conexion de Internet, NO SOBRE LA CONEXION DE LOOPBACK,  y pulsamos sobre "Properties"
  • Seleccionamos la pestaña "Sharing"
  • Marcamos la opcion de "Allow other network users to connect through...", y en el desplegable seleccionamos Loopback

Y con esto ya tenemos la segunda parte, que es compartir nuestra conexion de internet a traves del Loopback. Acabar con el asunto es tan sencillo como arrancar Virtual PC y decirle en las propiedades de la maquina virtual que utilice como adaptador de red primario el Microsoft Loopback Adapter. Y listo para la conexion :)

Espero que os sea util
 

Publicado 12/1/2007 16:06 por Francisco Martinez | 4 comment(s)

Archivado en:

Copycat / He sido taggeado

Pues eso, que se supone que ahora deberia contar cinco cosas de mi que sepa poca o muy poca gente. O nadie. Y como parece que hay interes, porque no me han taggeado ni uno ni dos (sino tres, Ethel, Jorge y Doval), pues alla van. Luego no os quejeis :P

  1. Me chiflan los RPG's. Ya sea en un PC, con dados, con cartas, o con muñecajos, tengo un vicio que no me aguanto. Juego a Warhammer 40K desde hace unos 8 años, he coleccionado cartas de Magic (Mentira, no eran de Magic, eran de Pokemon!! Da lo mismo, a callar!!!), he estado un año y medio enganchado a Ultima Online y ahora juego al WoW, he jugado a n RPG's en un PC y he disfrutado de muchisimos juegos de rol "clasico",con sus dados y sus fichas de personaje. Mucho mucho vicio, mucho mucho dinero y, eso si, mucha mucha diversion.
  2. Durante 4 años hice Judo, hasta que me cambie de colegio. Llegue a ser cinturon naranja-verde, si no me equivoco. Hace ya bastante tiempo de eso :P Despues estuve un par de años practicando Tenis de Mesa, y ahora me (nos, verdad Doval) ha dado por la Esgrima. A ver lo que sale. Eso si, siempre he jugado al futbol de manera irregular, y siempre me han gustado deportes como el Kick-Boxing, o el Muay-Thai, pero mi fragilidiad fisica no me ayuda a animarme :P
  3. Leo regularmente (vease a diario) un buen puñado de webcomics que, curiosamente, poca gente encuentra divertidos. Asi que me ahorrare el poner los links y tener que escuchar por n-esima vez eso de: "No le veo la gracia..."
  4. Aunque pueda parecer lo contrario, de niño nunca me llamaron los ordenadores ni la informatica. Es decir, no mas alla de "Papa monta el Spectrum", o "Papa dejame jugar al Atic Atac". Sin embargo, si que me gustaba jugar con muñecas, y en el colegio en vez de jugar al futbol en el recreo me dedicaba a jugar con niñas y Barbies. Dios, esto empieza a ser humillante...
  5. Me encanta el dulce. Gominolas, chocolate, bombones...todo menos pasteles y tartas. Eso no :( Y aunque no lo parezca dado mi esbelto fisico, como MUCHO. Preguntad si no os fiais :P
Y ya esta, 5 cosas contadas. Ahora a ver lo que vais a acabar pensando de mi. Y como ya hay mucha gente taggeada que aun no ha respondido, se lo recuerdo yo. Cachero, Ricardo, Fran, Llopis y los compañeros de Plain que aun no se han animado...tardando estais :)

 

Publicado 5/1/2007 16:39 por Francisco Martinez | 4 comment(s)

Archivado en:

Wake the Snake / WPF y su UX

Ahhh, WPF...el Santo Grial de la programacion de interfaces de usuario, el nuevo paradigma de la presentacion grafica, el summum de los colores el pantalla, el...el...el que??

Empecemos pues por el principio. WPF es el nuevo susbistema de presentacion grafica incluido en el .NET Framework 3.0, centrando en la tan cacareada user experience. Bien. Y el Madrid que, otra vez campeon de Liga? Que es esto de user experience, o experiencia de usario? Pues no es mas que un esfuerzo por conseguir que los usuarios disfruten de aplicaciones que les permitan hacer las cosas de manera mas facil y mas atractiva.

Por que mas facil? Todos estamos hartos de aplicaciones de gestion de <inserteSuCosaAGestionar> que te obligan a pulsar 7 botones en 4 formularios distintos para cambiar de nombre a un usuario. Seamos serios, la mayoria de las interfaces de usuario de hoy en dia son simplemente malas. Son malas porque fallan en su principal objetivo, que es permitir al usuario hacer lo que quiere de la manera mas indolora posible. Eso es lo que pretende el concepto de UX, interfaces simples y efectivas. Ni mas, ni menos.

Por que mas atractiva? A todo amante de los coches le gustan los Ferraris. Ahora bien, si colocasemos a un F40 un chasis de 600...no seria lo mismo verdad? Tan importante como la funcionalidad de nuestra aplicacion es su aspecto. Es lo primero que va a ver el usuario, lo que marcara la primera impresion que se llevara de nuestra aplicacion. Y puede llegar a ser determinante en la manera que tenga de usarla...o de tirarla a la basura.

En resumen, UX es la calidad de la experiencia del usuario cuando interactua con nuestra aplicacion. Y nuestro objetivo, al menos el mio a dia de hoy, es hacer que tienda a infinito, utilizando WPF. Os interesa echarme una mano?

Publicado 10/12/2006 17:46 por Francisco Martinez | 5 comment(s)

Archivado en: ,