Controlando tu computadora con el Wiimote mediante C# Parte III

En esta entrega se trata el tema del control de los dispositivos de teclado y ratón mediante C#, con el fin de enlazar el conocimiento anterior de la conexión entre la computadora y el mando de wii. Primero se tiene que ahondar un asunto. Las librerías .NET no brindan de manera  nativa una interfaz para enviar señales de teclado o de ratón. Por esta razón es necesario utilizar los mecanismos para interactuar con las librerías  de Windows desde C#. El mecanismo provisto por Microsoft para permitir la interacción de código nativo con plataformas de código manejado como la Plataforma .NET  se conoce como Servicios de Invocación de Plataforma o P/Invoke (Del Inglés  Platform Invoke Services).
Para utilizar una librería nativa desde código C#, primero se necesita incluir la librería que provee los servicios de Invocación de Plataforma, para esto basta introducir la sentencia: using System.Runtime.InteropServices; en la sección donde se incluyen las librerías de nuestro código.
Existen muchas librerías que pueden ser enlazadas de esta manera pero, para mantener el hilo conductor del tema se utilizará la librería “user32.dll” que es la librería encargada de, entre muchas funciones, manejar eventos producidos por el teclado y el ratón dentro del sistema operativo. Esto nos resulta muy beneficioso pues los movimientos realizados usando esta librería serán interpretados de la misma manera que si fueran producidos por el teclado o el ratón “reales”.
Para más información sobre las posibilidades de  uso de p/invoke  y de la librería user32.dll pueden visitar: http://www.pinvoke.net/.
Con el fin de poder controlar los movimientos de ratón, será necesario hacer referencia al método mouse_event de la librería "user32.dd". Para hacer uso del método externo escribimos lo siguiente
[DllImport("user32.dll")]
        public static extern void mouse_event(
            int dwFlags,
            int dx, int dy,
            int dwData,
            IntPtr dwExtraInfo
        );
