Archivos Mensuales: enero 2011

Configurando Micosoft Visual C# 2010 Express para crear aplicaciones Digi3D 2011 de 64 Bits

Si tienes instalada la versión de 64 bits de Digi3D 2011, las aplicaciones que desarrolles en .NET deberán ser aplicaciones de 64 Bits o aplicaciones Any CPU.

Si realizas alguna aplicación de 32 bits utilizando el motor de Digi3D 2011 de 64 bits, no podrás ejecutar la aplicación, el CLR te enviará una excepción de tipo System.BadImageFormatException como puedes comprobar en la siguiente captura:

Solucionar esto es muy sencillo, pero depende del compilador que utilices:

  • Si tu compilador es un Microsoft Visual Studio 2010 Professional, realizar esta tarea es sencillo:

    Despliegas el cuadro de lista Plataformas de solución de la barra de herramientas Estándar y si aparece la opción x64 o Any CPU la seleccionas.

    Si no aparece esta opción, seleccionas Administrador de configuración…, y en el cuadro de diálogo Administrador de configuración seleccionas en Plataforma de soluciones activas: la opcion <Nueva…>.
    En el cuadro de diálogo Nueva plataforma de solución, despliega el cuadro de lista Escriba o seleccione la nueva plataforma: y selecciona x64 o Any CPU.
    Acepta los cuadros de diálogo Nueva plataforma de solución y Administrador de configuración.

    Ya tienes preparado tu proyecto para compilar aplicaciones para Digi3D 2011 edición 64 Bits.

  • Si tu compilador es Microsoft Visual C# 2010 Express los pasos son los mismos, pero es posible que la barra de herramientas Estándar no te muestre el cuadro de lista Plataformas de Solución ya que este compilador, al ser un compilador de evaluación y aprendizaje, viene configurado con en mínimo interfaz de usuario posible.

    Además, si hacemos que esta barra de herramientas muestre el cuadro de lista Plataformas de Solución, es posible que no podamos desplegar el cuadro de lista porque aparece bloqueado.

    A continuación tienes los pasos que debes seguir para poder cambiar de plataforma:

    1. En Herramientas/Configuración, selecciona la opción Configuración para expertos. Con esto conseguirás que la barra de herramientas Estándar muestre el cuadro de lista Plataformas de solución.
    2. En Herramientas/Opciones seleccionamos la casilla de verificación Mostrar todas las configuraciones (abajo del todo). Con esto conseguimos que el cuadro de diálogo Opciones muestre mucha más información.
    3. En Proyectos y soluciones/Generar activamos Mostrar configuraciones de compilación avanzadas y aceptamos el cuadro de diálogo. Con esto conseguiremos que el cuadro de lista Plataformas de solución sea modificable.

Base de datos EPSG en Digi3D 2011 edición de 64 Bits

Esta entrada ha quedado obsoleta pues con posterioridad a su creación, se convirtió la base de datos a SQL Server Compact que si es compatible con ediciones de 64 bits y no requieren instalar un SQL Server Express. Se mantiene la entrada en el blog como curiosidad histórica.

Digi3D 2011 extrae los parámetros de los distintos sistemas de coordenadas que implementa de la base de datos estándar publicada por “OGP Geomatics Committee”.

Este comité publica periódicamente una base de datos (denominada Geodetic Dataset) en distintos formatos (Microsoft Access 2000, mySQL, Oracle y PostgreSQL).

El instalador de Digi3D 2011 instala una copia de la base de datos Access en el disco duro local y almacena una entrada en el registro para indicarle a Digi3D la cadena de conexión que debe establecer para conectarse con la base de datos Access.

Esta cadena se almacena en:

Sistema operativo Versión de Digi3D Entrada en el registro
32 bits 32 bits HKEY_LOCAL_MACHINESoftwareDigi21Digi3D2011AppConfigurationEPSGConnectionString
64 bits 32 bits HKEY_LOCAL_MACHINESoftwareWow6432NodeDigi21Digi3D2011AppConfigurationEPSGConnectionString
64 bits 64 bits HKEY_LOCAL_MACHINESoftwareDigi21Digi3D2011AppConfigurationEPSGConnectionString

con el siguiente valor:

Sistema operativo Valor almacenado
Windows XP Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=C:Documents and SettingsAll UsersDatos de programaDigi3D 2011 BetaEPSGEPSG_v7_5.mdb
Windows 7 Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Source=c:ProgramDataDigi3D 2011EPSGEPSG_v7_5.mdb

