Saturday, September 08, 2007

WPF Video

Es la 1:30 am, y el sueño ya no me venció. Así que decidí escribir esta entrada sobre WPF y una tonta comparación con GDI+.

Supongamos que quiero dibujar un cubo con algo de pintura en un windows form.

private void Form1_Paint(object sender, PaintEventArgs e)
{
GraphicsPath miPath = new GraphicsPath();LinearGradientBrush miBrochaGradiente = new LinearGradientBrush(new Rectangle(20, 20, 200, 150),Color.Blue,Color.Black,LinearGradientMode.ForwardDiagonal);Graphics miGrafico = this.CreateGraphics();//Iniciar una figuramiPath.StartFigure();miPath.AddRectangle(new Rectangle(20, 20, 200, 150));miGrafico.FillRectangle(miBrochaGradiente,20,20,200,150);miPath.AddRectangle(new Rectangle(50, 50, 200, 150));miPath.AddLine(20, 20, 50, 50);miPath.StartFigure();miPath.AddLine(220, 20, 250, 50);miPath.StartFigure();miPath.AddLine(220, 170, 250, 200);miPath.StartFigure();miPath.AddLine(20, 170, 50, 200);//Dibujando el pathPen miLapiz = new Pen(Color.Red, 3);miGrafico.DrawPath(miLapiz, miPath);miPath.Dispose();miLapiz.Dispose();miBrochaGradiente.Dispose();
}


Sencillo cierto? un path, que me permite construir una figura a partir de figuras primitivas, las cuales pueden ser: líneas, arcos, rectángulos, elipses, polígonos, y cuantas más figuras se les puedan ocurrir como clases trae el framework para esto. Bien la cosa es que todo esto forma una sola entidad, y en mi sencillo ejemplo, es cuestión de rectángulos y líneas. Oh claro no olviden hacerle Dispose a cada una de sus instancias gráficas, en este caso al objeto que permite hacer el dibujado sobre la forma (miGrafico), el objeto (miPath) quien representa los rectángulos y líneas, y los objetos encargados de ponerle color al asunto (miLapiz y miBrochaGradiente).
Bueno hasta este punto esto ya se pone aburridor y me comienza a dar sueño. Pero se me ocurre que puedo rotar mi cubo. Qué!! Rotar este cubo a estas horas de la madrugada, no señor, y con GDI+, esto no lo acepto. Y que tal si además de rotarlo, en cada una de sus caras muestro un video. Pues yo creo que esto es una pesadilla. Pues no señores es aquí cuando WPF (Windows presentation foundation) llega al rescate.
Dejando la tontería atrás quiero mostrarles como se puede lograr esto. Qué necesitan? Framework 3.0 o 3.5 y de ahí en adelante mucha pero mucha creatividad. Aquí va y que tengan lindos sueños.