Aquí DllImport("") es la función usada por el CLR para saber que librería adjuntar. En el ejemplo anterior se incluye a "user32.dll".
Como paso siguiente se escribe el método externo a utilizar así como sus parámetros si es que existen. Como dato a destacar se tiene la utilización del modificador extern para indicarle al compilador que la implementación del método se encuentra en una librería externa al mismo.
El método mouse_event representa a todos los eventos que puede experimentar un ratón.
El atributo dwFlags   especifica varios aspectos del movimiento del ratón y de sus botones. Este parámetro puede ser una combinación de los siguientes valores.
Los valores que especifican el estado de los botones del ratón se encuentran configurados para indicar cambios en el estado del ratón, no para representar condiciones repetidas. Un ejemplo de esto puede ser que si se presiona el botón izquierdo del ratón y se sostiene, la condición MOUSEEVENTF_LEFTDOWN se activa cuando el botón izquierdo se presiona por primera vez pero no para movimientos siguientes. De una manera similar la condición MOUSEEVENTF_LEFTUP se activa solo cuando el botón se suelta.
Un detalle importante es que no se puede especificar las condiciones  MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN o MOUSEEVENTF_XUP de manera simultánea debido a que requieren el uso del parámetro dwData.
Esta es una tabla con los atributos disponibles así como su valor hexadecimal, que es el que utilizaremos en su aplicación:
Nombre del Atributo
Valor Hexadecimal
Función
MOUSEEVENTF_ABSOLUTE 0x8000 Especifica que los parámetros dx y dy contienen coordenadas absolutas normalizadas. Si no se incluye este atributo, esos parámetros contienen datos relativos (El cambio desde la última posición anterior reportada). Este atributo puede ser incluido sin importar el tipo de ratón o similares que se encuentren conectados.
MOUSEEVENTF_MOVE 0x0001 Especifica que ocurrió un movimiento.
MOUSEEVENTF_LEFTDOWN 0x0002 Especifica que el botón izquierdo ha sido presionado.
MOUSEEVENTF_LEFTUP 0x0004 Especifica que el botón izquierdo ha sido soltado.
MOUSEEVENTF_RIGHTDOWN 0x0008 Especifica que el botón derecho ha sido presionado.
MOUSEEVENTF_RIGHTUP 0x0010 Especifica que el botón derecho ha sido soltado.
MOUSEEVENTF_MIDDLEDOWN 0x0020 Especifica que el botón medio ha sido presionado.
MOUSEEVENTF_MIDDLEUP 0x0040 Especifica que el botón medio ha sido soltado.
MOUSEEVENTF_WHEEL 0x0800 Windows NT/2000/XP: Especifica que  la rueda del botón ha sido movida, si el ratón posee rueda. El movimiento es especificado en el parámetro dwData.
MOUSEEVENTF_XDOWN 0x0080 Windows 2000/XP: Especifica que un botón X ha sido presionado.
MOUSEEVENTF_XUP 0x0100 Windows 2000/XP: Especifica que un botón X ha sido soltado.
El parámetro dx especifica  la posición absoluta del ratón en el eje X, o la cantidad de movimiento desde que el último evento de ratón fue generado, esto dependiendo de si el atributo MOUSEEVENTF_ABSOLUTE fue incluido en el parámetro dwFlags.
El parámetro dy realiza la misma función que el parámetro dx, solo que para el eje Y.
El parámetro dwdata puede especificar varias cosas:
• Si se incluyó al atributo MOUSEEVENTF_WHEEL en dwFlags, entonces el parámetro especifica la cantidad de movimiento ejercido en la rueda del ratón Un valor positivo indica movimiento hacia adelante en dirección contraria al usuario mientras que un valor negativo indica un movimiento inverso. Un clic en la rueda se identifica mediante el valor WHEEL_DELTA, que corresponde al entero 120.
• Si se incluyó al atributo MOUSEEVENTF_XDOWN o MOUSEEVENTF_XUP en dwFlags, entonces dwData especifica que botones X son los que están siendo presionados o soltados. Este atributo es una combinación de los valores de los botones involucrados. (El primer botón XButton1 con valor hexadecimal 0x0001, o el botón XButton2 con el valor 0x0002).
• Si dwFlags no incluye a MOUSEEVENTF_WHEEL, MOUSEEVENTF_XDOWN o a MOUSEEVENTF_XUP, entonces el valor de  dwData debe ser cero.
El parámetro dwExtraInfo contiene datos adicionales relacionados al evento del ratón. Para este caso no será de utilidad así que en lo posible será asignado con valor nulo.
Para los valores de entrada del teclado se utiliza la misma lógica, primero se hace referencia al metodo que maneja el evento de presionar teclas:
[DllImport("user32.dll")]
        public static extern void keybd_event(
            byte bVk,
            byte bScan,
            int dwFlags,
            IntPtr dwExtraInfo
        );
Los parámetros para este método son:
El parámetro bVk especifica un código de tecla virtual. Este código debe corresponder a un valor en un rango entre 1 y 254. Los códigos de teclas virtuales y sus respectivos valores se pueden observar desde Esta Dirección. Para este artículo se utiliza el enum Keys incluido en la librería System.Windows.Forms, este enumerado contiene gran variedad de teclas y sus valores son correspondientes a las teclas virtuales.
El parámetro bScan permite incluir un código de hardware relacionado con la tecla, para este caso no se utiliza, se establece su valor como cero.
 dwFlags se comporta de la misma manera que el parámetro de mouse_event, permitiendo definir una serie de aspectos de la operación de la función. Se pueden incluir los siguientes atributos.





KEYEVENTF_EXTENDEDKEY: Si se incluye este atributo, el código especificado en bScan esta precedido por un prefijo de valor 0xE0 (224)







KEYEVENTF_KEYUP: Si se incluye este atributo,  la tecla está siendo soltada, de lo contrario esta siendo presionada.


Por último, el parámetro dwExtraInfo contiene datos adicionales relacionados al evento del ratón. Para este caso no será de utilidad así que en lo posible será asignado con valor nulo.

Mediante estas funciones es posible emular las acciones de un teclado  y un mouse, para ilustrar mejor la utilización de estas funciones he preparado el ejemplo siguiente.

Ejemplo de control de ratón utilizando nunchuk: EjemploNunchukMouse.zip


Controlando tu computadora con el Wiimote mediante C# Parte II

