En un post anterior detallé los pasos básicos necesarios para la implementación de un ActiveX con .NET (C#). Pero faltó por describir aquellos necesarios para la interacción de la página HTML con el ActiveX y de este con la página.

Interacción de la página con el ActiveX

La interacción de la página con el ActiveX consiste en poder llamar a métodos del ActiveX o establecer y/o recuperar valores de propiedades públicas del mismo.

Para establecer el valor de una propiedad haremos lo siguiente:

  1. Marcar la propiedad, a la que queremos acceder desde la página, como visible para COM.
  2. [ComVisible(true)]
    public string Property1
    {
        get; set;
    }
  3. Establecer el valor de la propiedad pasándolo como parámetro del ActiveX
  4. <object id="MyActiveX" width="306px" height="167px" classid="clsid:D857B4F5-8684-453e-82C8-7F493CBE5592"
                viewastext style="border-style:dashed">
        <param name="Property1" value="desde Javascript" />
        <p>
            Pon el texto que quieras mostrar si se abre la página con un browser no compatible
            o si el ActiveX no está instalado correctamente.             
        </p>
    </object>
  5. Recuperar el valor de la propiedad del ActiveX
  6. <script type="text/javascript">
        function Method1() {
            alert(MyActiveX.Property1);
        }
    </script>

Para llamar a un método del ActiveX haremos lo siguiente:

  1. Marcar el método que queremos llamar como visible para COM.
  2. [ComVisible(true)]
    public void Method1()
    {
        MessageBox.Show("Hola Mundo desde Javascript");
    }
  3. Llamar el método desde la página.
  4. <script type="text/javascript">
        function Method2() {
            MyActiveX.Method1();
        }
    </script>
    y si abrimos la página en Internet Explorer y hacemos clic en el nuevo botón veremos lo siguiente
    LlamadaDesdeJS

Interaccion del ActiveX con la página

La interacción del ActiveX con la página consiste en poder ejecutar código javascript desde el ActiveX. Esta funcionalidad esta muy bien descrita en este artículo de microsoft y en esencia se trata de crear eventos en .NET y suscribirse a estos desde javascript.

Para ello implementamos la siguiente interface.

using System.Runtime.InteropServices;

namespace MyActiveX
{
    public delegate void ControlEventHandler(string eventArgs);

    [Guid("0422D916-C11A-474e-947D-45A107038D12")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [ComVisible(true)]
    public interface IControlEvents
    {
        [DispId(0x60020000)]
        void Execute(string handler);
    }
}

Marcamos el control tal como sigue

[ClassInterface(ClassInterfaceType.AutoDispatch), ComSourceInterfaces(typeof(IControlEvents))]
[ComVisible(true), Guid("D857B4F5-8684-453e-82C8-7F493CBE5592")]
public partial class MyUserControl : UserControl
{
    ...
}

Luego creamos un evento y el método que lo dispara

public event ControlEventHandler Execute;

private void OnExecute(string handler)
{
    if (Execute != null)
        Execute(handler);
}

Una vez hecho esto en la página HTML nos suscribimos al evento de la siguiente forma

<script type="text/javascript">        
    function MyActiveX::Execute(param)
    {
        alert(param)
    }
</script>

y ya solo los queda llamarlo cuando haga falta. Para este ejemplo la llamada la haremos al hacer click en un botón del control.

mapping_events

y esto ha sido todo. Creo que solo quedaría lo relacionado con marcar el ActiveX como seguro para scripting pero eso es algo que podemos retomar en otro post. Mientras tanto aquí les dejo el código fuente.


Hay muchas formas de hacer que una aplicación de escritorio (Windows Form, WPF) ejecute una y solo una instancia a la vez. Existen muy buenos artículos en internet que hablan de este tema, pero en este post quiero mostrar la que para mi es la manera mas fácil y rápida de lograr esta funcionalidad.

Lo primero que tenemos que hacer cuando creamos el proyecto donde queremos implementar esta característica es agregar la referencia a ensamblado “Microssoft.VisualBasic.dll”

Microsoft.VisualBasic.dll

Luego creamos una clase que herede de WindowsFormsApplicationBase para ello necesitamos incluir el siguiente usgin

using Microsoft.VisualBasic.ApplicationServices;

La implementación de la clase puede ser algo como lo que sigue:

class MyApp : WindowsFormsApplicationBase
{
    //Creamos el constructor y especificamos la forma en que 
    //la aplicación inicializará el objeto My.User de VisualBasic
    public MyApp() : base(AuthenticationMode.ApplicationDefined)
    {
        //Especificamos que solo queremos que se ejecute una solo instancia de la aplicación
        IsSingleInstance = true;
    }

    protected override void OnCreateMainForm()
    {
        //Indicamos cual será el formulario principal de la aplicación
        MainForm = new Form1();
		base.OnCreateMainForm();
    }
}

Una vez hecho esto solo hay que sustituir la llamada a Form1 en el método inicial de la aplicación por la llamada al método Run de la clase que hemos creado.

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        
        //Application.Run(new Form1()); esto es lo que sustituimos por la línea que sigue a continuación

        new MyApp().Run(new string[0]);
    }
}