<Window
  x:Class="RichContent.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="RichContent">
  <Grid MouseLeftButtonDown="Evento">
  <Viewport3D>
    <Viewport3D.Camera>
      <PerspectiveCamera
        FarPlaneDistance="20"
        LookDirection="0,-0.65,-1"
        UpDirection="0,1,0"
        NearPlaneDistance="1"
        Position="0,2,3" FieldOfView="40" x:Name="Camara" />
    </Viewport3D.Camera>
    <ModelVisual3D>
      <ModelVisual3D.Content>
        <Model3DGroup>
          <AmbientLight Color="White" />
          <GeometryModel3D>
            <GeometryModel3D.Geometry>
              <MeshGeometry3D
              TriangleIndices="0,1,2 3,4,5 6,7,8 9,10,11 12,13,14 15,16,17 18,19,20 21,22,23 24,25,26 27,28,29 30,31,32 33,34,35 "
              Normals="0,0,-1 0,0,-1 0,0,-1 0,0,-1 0,0,-1 0,0,-1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,-1,0 0,-1,0 0,-1,0 0,-1,0 0,-1,0 0,-1,0 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0 1,0,0 0,1,0 0,1,0 0,1,0 0,1,0 0,1,0 0,1,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 "
              TextureCoordinates="1,1 1,0 0,0 0,0 0,1 1,1 0,1 1,1 1,0 1,0 0,0 0,1 0,1 1,1 1,0 1,0 0,0 0,1 1,1 1,0 0,0 0,0 0,1 1,1 1,0 0,0 0,1 0,1 1,1 1,0 0,0 0,1 1,1 1,1 1,0 0,0 "
              Positions="-0.5,-0.5,-0.5 -0.5,0.5,-0.5 0.5,0.5,-0.5 0.5,0.5,-0.5 0.5,-0.5,-0.5 -0.5,-0.5,-0.5 -0.5,-0.5,0.5 0.5,-0.5,0.5 0.5,0.5,0.5 0.5,0.5,0.5 -0.5,0.5,0.5 -0.5,-0.5,0.5 -0.5,-0.5,-0.5 0.5,-0.5,-0.5 0.5,-0.5,0.5 0.5,-0.5,0.5 -0.5,-0.5,0.5 -0.5,-0.5,-0.5 0.5,-0.5,-0.5 0.5,0.5,-0.5 0.5,0.5,0.5 0.5,0.5,0.5 0.5,-0.5,0.5 0.5,-0.5,-0.5 0.5,0.5,-0.5 -0.5,0.5,-0.5 -0.5,0.5,0.5 -0.5,0.5,0.5 0.5,0.5,0.5 0.5,0.5,-0.5 -0.5,0.5,-0.5 -0.5,-0.5,-0.5 -0.5,-0.5,0.5 -0.5,-0.5,0.5 -0.5,0.5,0.5 -0.5,0.5,-0.5 "/>
            </GeometryModel3D.Geometry>
            <GeometryModel3D.Transform>
              <RotateTransform3D>
                <RotateTransform3D.Rotation>
                  <AxisAngleRotation3D
             x:Name="MyRotation3D" Angle="45" Axis="0 1 0"/>
                </RotateTransform3D.Rotation>
              </RotateTransform3D>
            </GeometryModel3D.Transform>
            <GeometryModel3D.Material>
              <DiffuseMaterial>
                <DiffuseMaterial.Brush>
                  <VisualBrush>
                    <VisualBrush.Visual>
                      <MediaElement LoadedBehavior="Play" UnloadedBehavior="Close" Source = "D:\Música\Radiohead\Radiohead live at Glastonbury 2003.avi" Name="Media" />
                    </VisualBrush.Visual>
                  </VisualBrush>
                </DiffuseMaterial.Brush>
              </DiffuseMaterial>
            </GeometryModel3D.Material>
          </GeometryModel3D>
        </Model3DGroup>
      </ModelVisual3D.Content>
    </ModelVisual3D>

    <Viewport3D.Triggers>
      <EventTrigger RoutedEvent="Viewport3D.Loaded">
        <EventTrigger.Actions>
          <BeginStoryboard>
            <Storyboard>
              <DoubleAnimation From="0" To="360" Duration="0:0:5"
              Storyboard.TargetName="MyRotation3D"
              Storyboard.TargetProperty="Angle" RepeatBehavior="Forever" Name="Animacion"/>
            </Storyboard>
          </BeginStoryboard>           
        </EventTrigger.Actions>
      </EventTrigger>
    </Viewport3D.Triggers>

  </Viewport3D>
    <Button HorizontalAlignment="Left" Margin="7,10,0,236" Name="button1" Width="58"  Click="Evento" >Button</Button>
    <TextBox Height="20" Margin="11,42,0,0" Name="textBox1"  VerticalAlignment="Top" HorizontalAlignment="Left" Width="20" TextChanged="Cambio"></TextBox>
    <TextBox Height="20" Margin="11,72,0,0" Name="textBox2" VerticalAlignment="Top" HorizontalAlignment="Left" Width="20" TextChanged="Cambio"></TextBox>
    <TextBox Height="20" Margin="11,102,0,0" Name="textBox3"  VerticalAlignment="Top" HorizontalAlignment="Left" Width="20" TextChanged="Cambio"></TextBox>
    <TextBox Height="20" Margin="11,132,0,0" Name="textBox4"  VerticalAlignment="Top" HorizontalAlignment="Left" Width="20" TextChanged="Cambio"></TextBox>
    <Slider Height="23" Margin="78,9,83,0" Name="slider1" VerticalAlignment="Top" Maximum="59" ValueChanged="Cambio" />
    <Label Height="24.2766666666667" HorizontalAlignment="Right" Margin="0,2.72333333333333,7,0" Name="label1" VerticalAlignment="Top" Width="72.63">Label</Label>
  </Grid>