Si te fijas en la cadena de conexión, se utiliza como proveedor Microsoft.Jet.

Bueno, pues el proveedor Microsoft Jet esconde una “sorpresa”, y es que no es compatible con aplicaciones de 64 bits, así que si queremos ejecutar Digi3D 2011 tendremos que importar la base de datos Access en un servidor de bases de datos que sí que sea compatible con aplicaciones de 64 bits.

A continuación tienes una captura de pantalla del mensaje que muestra Digi3D 2011 edición 64 Bits al ejecutarse en el equipo por privera vez:

La solución más sencilla es instalar (si no lo tienes ya instalado) el fantástico servidor de bases de datos Microsoft SQL Server 2008 Express que puedes descargar de http://www.microsoft.com/express/Database/.

  • Una vez instalado, ejecuta el programa Microsoft SQL Server Management Studio.
  • Aparecerá un cuadro de diálogo titulado Connect to Server.
  • En Server type, selecciona: Database Engine
  • En Server name teclea: .sqlexpress
  • Pulsa el botón Connect
  • En la ventana Object Explorer (que aparece acoplada en la parte izquierda) pulsa con el botón derecho del ratón en Databases.
  • En el menú contextual que aparece, selecciona New database…
  • En el cuadro de diálogo New Database teclea EPSG_v7_6 (o el nombre que quieras) y pulsa el botón OK
  • Abre el arbol Databases en la ventana Object Explorer y comprobarás que ahora aparece tu base de datos. Únicamente nos queda rellenarla con información, pues está recién creada y sin información.
  • Pulsa con el botón derecho del ratón en la base de datos y en el menú contextual selecciona la opción Tasks/Import data….
  • En el asistente SQL Server Import and Export Wizard pulsa Next en la página de bienvenida.
  • En la página Choose a Data Source, en el cuadro de lista Data Source selecciona Microsoft Access
  • En File name, pulsa el botón Browse… y localiza la base de datos.

    En la siguiente tabla puedes ver la ubicación de la base de datos Acces en función del sistema operativo:

    Sistema operativo Ruta
    Windows XP C:Documents and SettingsAll UsersDatos de programaDigi3D 2011 BetaEPSGEPSG_v7_6.mdb
    Windows 7 c:ProgramDataDigi3D2011EPSGEPSG_v7_6.mdb
  • Selecciona la base de datos, acepta el cuadro de diálogo Open y pulsa el botón Next.
  • En la página Choose a Destination selecciona SQL Server Native Client 10.0 en el cuadro de opciones Destination, en Server name teclea .sqlexpress y abajo en Database selecciona la base de datos que habías creado.
  • Pulsa Next
  • En la pagina Specity Table Copy or Query selecciona Copy data from one of more tables or views y pulsa Next.
  • En Select Source Tables and Views selecciona todas las tablas excepto aquellas que comienzan con `qry y pulsa Next.
  • Por último en la página Run Package pulsa el botón Finish y en la página Complete the Wizard pulsa el botón Finish.
  • Verás cómo se importa la base de datos. Una vez finalizado el proceso, pulsa Close.
  • Por último cierra el programa Microsoft SQL Server Management Studio.

Ahora ya puedes configurar Digi3D 2011 para que localice la base de datos.

  • Si tu versión de Digi3D 2011 es de 64 bits, al intentar ejecutar el programa éste te muestra un cuadro de diálogo indicando que no se puede conectar con la base de datos geodésica. Pulsa el botón Especificar una nueva cadena de conexión mediante un cuadro de diálogo.
  • Si tu versión es Digi3D de 32 bits, puedes hacer este cambio en Herramientas/Configuración/Base de datos EPSG, pulsando el botón de los tres puntos.
  • En el cuadro de diálogo Data Link Properties selecciona Microsoft OLE DB Provider for SQL Server y pulsa el botón Next.
  • En la pestaña Connection en el primer punto teclea: .sqlexpress
  • En el segundo punto selecciona Use Windows NT Integrated secirity.
  • En el tercer punto, despliega la lista y selecciona tu base de datos.
  • Pulsa el botón Test Connection para comprobar que todo ha ido bien. Deberá aparecer un cuadro de mensaje indicando que la conexión ha sido satisfactoria.
  • Por último acepta el cuadro de diálogo Data Link Properties y ya has terminado.

Archivos de teclas de Digi3D 2011

Hay una pregunta que me hacen siempre que hago un curso de Digi3D cuando explico cómo asignar órdenes a teclas:

¿Cómo se qué en qué tecla tengo asignada una determinada orden?

Y la respuesta muy a mi pesar es siempre la misma: No hay manera de saberlo.

Este escenario cambia completamente en Digi3D 2011, ya que los archivos de teclas son XML y están pensados para que se puedan imprimir para tener un listado de las teclas asignadas. Además ahora podemos tener asignadas varias órdenes a una pulsación de teclas, haciendo innecesario el uso de macroinstrucciones.

Al instalar Digi3D 2011, se crea en la carpeta %ProgramData%\Digi3D 2011\Esquemas XML una carpeta con los esquemas de los archivos XML soportados por Digi3D 2011, y entre otros se copia el archivo Keyboard.xsd con el siguiente contenido:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://schemas.digi21.net/Digi3D/keyboard/v1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Keyboard">
    <xs:complexType>
      <xs:sequence>
        <xs:element maxOccurs="unbounded" name="Key">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute name="Name" type="xs:string" use="required" />
                <xs:attribute name="Shift" type="xs:boolean" use="optional" />
                <xs:attribute name="Control" type="xs:boolean" use="optional" />
                <xs:attribute name="Menu" type="xs:boolean" use="optional" />
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

En el que podemos ver que el nuevo formato está compuesto por un nodo raiz de tipo Keyboard que está compuesto por nodos Key que tienen que tener obligatoriamente un atributo Name y que opcionalmente pueden o no tener atributos de tipo Control, Shift o Menu

Veamos el contenido del archivo Default.keyboard.xml que instala el instalador de Digi3D 2011:

<?xml version="1.0" encoding="utf-8"?>
<Keyboard xmlns="http://schemas.digi21.net/Digi3D/keyboard/v1.0">
  <Key Name="AV PAG">rest_zoomin</Key>
  <Key Name="RE PAG">rest_zoomout</Key>
  <Key Name="F3">rest_zoome</Key>
  <Key Name="F4">rest_zoom1x1</Key>
  <Key Name="TECLA DE ADICION">velocidad_mas_xy</Key>
  <Key Name="TECLA DE SUSTRACCION">velocidad_menos_xy</Key>
  <Key Name="TECLA DE MULTIPLICACION">velocidad_mas_z</Key>
  <Key Name="TECLA DE DIVISION">velocidad_menos_z</Key>
  <Key Name="F2">tipo_indice</Key>
  <Key Name="F5">positivo_negativo</Key>
  <Key Name="B">correlar</Key>
  <Key Name="TABULACION">cambia_teclas_mnu</Key>
  <Key Name="F12">mostrar_estereo</Key>
  <Key Name="FIN" Control="true">salir_digi3d</Key>
  <Key Name="P" Control="true">ir_a_punto_apoyo</Key>
  <Key Name="F1">raton_digi3d</Key>
</Keyboard>

Se puede comprobar perfectamente que pulsando la combinación de teclas Control + Fin se ejecuta la orden SALIR_DIGI3D.

Ahora disponemos de un formato mucho mejor, pero tenemos un problema: Hay que hacer un programa que genere este tipo de archivos a partir de versiones anteriores.
El problema es que no es trivial, ya que no hay una forma directa de averiguar la tecla o la combinación de teclas que corresponde con el número de tecla almacenado en los archivos Teclas.mnu, ya que los números de tecla que aparecen en los archivos Teclas.mnu son números de teclas generados por MS-DOS y no por Windows.

Cuando pasamos de Digi (la versión de MS-DOS) a Digi21 (la versión de Windows) hicimos el esfuerzo de hacer que los archivos TECLAS.MNU de MS-DOS fueran compatibles con los archivos TECLAS.MNU del programa de Windows para así evitar que los usuarios de MS-DOS tuvieran que volver a generar sus archivos de teclas.

Para conseguirlo, dedicamos tiempo en intentar simular el número de tecla que genera MS-DOS a partir del número de tecla que nos envía Windows cuando el usuario realiza una pulsación.

Estos números no tienen nada que ver, pero al final conseguimos un algoritmo que acertaba en el 90% de los casos.

El algoritmo es el siguiente:

    UINT teclaDigi21 = 0;
    UINT nFlags = (pMsg->lParam & 0xffff0000) >> 16;

    if( mayusculasPulsada )
        nFlags += 25;
    else if( controlPulsada )
        nFlags += 35;
    else if( altPulsada )
        nFlags += 45;

    if( ::TranslateMessage(pMsg) ) {
        MSG msg;
        teclaDigi21 = msg.wParam;
    }

    int scanCode = (nFlags & 0xFF) << 8;
    teclaDigi21 |= scanCode;

Si te fijas, hay que hacer muchas operaciones para transformar el número de tecla que envía Windows para conseguir el valor teclaDigi21.

Una vez conocido el algoritmo, podríamos hacer un programa que crée una tabla con todas las posibles combinaciones. Este programa podría esperar a que el usuario pulse todo tipo de combinaciones y al finalizar almacenar la tabla que luego utilizará otro programa que es el que realmente transforma los archivos Teclas.mnu a Teclas.keyboard.xml.

Captura de pantalla del programa CreaTablaTeclasMnuAXml

Este programa espera a que el usuario pulse teclas. Por cada tecla pulsada añade una entrada en el ControlList donde nos muestra el código de tecla Digi21 calculado y la combinación de teclas que se ha pulsado.

Al aceptar el cuadro de diálogo, el programa pregunta la ruta del archivo de texto a crear, y lo que crea es código fuente en C# para luego añadirlo a un proyecto en C#.

A continuación tienes un ejemplo del resultado generado por este programa tras realizar una serie de pulsaciones de teclas:

    struct DatosTecla
    {
        public string Nombre;
        public bool Control;
        public bool Mayusculas;
        public bool Alt;

        public DatosTecla(string nombre, bool control, bool may, bool alt)
        {
            this.Nombre = nombre;
            this.Control = control;
            this.Mayusculas = may;
            this.Alt = alt;
        }
    };
private static Dictionary<int, DatosTecla> diccionario = new Dictionary<int, DatosTecla>
{
    { 8051, new DatosTecla("S", false, false, false) },
    { 8292, new DatosTecla("D", false, false, false) },
    { 7777, new DatosTecla("A", false, false, false) },
    { 8550, new DatosTecla("F", false, false, false) },
    { 9579, new DatosTecla("K", false, false, false) },
    { 9322, new DatosTecla("J", false, false, false) },
    { 11875, new DatosTecla("C", false, false, false) },
    { 12654, new DatosTecla("N", false, false, false) },
    { 12909, new DatosTecla("M", false, false, false) },
};

Si te fijas, este programa crea una estructura en C# con cuatro campos: Nombre, Control, Mayúsculas y Alt, y a continuación crea un diccionario cuya clave principal es el número de tecla de Digi21 y cuyo valor es esta estructura, de modo que el número de tecla 8051 es la tecla S sin Control, ni Mayúsculas ni Alt.

Ahora tan solo nos queda crear un proyecto de C# (yo he creado un proyecto de consola), copiar tanto la estructura como la instancia del diccionario dentro del proyecto y leer el archivo original para crear un archivo XML.

Y el algoritmo de este programa es muy sencillo:

  1. Abrimos el archivo Teclas.mnu antiguo.
  2. Leemos una línea
  3. Separamos la primera palabra de la línea y el resto.
  4. Transformamos la primera palabra a un número entero.
  5. Buscamos ese número en el diccionario.
  6. Almacenamos en el XML un nodo con la información devuelta por el diccionario.
  7. Volvemos al punto 2 mientras queden líneas

A continuación un recorte del código del programa que realiza las acciones 3, 4, 5 y 6:

                        int teclaDigi21 = int.Parse(partes[0]);

                        if (!diccionario.ContainsKey(teclaDigi21))
                        {
                            ++erroresLocalizados;
                            Console.WriteLine(string.Format("No ha sido posible traducir la tecla con número: {0}",
                                teclaDigi21));
                            continue;
                        }

                        DatosTecla datosTecla = diccionario[teclaDigi21];

                        escritor.WriteStartElement("Key");
                        escritor.WriteAttributeString("Name", datosTecla.Nombre);
                        if (datosTecla.Control)
                            escritor.WriteAttributeString("Control", "true");
                        if (datosTecla.Mayusculas)
                            escritor.WriteAttributeString("Shift", "true");
                        if (datosTecla.Alt)
                            escritor.WriteAttributeString("Menu", "true");

                        escritor.WriteString(partes[1]);
                        escritor.WriteEndElement();

y por último, el enlace al código fuente del programa en el repositorio de código fuente de Digi21 en GitHub: https://github.com/digi21/TeclasMnuATeclasMnuXml