Esta es la segunda parte de la serie de Artículos de como controlar tu computadora con el Wiimote en C#. 

Esta librería fue concebida inicialmente como un artículo para el sitio Coding4Fun de Microsoft por el Desarrollado Brian Peek en marzo del 2007. La librería ha ido evolucionando desde entonces hasta convertirse en una herramienta práctica y poderosa para utilizar el mando del wii. La última versión para la fecha del presente artículo es la 1.8, contiene un soporte limitado para el accesorio WiiMotionPlus aunque como todavía es inestable, se utilizará la versión 1.7.

Para comenzar, se crea un proyecto nuevo en c#, para este artículo se creará una Aplicación de Windows Forms. El primer paso será guardar el proyecto, con el fin de establecer la carpeta de archivos del mismo.

Luego se debe bajar la librería de la Página del Proyecto. Con lo que se debería contar con el archivo WiimotLib_1.7.zip, dentro del cual se encuentra el archivo WiimoteLib.dll que se deberá extraer en el directorio donde se guardó el proyecto.

Ahora, dentro del menú contextual encima del nombre de proyecto se escoge la opción Agregar Referencia como aparece en la imagen siguiente


Seguidamente, aparecerá el dialogo Agregar Referencia, donde se hará clic en la pestaña Examinar y se buscará el archivo Wiimotelib.dll dentro de la carpeta del proyecto donde se extrajo anteriornente.




Aceptando este último dialogo, la librería de control del Wiimote ha sido añadida con éxito.

Se probará el funcionamiento de la librería entonces añadiendo el siguiente código al formulario principal de la aplicación:
using System.Windows.Forms;

using WiimoteLib;
namespace EjemploWiimote

{   
    public partial class Form1 : Form


    {


        Wiimote Control; //Esta estructura representa al mando de wii 
        public Form1(){


            Control = new Wiimote();


            try


            {//Se intenta establecer una conexión con el control de Wii


                Control.Connect();


                // Se va a añadir una función que se active cuando el


                // mando produzca un evento   
                Control.SetReportType(InputReport.Buttons, true);


                Control.WiimoteChanged += new System.EventHandler<WiimoteChangedEventArgs>(Control_WiimoteChanged);


            }


            catch (WiimoteNotFoundException e)


            {// El Control no se encuentra enlazado con la computadora


                MessageBox.Show(e.Message);


            }


            InitializeComponent();


        }
        void Control_WiimoteChanged(object sender, WiimoteChangedEventArgs e)

        {//Funcíon que se activa cuando ocurre un cambio en el estado del control de wii


            if (e.WiimoteState.ButtonState.A)


            {//Si está presionado el Botón A


                MessageBox.Show("Presionado el Botón A!");


            }


        }


    }


}


Donde primero se incluye la librería WiimoteLib a fin de utilizar la estructura Wiimote que representa al control de wii.

Con la instrucción Connect, el programa busca entre los dispositivos bluetooth que se tengan enlazados con la computadora e intenta conectar al dispositivo que corresponda con un mando de wii. En caso de no estar ningún wiimote enlazado, se envía la excepción WiimoteNotFound indicando precisamente eso, que no se puede encontrar el control.

Se crea entonces una función(Control_WiimoteChanged) para manejar el evento WiimoteChanged que se activa cada vez que ocurre un evento significativo en el mando como el presionar un botón o mover el mando.  Este evento incluye como argumento un objeto WiimoteState que incluye diferentes estructuras que contienen atributos para representar el estado del mando en ese momento. Por ejemplo, en el código anterior se observa el estado e.WiimoteState.ButtonState.A, lo que significa que se esta observando el estado del boton A dentro del estado de los botones.

Se puede variar el criterio para generar un evento utilizando la función SetReportType donde se recibe un InputReport que es la clase de reporte a mostrar como Buttons que significa solo datos de los Botones por lo que solo los cambios en los botones activarán el evento o ButtonsAccel que representa que tanto los cambios en el estado de los botones como el movimiento del mando activarán el evento.

Para conocer todas las posibilidades que ofrece la librería se tiene que experimentar un poco.