</Window>



Lo anterior damas y caballeros, es el pequeño fragmento de código XAML que hace toda la tarea que yo quise hacer con GDI+. La verdad es para mí un fragmento de código muy corto, comparado con todo lo que esto hace por nosotros, clases muy potentes que nos proporcionan estos lujos.

Hay unos pocos controles que adicioné para controlar la rotación del cubo, lo cual es otra característica más, además de producir XAML (si créanme, producir, y a cargo de diseñadores gráficos), nosotros como desarrolladores C#, seguimos escribiendo nuestro code behind como veníamos haciéndolo. Y al ritmo de Radio Head aquí está:

// Sample event handler:
private void Evento(object sender, EventArgs e)
{
// Media.Source = new Uri("D:\\Música\\James Morrison - The Last Goodbye.mp3");
}

private void Cambio(object sender, EventArgs e)
{

if (textBox1.Text.Length > 0 && textBox2.Text.Length > 0 && textBox3.Text.Length > 0)
{
Vector3D miV3D = new Vector3D(Double.Parse(textBox1.Text), Double.Parse(textBox2.Text), Double.Parse(textBox3.Text)); MyRotation3D.Axis = miV3D; } if (textBox4.Text.Length > 0) MyRotation3D.Angle = Double.Parse(textBox4.Text); TimeSpan miTs = new TimeSpan(0,0,Convert.ToInt32(slider1.Value)); Duration miDuracion = new Duration(miTs); Animacion.Duration = miDuracion; label1.Content = miTs.Hours.ToString() + ":" + miTs.Minutes.ToString() + ":" + miTs.Seconds.ToString(); Camara.UpDirection = new Vector3D(0, 1, slider1.Value);
}
}

Bueno recueden, deberan apuntar a su propio video, tengo comentada la línea del manejador Evento(), porque ahí muestro cómo puedo cargar por ejemplo un archivo de audio. Claro señores, no solo de video vive el hombre.

Bueno solo dejo a su imaginación todo lo que puede llegar hacer con esto, no siendo más… WPF los mató a todos!!

La imaginación es más importante que el conocimiento
Albert Einstein

Saturday, September 01, 2007

The .NET Show: The Final Episode - Silverlight

Es tiempo de decirle adiós a una de las mejores iniciativas de Microsoft, en pro de los desarrolladores. Lastimosamente veo anunciado el episodio final del .NET Show, que lástima pero bueno sus razones tendrán.

http://blogs.msdn.com/theshow/archive/2007/08/14/the-net-show-the-final-episode-silverlight.aspx

Thursday, August 23, 2007

Digame Patrón

Hola de nuevo

Esta ves quiero regresar a bloguear con un tema que definitivamente es de mucha importancia para todos los que tratamos de desarrollar software. Todos ya nos conocemos el tema aquel de análizar, diseñar, construir, probar... Y en cada una de estas etapas, algunos consagrados y juiciosos personajes han encontrado soluciones generales a problemas bastante específicos. Soluciones que no están restringidas a ningún lenguaje, tecnología o herramienta. Si señores, son los patrones, que nos contextualizan, nos emprobleman, pero al final nos dan una solución.
Y espero de aqui en adelante, basado en el documento "Enterprise Solution Patterns Using Microsoft .NET v2.0" de lo señores de Patterns & Practices, regalarles algunos tips de lo que encuentro ahi como lo más relevante. Acerca de esto no se ha dicho la última palabra, pero los patrones aqui expuestos son la base filosofica y metafisica de miles de aplicaciones ejecutandose en el mundo, por qué? porque nos facilitan la vida, cuando esta se vuelve un ocho en aplicaciones de clase empresarial. No siendo más espero sea de su utilidad.