y con esto garantizamos que la aplicación solo ejecute una solo instancia.

Pasando Argumentos

Existen ocasiones donde es necesario pasarle argumentos a la aplicación para que esta tenga un comportamiento especial en función de los dichos parámetros. En este caso podríamos pasar los argumentos en la llamada al método Run de la aplicación.

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        
        //Application.Run(new Form1());
        new MyApp().Run(args);
    }
}

y luego en los métodos OnStartup y OnStartupNextInstance manejar el comportamiento de la aplicación en función de dichos parámetros.

protected override bool OnStartup(StartupEventArgs eventArgs)
{
    //Hacer algo con los parámetros recibidos (eventArgs.CommandLine)
    return base.OnStartup(eventArgs);
}

protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
    //Hacer algo con los parámetros recibidos (eventArgs.CommandLine)
    base.OnStartupNextInstance(eventArgs);
}

Como hemos podido ver esta es una forma muy sencilla de implementar una aplicación que solo abra una instancia a la vez. Más información sobre la clase WindowsFormsApplicationBase en MSDN

Puedes descargarte el código fuente desde aquí


Uno de los proyectos en los que trabajo actualmente trata de crear un componente común a varias aplicaciones de una empresa. Dichas aplicaciones son todas web y el componente trata de automatizar un proceso que solo puede ocurrir del lado del cliente: capturar la firma digital hecha por un usuario de cualquiera de estas aplicaciones a través de un tableta conectada a un ordenador por USB. Así que como solución se optó por crear un ActiveX ya que como política de la empresa todos eran ordenadores Windows que usaban Microsoft Internet Explorer como navegador.

Yo nunca antes había hecho un ActiveX así que comencé a buscar información en la web. Aunque existen muchos sitios en los cuales se puede encontrar información acerca de este tema. La solución final fue el resultado de lo encontrado en diversos lugares. Este artículo resume todos los pasos que necesité para completar la construcción del ActiveX, y espero que me sirva como referencia en el futuro.

1.) Creando el control ActiveX

Lo primero que haremos es crear un proyecto en VisualStudio del tipo Librería de Clases (Class Library). En la que añadiremos un UserControl en el pondremos un botón y en el evento clic de este mostraremos un mensaje.

SolucionInicial La clase “MyUserControl” deberemos marcarla con los siguientes atributos:

  1. Guid –> Identificador de la clase cuando esta sea expuesta en COM
  2. ComVisible –> Expone la clase para que sea visible desde COM
  3. ClassInterfaceAttribute –> Es el tipo de Interface COM que encapsulará a la clase (mas información en MSDN)

Tip: Si tu ensamblado va a tener más de una clase asegúrate de que esté marcado como NO visible para COM y solo marca las clases realmente quieras exponer.

[assembly: ComVisible(false)]
Al final tenemos algo como en código que sigue a continuación.
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace MyActiveX
{
    [ClassInterface(ClassInterfaceType.AutoDispatch)]
    [ComVisible(true), Guid("D857B4F5-8684-453e-82C8-7F493CBE5592")]
    public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hola Mundo");
        }
    }
}

2.) Incrustando el control en la página HTML

Para mostrar el control en una página web primero hay que instalarlo, ese será el siguiente paso, y luego solo hay que utilizar el tag object como se muestra a continuación. Ten en cuenta que el atributo classid debes poner el GUID con que has decorado la clase en C#



    

Este texto se mostrará si se abre la página con un browser no compatible o si el ActiveX no está instalado correctamente.

3.) Instalando el AcativeX

Para instalar el ActiveX una de las opciones que tenemos es la de crear un instalador que además de dar la opción de ubicar los archivos necesarios para que la aplicación funcione, registre el ensamblado (DLL) que contiene la clase que queremos exponer en COM. Solo hará falta añadir el proyecto principal al proyecto de instalación de VisualStudio.

PrimaryOutput

Seleccionando el “Primary output from MyActiveX” y visualizando sus propiedades, podremos marcar la DLL para que se registre en COM durante la instalación.