Aquí se ofrece el código de ejemplo para esta parte del artículo.

En la siguiente entrega, como enviar las señales del mando hacia el mouse y el teclado.

Controlando tu computadora con el Wiimote mediante C# Parte I


Introducción

En los siguientes post  se tratará la forma de controlar una computadora mediante el mando de la consola Wii de Nintendo, utilizando el lenguaje C# para redirigir la entrada del mando hacia clics en teclado o movimientos y clicks del ratón.

Para la creación del programa de control se utilizaron los siguientes recursos:

•    Microsoft Visual C# Express 2008, que se puede descargar desde este enlace.

•    La librería para comunicarse con el Wiimote desde C# utilizada es la librería WiimoteLib, versión 1.7 elaborada por Brian Peek para el sitio Coding4Fun de Microsoft. Para descargarla, visite la página del proyecto en este enlace.

•    Un adaptador bluetooth para conectar el Wiimote con la computadora.

•    Un control de Wii XD.

El mando de la consola Wii ha asombrado a las personas por la manera en la que permite interactuar con los videojuegos ya que cuenta con la capacidad de detectar el movimiento en el espacio y la habilidad de apuntar hacia objetos en la pantalla.

Configuración del mando

Una de las características más interesantes del mando de Wii es la capacidad de ser detectado por una gran variedad de dispositivos bluetooth, incluida la computadora personal.  El mando de Wii puede ser configurado en una gran variedad de sistemas operativos, entre ellos Windows, Linux y Mac OS. Para este artículo se utilizará solo su configuración en el ambiente Windows. Se espera ahondar en la configuración para Linux en futuros artículos.

Existen varias maneras de acoplar el mando de Wii a la PC. Generalmente varían por el tipo de controladores que traiga el adaptador bluetooth. Es importante saber que existen ciertos adaptadores bluetooth incompatibles con el Wiimote.



Como primer paso hay que identificar el tipo de adaptador, existen gran variedad de software bluetooth en el mercado. Abajo se postearán tutoriales para una variedad de los mismos.

En mi caso particular, se resolvió el asunto de manera sencilla utilizando el menú por defecto Dispositivos Bluetooth de Microsoft Windows. Se encuentra en Panel de Control. Es recomendable tratar de conectar el adaptador y probar el controlador por defecto de Windows. Si no funciona puedes seguir las Instrucciones siguientes dependiendo del programa que traiga el dispositivo:
Por ahora posteo los tutoriales en inglés, a medida que los vaya traduciendo actualizaré los link a los post adecuados.

BlueSoleil –>  BlueSoleil Tutorial

WIDCOMM –>; How to: Widcomm

Kensington-> How to: Kensington Bluetooth

Toshiba Stack->  Toshiba Stack


En este post explicaré como enlazar el dispositivo usando la opción Dispositivos Bluetooth.



Primero se accede a la opción desde la vista clásica del Panel de Control.





Desde aquí se abre el cuadro de Dispositivos Bluetooth que debe verse como:
 
Se selecciona entonces la opción Agregar… lo que nos lleva al Asistente para agregar Dispositivos Bluetooth, donde debemos marcar la opción “Mi dispositivo está configurado y listo para ser detectado”. Aquí apretamos los botones 1 y 2 del wiimote y seleccionamos la opción Siguiente con lo que aparecerá el cuadro donde debemos seleccionar el  mando de Wii, llamado Nintendo RVL-CNT-01. en caso de que no aparezca se puede seguir tratando presionando Buscar de nuevo y volviendo a presionar 1 y 2 en el Wiimote (1 y 2 en el Wiimote es la señal por defecto para sincronizar el mando, las luces del control parpadean durante este proceso).




Luego de seleccionar el mando, se le da clic en Siguiente y aparece el cuadro para seleccionar una clave de paso para el dispositivo. El Wiimote no tiene una clave de paso por lo que se escoge la opción “No usar ninguna clave de paso”.
Luego de esto, se da clic en siguiente, se espera a que se termine de instalar el controlador y se da Finalizar cuando se complete el asistente.

Con esto se termina la primera parte del tutorial. En la segunda se tratará verdaderamente el tema de la librería WiimoteLib y su utilización.