Patrones para soluciones empresariales utilizando Microsoft .NET

Lo primero es pensar en que todo sistema empresarial debe concebirse simple y crecerá con el tiempo. Esto radica en que cualquier cosa simple trabaja mientras necesite ser reemplazada. La idea es encontrar patrones que sirvan a lo simple y a lo complejo en tiempos distintos. No significa que un patrón lo haga mal y el otro lo haga correctamente, significa que cada patrón se acomoda a un momento dado del proyecto. Muchos objetos en .NET ya implementan varios patrones, así que la idea es utilizarlos y no implementar el patrón desde el principio.

La idea es presentar 32 patrones que expandan varios puntos de vista, y mostrar como pueden ser integrados en una aplicación empresarial. Visualizar los patrones como un lenguaje para expresar experiencias de diseño. Los patrones proporcionan un lenguaje común a arquitectos y desarrolladores para acortar la brecha entre las dos disciplinas.

Las soluciones de negocio de clase empresarial, son a menudo extremadamente complejas y deben ejecutarse bien frente a las altas expectativas. No solo deben ser altamente disponibles y escalables de cara a lo impredecible, sino también medibles y predecibles en respuesta a requerimientos de negocio que cambian rápidamente.

Los patrones son útiles para arquitectos y desarrolladores porque:
· Documentan mecanismos simples que trabajan
· Proveen un vocabulario y una taxonomía común para desarrolladores y arquitectos
· Habilitan a las soluciones para ser descritas como combinaciones de patrones.
· Habilitan el rehúso de arquitectura, diseño, e implementación de decisiones.

Mecanismo para documentar patrones

Un patrón describe un problema recurrente que ocurre en un contexto dado y, basado en un conjunto de lineamientos, recomienda una solución. La solución es usualmente un mecanismo simple, una colaboración entre dos o más clases, objetos, servicios, procesos, hilos, componentes, o nodos que trabajan juntos para resolver el problema identificado en el patrón.

Nota. Se debe aclarar que la implementación de los patrones puede volverse compleja, y lo mostrado aquí es solo para propósitos de introducción, así que mientras más se estudian los patrones en profundidad, se pueden observar aspectos más detallados y de mayor complejidad.

Patrón Singleton

Contexto. Controlar el acceso a una clase administrando su proceso de instanciación.

Problema. Una aplicación contiene un cierto tipo de data que necesita ser globalmente accedida y mantenida. Al mismo tiempo, este tipo de data es a menudo única en el sistema. Cómo proveer una interfaz accesible a una clase, pero controlar el número de instancias dentro del sistema.

Solución. La clase en si misma es responsable de crear una instancia simple y proveer acceso global a esa instancia. Crear una clase que contiene una instancia estática del Singleton que es retornada con un método estático.

public class MiSingleton
{
private static MiSingleton miInstancia = null
private MiSingleton() {}
public static MiSingleton ObtenerInstancia ()
{
if (miInstancia ==null)
{
miInstancia = new MiSingleton ()
}
return miInstancia
}
//... Funciones provistas por MiSingleton
}

El ejemplo anterior define un constructor privado, que hace que ninguna otra clase pueda instanciar a MiSingleton. La clase contiene una instancia estática miInstancia que es retornada con el método ObtenerInstancia().

Como se puede observar, el anterior es un ejemplo muy simple, pero que muestra la implementación esencial del patrón singleton, su objetivo y toda la utilidad que puede proveer dentro de nuestras aplicaciones. Es importante aclarar que los patrones no tienen una única solución o implementación, y están pensados para ser abiertos a cada tecnología.

Patrones en niveles diferentes

Los patrones existen en niveles diferentes de abstracción. Consideremos otro ejemplo, esta ves a un nivel más alto de abstracción que el nivel de codificación:

Estamos diseñando una aplicación basada en Web, que contiene una gran cantidad de lógica de negocio y de presentación. Cómo organizar este sistema a alto nivel para que sea flexible, débilmente acoplado, y aun así, altamente cohesivo?