InstaladorUna vez hecho esto generamos el instalador lo instalamos en el ordenador y al abrir Internet Explorer y navegar a la página de demostración, vemos el control que hemos creado previamente.

html

y si hacemos clic en el botón vemos que funciona tal y como esperábamos.

holamundo

En un próximo post trataré el tema de la interacción entre el ActiveX y el Navegador.

 

Puedes descargarte el código fuente desde aquí


Hoy he recibido mi Kildle 2, un adelanto de mi regalo de navidad (Gracias DUN). Una de las razones por la que compré este aparato era que, a diferencia de su versión anterior, este incluía a la lista de formatos soportados, archivos con formato PDF. Así que ya no tendría que cargar pesados libros mientras voy leyendo de camino al trabajo.

Una vez lo tuve en la mano, lo primero que hice fue copiar un PFD cualquiera y probar si lo abría kindle2correctamente. Me lleve una desagradable sorpresa al ver que ni siquiera aparecía en la pantalla principal (donde se muestra la lista de todos los libros o documentos). Por lo que me fui a Amazon y me aseguré de que esta versión soportaba el reconocimiento de PDF. Así era, pero el mío no funcionaba (la versión que traía de fábrica 2.2.2) no reconocía el formato PDF :((. Después de hacer búsquedas en Google sin resultado alguno, regresé a Amazon y me descargué la última versión del Software (aquí encontrarás información detallada de como actualizar tu Kindle de forma manual) y con eso se solucionó el problema.

¿Cosas buenas?

  • Luce bastante mejor que su antecesor.
  • La pantalla es bastante opaca, simulando lo mejor posible una hoja de papel.
  • Puedes hacer anotaciones y subrayar parte del texto que estás leyendo
  • Tiene un buen diccionario (Online) si vas a leer documentos en Inglés
  • Soporta formato PDF nativo (a partir de la versión 2.3)
  • Según Amazon la batería dura hasta una semana con el 3G funcionando (no me ha dado tiempo a comprobarlo apenas es mi segundo día con él)

¿Cosas Malas?

  • No he probado la primera generación de Kindles y aunque dicen que en esta se ha mejorado la velocidad de navegación entre páginas, esta sigue siendo lenta.
  • No tiene lector de tarjeta (Ej. SD)
  • La batería no se reemplaza fácilmente.
  • Los documentos PDF no los lee como texto sino como imágenes, por lo que no puedes cambiar el tamaño de la fuente, ni traducir una palabra en específico, ni ninguna de las funcionalidades relacionadas con texto (Ej.Text-to-Speech)

Dentro de lo poco que lo he usado, puedo decir que cumple mis expectativas. Y que ahora mis viajes en el metro son bastante más ligeros :P. Sin embargo creo que va ser muy difícil con este tipo de aparatos acercarse a la experiencia de leer un libro real.


SQL Server Management Studio permite la ejecución de Scripts de SQLCMD (mas información acerca de la utilidad SQLCMD en MSDN).

Para habilitar o deshabilitar SQLCMD en SQL Server Management Studio marque el checkbox
“By default, Open new queries in SQLCMD” de la ventana opciones ( Tools->Options->Query Execution –> SQL Server –> General)

sqlcmd

Una vez hecho esto todas las nuevas ventanas tendrán habilitada o deshabilitada la posibilidad de ejecutar código SQLCMD.

Si lo que quieres es habilitar o deshabilitar para una ventana en específico sin cambiar el valor global de configuración solo deberías activar o desactivar el botón de la barra de herramientas “SQLCMD Mode”

sqlcmd_toolbar

Una vez que habilites SQLCMD podrás ejecutar desde SQL Server Management Studio código como el que sigue a continuación.

:setvar DatabaseName "DB"
:setvar PrimaryFilePhysicalName "C:\DATA\DB.mdf"
:setvar PrimaryLogFilePhysicalName "C:\DATA\DB_log.ldf"

USE [master]

GO

IF (DB_ID(N'$(DatabaseName)') IS NULL) 
BEGIN
    CREATE DATABASE [$(DatabaseName)] ON ( NAME = N'PrimaryFileName', FILENAME = N'$(PrimaryFilePhysicalName)') LOG ON ( NAME = N'PrimaryLogFileName', FILENAME = N'$(PrimaryLogFilePhysicalName)') COLLATE Modern_Spanish_CI_AI 
END
GO

:on error exit

Este tipo de código es el que genera, por ejemplo, un proyecto de “Base de Datos” de Visual Studio.


«Older Posts | Newer Posts»