Una solución a este problema involucra organizar el sistema dentro de una serie de capas, con cada capa conteniendo elementos aproximadamente en el mismo nivel de abstracción. Se identifican las dependencias en cada capa y decidir por una estrategia de capas estricta o relajada. Luego, se decide si se va a crear un esquema de capas personalizado o adoptar un esquema de capas previamente documentado por otros. Supongamos que vamos a usar una estrategia de capas bien conocida, una capa para presentación, para la lógica del negocio y para el acceso a datos.

Si siempre diseñamos sistemas de este modo, estamos empleando un patrón ya existente, independiente de cualquier patrón generalizado. Aún así, hay muchas razones por la que queramos entender los patrones que apoyan esta aproximación de diseño. Podemos ser curiosos y preguntarnos por qué los sistemas frecuentemente se diseñan de esta manera, podemos buscar aproximaciones más óptimas a los problemas que este patrón no resuelve.

Patrón Capas

Contexto. Estamos trabajando, con un sistema grande y complejo, y queremos administrar la complejidad por descomposición.

Problema. Cómo estructurar una aplicación para soportar tales requerimientos operacionales, como mantenibilidad, reusabilidad, extensibilidad, escalabilidad, robustez y seguridad?

Solución. Componer la solución dentro de un conjunto de capas. Cada capa debería ser cohesiva, y aproximadamente al mismo nivel de abstracción. Cada capa debería ser débilmente acoplada a las capas de abajo.

Esta simple estrategia, ayuda a organizar las aplicaciones para resolver dos desafíos en desarrollo de software: la administración de dependencias y la necesidad de componentes intercambiables. Construir aplicaciones sin una estrategia bien considerada para administración de dependencias, conlleva a componentes frágiles, los cuales son difíciles y costosos de mantener, extender y substituir.

Patrón de Aplicación de Tres capas

Contexto. Estamos construyendo una solución de negocio, usando capas para organizar nuestra aplicación.

Problema. Cómo organizar la aplicación para reutilizar lógica de negocio, proveer flexibilidad en el deployment, y conservar conexión a recursos valiosos.

Solución. Crear tres capas: presentación, lógica del negocio (dominio), y acceso a datos. Colocar todos los componentes responsables de la vista en la capa de presentación. Encapsular toda la lógica del negocio en componentes de la capa de dominio que implementan interfaces de componentes bien conocidas. Localice todo el código relacionado a la base de datos, incluyendo clientes de acceso a base de datos, y componentes de utilidad, en la capa de acceso a datos. La capa de datos es responsable por el pool de conexiones cuando acceda los recursos. Asegurarse de eliminar las dependencias entre componentes de acceso a datos, y componentes de la capa de negocio. Eliminar dependencias entre la capa de negocio y la capa de presentación o administrar las dependencias utilizando el patrón observador.

Refinamiento simple

Cabe notar que Aplicación de tres capas es realmente un refinamiento simple de Capas; el contexto, la importancia, y la solución identificada en Capas se mantiene aplicada en Aplicación de tres capas, pero no al contrario. Esto es, el patrón Capas restringe a Aplicación de tres capas, y el patrón Aplicación de tres capas refina el patrón Capas. Esta relación de patrones es útil para administrar la complejidad. Después de que entendamos un patrón, debemos solo entender las diferencias incrementales entre el patrón inicial y los patrones que lo refinan. Otro ejemplo, esta ves en el área de servicios web, debería ayudar a ilustrar el concepto de refinamiento.

Hemos escrito una aplicación para una empresa exitosa que se expande rápidamente. Ahora queremos extender la aplicación exponiendo su motor de lógica a socios de negocio e integrar los servicios adicionales de los socios (tales como compras) dentro de la aplicación. Cómo estructuramos nuestra aplicación de negocio para proveer y consumir servicios?

Una solución a este problema es extender el patrón Aplicación de tres capas adicionando responsabilidades relacionadas a servicios adicionales a cada capa. La capa de negocio adiciona la responsabilidad de proveer un conjunto simplificado de operaciones para aplicaciones clientes a través de Interfaces de Servicio. Las responsabilidades de la capa de acceso a datos van más allá de la base de datos e integran hosts para incluir comunicación con otros proveedores de servicios. Esta funcionalidad adicional en la capa de acceso a datos es encapsulada en componentes de Pasarelas de Servicios, los cuales son responsables por conectarse a servicios (tanto sincrónica como asincrónicamente), administrando el estado conversacional básico con el servicio, y notificando a los componentes de procesos de negocio de significativos eventos relacionados a servicios.

Patrón Servicios de tres capas

Contexto. Estamos construyendo una solución de negocio que usa capas de presentación, negocio y acceso a datos para organizar la aplicación. Queremos exponer algo de la funcionalidad central de la organización como servicios que otras aplicaciones puedan consumir y habilitar la aplicación para consumir otros servicios.

Problema. Cómo organizar nuestra aplicación para proveer y consumir datos granulares y elementos lógicos de fuentes altamente variables?

Solución. Descomponer la lógica de la aplicación dentro de un conjunto de servicios colaborativos que proveen partes de la funcionalidad completa del sistema. Luego, en la capa de dominio, identificar una Interfaz de Servicios por cada servicio que es independiente de la implementación subyacente. Finalmente, extender la capa de acceso a datos para utilizar Pasarelas de Servicio, para comunicarse con otros proveedores de servicio. Si la lógica de navegación de la aplicación es suficientemente compleja, consideremos usar componentes de proceso de interfaz de usuario como parte de la capa de presentación para encapsular y reutilizar esta lógica.

Es notoria la relación entre estos patrones. Capas introduce una estrategia fundamental para organizar una aplicación de software. Aplicación de tres capas refina esta idea y la restringe a los sistemas de negocio que requieren reutilizar lógica de negocio, flexibilizar el deployment, y uso eficiente de conexiones. Aplicación de servicios de tres capas refina a Aplicación de tres capas y extiende el diseño para proveer y consumir elementos granulares de datos y lógica de fuentes altamente variables.

Bien para terminar, ya iremos desarrollando algo práctico de todo esto, pero es muy importante iniciarse en la teoría y familiarizarse con la forma de documentar patrones, que realmente no es tan complicado, y tal ves tú, si tú, puedas encontrar nuevos patrones o refinar los existentes.

Feliz arquitectura

Wednesday, July 04, 2007

Excel AddIn con C# y VSTO

Hola de nuevo

Retomando uno de los temas que más me gusta, aqui les traigo un ejemplo bastante sencillo acerca de cómo crear addins de Excel 2007, utilizando VSTOs con C#.

Lo primero es adicionar un nuevo proyecto y seleccionar el template adecuado como le sindico en la siguiente imagen:

Luego de esto, VS crea para nosotros un proyecto de tipo AddIn de Excel, un proyecto de setup y toda una infraestructura de métodos, eventos y objetos, listos para comenzar a trabajar en el desarrollo.


Ahora, sobre el proyecto de AddIn, damos clic derecho y seleccionamos Add - New Item... y seleccionamos la opción Ribbon suport:Esto de ribbon es un nuevo concepto, introducido en Office 2007, digamos para ordenar las funcionalidades en diferentes pestañas, las cuales hacen parte del Ribbon que es la combinación de las barras de herramientas y el menú, que antes lo veiamos como una fila de botones.

Ahora bien, las clases sobre las que vamos a trabajar son las creadas por VS para nosotros: ThisAddIn.cs y Ribbon1.cs.

En la primera se encuentran los eventos ThisAddIn_Startup y ThisAddIn_Shutdown, los cuales son los puntos inicial y final del AddIn. Pero por ahora no los vamos a tocar, más bien creamos un nuevo método que sera el que preste la funcionalidad:


public void TestExcelRanges()
{
Excel.Range miRango = null;
Excel.Worksheet miSheet = null;
miSheet = this.Application.ActiveSheet as Excel.Worksheet;
miRango = miSheet.get_Range("A1", "A1");
miRango.set_Value(Missing.Value,10);
miRango = miSheet.get_Range("B1", "D5");
miRango.set_Value(Missing.Value, 100);
miRango = miSheet.get_Range("E:E",Missing.Value);
miRango.set_Value(Missing.Value, 200);
miRango = miSheet.get_Range("F1;G2;H3;I4", Missing.Value);
miRango.set_Value(Missing.Value, 400);
}
Es un método bastante sencillo que fija valores, basado en el establecimiento de rangos sobre la hoja de trabajo. Lo realmente importante es la definición de las instancias de tipo Range y Worksheet, que son el punto de inicio para todo el trabajo. Lo demás es ir descubriendo la funcionalidad de la gran cantidad de métodos, propiedades, etc etc. Entre las cosas que tenemos aca es la clase Missing. No se maten la cabeza, simplemente adicionen el namespace System.Reflection, para que tengan acceso a Missing.Value. Recuerden este método va en la clase ThisAddIn.


Ahora en la clase de tipo Ribbon, la idea es quitar los comentarios del método RequestService() y en la sección CallBacks deberia quedar así:

public void OnButton1(Office.IRibbonControl control)
{
Globals.ThisAddIn.TestExcelRanges();
}

En el archivo XML que se agregó al proyecto, debe quedar así:
Básicamente en ese archivo se define una imagén asociada al AddIn, el manejador del evento disparado por el botón adicionado al Ribbon, y otras propiedades más. Solo basta ejecutar la aplicación, y debe entonces abrirse Excel desplegando los valores asociados para cada rango establecido, como se muestra en la figura:

Felices lineas de código
!!

Monday, June 18, 2007

No lo digo yo

Hola de nuevo

Esta es una pequeña entrada para algo que vengo escuchando ya hace unos años. Perdidas y ganancias, solo un pequeño porcentaje de proyectos de software dan buenos resultados, el resto...

De acuerdo al Standish Group [Sta94], las empresas en los Estados Unidos de América, invierten US$ 250 mil millones en el desarrollo de software para aproximadamente 200 proyectos cada año. Sólo el 16% finaliza a tiempo y dentro del presupuesto. El 31% se anula, debido a problemas de calidad generando pérdidas de aproximadamente US$ 81 mil millones. Otro 53% excede el presupuesto por un promedio de 189%, generando pérdidas aproximadas de US$ 58 mil millones. Los proyectos que se completan promedian sólo el 42% de los que se planificaron en un principio.

No se asusten, más bien lean el Journal de Microsoft sobre aruqitectura, que me sorprende ahora encontarlo en español, o más bien me emociona, así se gasta menos tiempo teniendo que traducir, se digiere más rápido. A lo que hago referencia lo encuentran en el número 3, a partir de ahi la revista tiene todos sus números en español. Así que si quieren saber de arquitectura de la mano de los mejores, ya no se pueden quejar por falta de información!!

http://msdn2.microsoft.com/en-us/arcjournal/bb201656.aspx#spanish

Un abrazo y feliz arquitectura!!

Sunday, June 03, 2007

Qué alguien me muestre los procesos

Hola de nuevo

La clase Process es mi invitada para esta entrada, con la cual quiero mostrarles un ejemplo muy simple. La idea, listar los procesos que se están ejecutando localmente en nuestra máquina. Es bueno saber también que está clase me permite listar los procesos de una máquina remota. Además puedo, iniciar y detener procesos. En fin aqui les dejo el ejemplo.

Primero, crearse un proyecto de tipo Consola, en las plantillas de C#

Luego en su método Main() escriben lo siguiente:


Bastante simple la cosa, y en la salida de este ejemplo, podran ver listados todos los procesos ejecutandose actualmente, mostrandose su PID y su nombre.
De todos modos, si buscan más en la clase Process, encontrarán muchas más propiedades y métodos bastante interesantes que pueden servir para llaver a cabo otra serie de tareas.

Felices líneas de código.

Friday, June 01, 2007

Microsoft Technology Day: Ciclo de vida de Aplicaciones

Nuevo evento en Colombia, donde se va a mostrar todo lo que Microsoft tiene para ofrecernos en herramientas que ayudan a administrar todo el ciclo de desarrollo de aplicaciones.

Vean más información en el blog del señor Ivanov Cepeda de Microsoft Colombia.

http://blogs.msdn.com/devcolombia/archive/2007/05/24/microsoft-technology-day-ciclo-de-vida-de-aplicaciones.aspx