Archivo

Archivo para la categoría ‘Código’

GLibWMI Versión 1.3 (beta)

lunes, 11 de enero de 2010 Sin comentarios
Share Button

Acabo de empaquetar la versión 1.3 (beta) de la librería de componentes GLibWMI, basados en la WMI de Windows.

Básicamente he añadido nuevos componentes y he corregido algunos errores que incluía la demo general. Además he testado la librería en Delphi 2009 sin ningun problema a la hora de compilar. Doy por supesto que en todas las intermedias entre D7 y D2009 fucionará sin problemas.

Los componentes nuevos son:

  • CProcessInfo:  Información acerca de los procesos que hay ejecutándose en el sistema..
  • CServiceInfo:   Información detalleda de los servicios que hay instalados en el sistema..
  • CDesktopMonitorInfo:   Información detallada sobre el monitor o dispositivo de visualización que hay en el sistema.
  • CComputerSystemInfo:   Información acerca del sistema en General.
  • CStartupCommandInfo:    Información acerca de los procesos que se ejecutan automáticamente cuando el usuario hace el Login en el sistema.

<Ver más detalles>

Componentes Generales GLib

viernes, 8 de enero de 2010 32 comentarios
Share Button

GLib es una librería/biblioteca de componentes de uso general

Son de uso gratuito y de licencia libre.

Puedes usarlos libremente y descargar el código fuente para estudiarlo o modificarlo; Puedes utilizarlos en cualquier tipo de aplicaciones; Gratuías o comerciales. Sólo te pido que si haces cambios en el código (mejoras, correcciones,…) me lo comuniques para actualizar los componentes, si son de interés para mi y para otras personas.

Puedes descargar los componentes de forma individual o todos juntos en un package, dependiendo de lo que te interese. Para ello selecciona los links individuales o para descargar el paquete completo el último que hace referencia a la Librería GLib.

 

HISTORIAL (v. 1.3)

A parte de algunos pequeños bugs se han compilado las librerías sobre la versión XE de Delphi sin presentar ningun problema. Se añadi el package para la versión XE.

Problemas resueltos:

  (ClogDisk)
* Permitir grabación continua de ficheros (Accumulative).
* (CLogDisk) Propiedades para permitir o no grabar pie y cabecera.

    (CustomizeGrid)
* Corregido problema al acceder a los títulos de las columnas.
* Corregido error de pintado de estilos y filas alternativas al recorrer el DBGrid.
* Puede pintar de forma automática las columnas de tipo Memo y Boolean como texto y checkbox respectivamente.

 (EditInsideHelp)
* Changed InsideHelpColor by InsideHelpFont for more customization possibilities.
(thanks Ariel Martín  from Cuba)

(DiskInfo)
* Corrected bug on select letter (Thanks Vincenzo).
* (v. 1.2) Corregido un error al obtener Número de Serie de varios discos instalados. (Thakns Peter Aschbacher)
* Añadidas propiedades para seleccionar los controles que se quieren almacenar… (SelectTaggedControls y SelectTag)

_________________________________________
Componente TLogDisk.
(version 1.0)

El componente TLogDisk sirve para facilitar el trabajo a un programador que necesite añadir un Log a sus programas. Basta con “soltar?? el componente en un formulario del programa y activarlo. Automáticamente el componente crea el fichero de Log, almacena datos de la aplicación (cabecera) y ofrece al programador métodos/rutinas para añadir datos de diferentes tipos al Log.

_________________________________________
Componente TEditInsideHelp.
(version 1.0)

Este componente permite definir un texto de ayuda en la parte interna del control de edición (TEdit). El texto desaparace cuando el control contiene algun texto que el usuario ha introducido. Se pueden definir el color que deseamos para el texto de la ayuda de forma independiente al color definido en la fuente (propiedad Font) del componente.

 


_________________________________________

Componente TPanelGrid.
(version 1.0)

Este componente (en éste caso derivado de un TPanel) muestra cómo añadir a un componente una Cuadrícula o Grid similar a la que aparece en los formularios cuando los estamos diseñando desde el IDE de Delphi.
Se puede configurar en el componente el color y el espaciado entre puntos de la cuadrícula.
Basta con soltarlo en el formulario y activarlo.

 


_________________________________________
Componente TDiskInfo.
(version 1.2)

Este componente permite para recuperar información diversa sobre los Discos existentes en el de sistema; Discos duros, diskettes, discos de red, discos RAM… Colóquelo en un formulario y defina la letra del disco.

Puede recuperar la información sobre:

  • Volumem; Etiqueta, número…
  • Serial number (no número de volumen)
  • Espacio; Libre, total, ocupado.
  • Icono del suistema
  • Nombre en el Explorer y descripción
  • Tipo de disco
  • Sistema de ficheros
  • Clusters, Sectores,…


_________________________________________
Componente TSortListBox.
(version 1.0)

Componente derivado de un TListBox que añade la propiedad de definir ordenaciones para los diferentes elementos de la lista; Junto a cada elemento se muestra una señal para indicar la ordenación. Posee una propiedad de tipo array para consultar el estado de cada item de la lista


_________________________________________
Componente TSaveComps.
(version 1.4)

Permite guardar la posicion y tamaño de todos los componentes que se encuentran en el formulario. Utiliza para ello un fichero INI.
Basta con colocar el componente en el formulario y activarlo; Cuando la aplicación se cierra graba la posición/tamaño y al volver a ejecutarla los recupera de forma automática.


_________________________________________
Componente TSelectOnRuntime.
(version 1.5)

Permite seleccionar componentes visuales (en Runtime) que haya en un form de forma visual como se hace con las imágenes en los programas de diseño o con los controles en el IDE de Delphi.
Además se pueden mover y redimensionar los controles seleccionados. Basta con soltar el control en el formulario, asignarle el control que se desea seleccionar/mover/redimensionar y activarlo.

_________________________________________
Componente TKeysOnForm.

(version 1.0)

Permite gestionar de forma sencilla (sin código) algunas de las combinaciones de teclas más utilizadas en los formularios. Basta con soltar el componente sobre el formulario y activar las propiedades deseadas segun el comportamiento que queramos.

  • ENTER para cambiar de campo.
  • ESC para cerrar el formulario
  • Avanzar al siguiente control
  • Retrasar al anterior control
  • Teclas de función


_________________________________________
Componente TCustomizeGrid.
(version 1.3)

Permite modificar algunos aspectos en la visualización de un Grid estandard.
No deriva del DBGrid, si no que funciona como complemento al componente estandard de Delphi. (En construcción…)
La propiedad Flat permite modificar el aspecto del DBGrid.
Implementa métodos para mejorar el pintado en el Grid de las celdas de tipo Booleano y Memo;
Sustituye el texto por un checkbox y (MEMO) que aparece en los campos Memo por el texto del campo.

Además provee eventos para modificar colores del DBGrid:

  • OnPaintCell: Para pintar xeldas de un determinado color.
  • OnPaintCellExt: BIS del anterior con más parámetros.
  • OnPaintColumn: Permite pintar una columna de color.
  • OnPaintRow: Permite pintar una file de color.
  • OnPaintCellImage: Permite pintar imágenes en una celda.
  • OnChangeTitleCell: Modificar las celdas de título.


_________________________________________
Componente TInactivityApp.
(version 1.0)

Este componente permite detectar en la aplicación donde se utiliza la inactividad de teclado y de ratón pasado un determinado tiempo (de forma similar a cómo se activa el salvapantallas del sistema).
El tiempo que se quiere detectar de inactividad es configurable por el usuario en minutos y segundos. Basta con activar el componente, configurar el tiempo de inactividad; Pasado este tiempo de inactividad «saltará» un evento de aviso.



_________________________________________
Librería completa GLib.
(version 1.3)

Actualizada  09/09/2011

Incluye en un único paquete todos los componentes anteriores.

Inventario de software instalado (WMI)

martes, 24 de noviembre de 2009 6 comentarios
Share Button

Siguiendo con los ejempos y ahondando en las posibilidades de WMI (Windows Management Instrumentation), a raiz de este hilo en los foros del ClubDelphi, referente al software instalado en nuestro ordenador, he probado a obtener la lista de programas instalados utilizando la WMI.

Para ello podemos utilizar la clase Win32_Product.
Si accedemos a su descripción en MSDN, obtenemos la siguiente descripción de la clase:

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
class Win32_Product : CIM_Product
{
  uint16   AssignmentType;
  string   Caption;
  string   Description;
  string   IdentifyingNumber;
  string   InstallDate;
  datetime InstallDate2;
  string   InstallLocation;
  sint16   InstallState;
  string   HelpLink;
  string   HelpTelephone;
  string   InstallSource;
  string   Language;
  string   LocalPackage;
  string   Name;
  string   PackageCache;
  string   PackageCode;
  string   PackageName;
  string   ProductID;
  string   RegOwner;
  string   RegCompany;
  string   SKUNumber;
  string   Transforms;
  string   URLInfoAbout;
  string   URLUpdateInfo;
  string   Vendor;
  uint32   WordCount;
  string   Version;
};

Podemos disponer así de toda la información, referente a cada uno de los programas/aplicaciones instalados en nuestro equipo (*NOTA*).

Para ello, lo primero que debemos hacer es Importar a Delphi la librería “Microsoft WMI Scripting v1.X Library (Version 1.X)“, si no lo hemos hecho ya.
En la Introducción sobre WMI, se explica un poco más detalladamente.

Una vez importada, lo siguiente (dentro de nuestro ejemplo) es conectar con nuestro proveedor (en este caso nuestra máquina local):

1
2
3
4
5
6
    // Create the Location object
    Locator := CoSWbemLocator.Create();
    // Connect to the WMI service, with the root\cimv2 namespace
    aServices := Locator.ConnectServer(STR_EMPTY, {Server}
        STR_CIM2_ROOT, {user}STR_EMPTY, {password}STR_EMPTY,
        STR_EMPTY,STR_EMPTY, 0, nil);

A continuación, si la conexión ha sido correcta, realizamos la consulta sobre la clase Win32_Product, que nos dará la información que necesitamos.

1
2
3
// realizar la consulta
ObjSet := Services.ExecQuery('SELECT * FROM Win32_Product',
 'WQL', wbemFlagReturnImmediately and wbemFlagForwardOnly , nil);

A partir de ahí basta con recorrer los elementos obtenidos y e nuestro caso formatear algunas propiedades para mostrarlas (Caption, InstallDate, Vendor y Version), aunque todas las demás están igualmente a disponsición del programador.

Recordad de colocar en el USES las dos units comentadas antes.

Se puede descargar el código de ejemplo desde aquí y el ejecutable compilado desde aquí.

<Ejemplo_sources>

<Ejemplo_Ejecutable>

(*NOTA*): Recordemos (link), que una de las características de WMI es que permite «Administración remota», con lo que si tenemos los suficientes permisos, este código también puede servir para inventariar otras máquinas.

WMI – Introducción

martes, 24 de noviembre de 2009 4 comentarios
Share Button

No hace mucho me cruce con esta “palabrota” este concepto: WMI.

A priori parece sólo eso, una “palabrota” más, de las muchas que nos encontramos en nuestro día a día “informático”. Pero rascando, rascando ha aparecido una perla oculta bajo una capa de polvo.

WMI son las iniciales de “Windows Management Instrumentation”. Se me hace complicado explicar en pocas palabras qué es, pero si tuviera que hacerlo, diría que es algo así como “Una puerta de acceso a la Administración de Sistemas Windows” ( ;-D Windows Management Instrumentation).

Junto a WMI aparecen dos “palabrotas” dos conceptos más que nos ayudan a saber de dónde viene.

  • WBEM (Web-Based Enterprise Management )
  • CMI (Common Model Information).

Si las juntamos todas nos queda que, WMI es una implementación que Microsoft ha hecho para Windows, de un estandard llamado WBEM que sirve para la administración de sistemas vía web y que está basado en CIM, que vienen a ser unas clases que nos dan acceso a diferente información del un equipo.

(Traducción al idioma Terrícola):

“A través de WMI yo puedo administrar un equipo basado en Windows, local o remoto, independientemente de la versión del sistema, utilizando las clases que me provee CIM.”

Y esto visto desde el punto de vista de un programador tiene muy buena pinta.

Este podría ser un gráfico sencillo de su estructura.

Dicho esto, yo me pregunto, ¿Qué tiene de bueno WMI y qué puede hacer por mi? (en el terreno más práctico)

  • Utilizando WMI podemos consultar información sobre nuestro equipo. Desde las aplicaciones instaladas, a la información de la BIOS, discos duros instalados, particiones creadas, Antivirus instalado si lo hay, nivel de carga de la batería (si conviene), procesos ejecutándose, acceso a los servicios instalados, acceso a las tareas programadas, y la lista sigue y sigue…
  • Cuando hablamos de administración significa que no sólo podemos consultar estos parámetros, sino también modificarlos en muchos casos.
  • Administración remota. Significa que lo dicho anteriormente se aplica también a administración remota. Es decir, no sólo podemos hacerlo en nuestro equipo, sino en el resto de equipos de la red. WMI está presente en sistemas Windows 2000 con SP2 en adelante. Para los anteriores (95, 98 y NT 4.0) se puede descargar un SDK para instalarlo (link).
  • Es extensible. Microsoft añade nuevas clases a cada versión de Windows. Además se pueden crear nuevos proveedores de WMI que amplíen funcionalidades.
  • Acceso desde la línea de comandos. Existe una herramienta para trabajar desde la línea de comandos con WMI (link).

Utilizándola podemos por ejemplo obtener los procesos ejecutándose si desde una ventana de MS-DOS escribimos:

1
2
3
4
WMIC PROCESS
WMIC PROCESS LIST BRIEF (mejora la visualización)
WMIC /output:”c:\procesos.txt” PROCESS LIST BRIEF 
(para obtener salida a un fichero)

Lenguaje de consulta similar a SQL llamado WQL (WMI Query Language). Utilizándolo podemos desde una ventana MS-DOS ejecutar comandos como estos:

1
2
3
4
5
WMIC PRINTER WHERE Default=”TRUE”
(obtener info sobre la impresora predeterminada)
WMIC PRINTER WHERE Default=”TRUE” LIST FULL
WMIC PRINTER WHERE default="TRUE" GET DriverName,PortName,PrintProcessor
(para obtener determinados datos de la impresora predeterminada)

Aquí se pueden ver unos cuantos ejemplos más a parte de la extensa documentación existente en las páginas de Microsoft.

Una vez hecha esta introducción (muy genérica) sobre WMI, me gustaría centrarme en las aplicaciones que pueden acceder a ella. Microsoft proporciona las API de WMI para scripts, aplicaciones Visual Basic, aplicaciones C++ y .NET Framework. Eso no quiere decir que no se pueda acceder desde casi cualquier lenguaje. En mi caso me voy a centrar en el acceso a ella desde Delphi.

Para acceder desde Delphi a WMI lo primero que necesitamos en Importar la librería desde el menú de Project/Import Type Library (pasos aquí):

“Microsoft WMI Scripting v1.X Library (Version 1.X)“

Una vez importada la librería tendremos la unit WbemScripting_TLB.pas generada y lista para utilizar. En nuestros programas deberemos incluir en la clausula USES, esta unit junto con la de ActiveX.

Antes de acabar esta entrada (espero poder publicar más, ya que el tema me parece muy interesante) podemos ver cómo utilizar la WMI para acceder a los datos del disco duro. En este caso, para simplificar vamos a acceder a los datos del primer disco (DiskDrive) existente en el sistema. Para ello se utiliza la clase: Win32_DiskDrive

http://msdn.microsoft.com/en-us/library/aa394132%28VS.85%29.aspx

Basta con crear un nuevo proyecto en Delphi, añadir un memo y un botón y colocar el siguiente código (no explico más, ya que incluye los comentarios):

Recordad de colocar en el USES las dos units comentadas antes.

Se puede descargar el código de ejemplo desde aquí y el ejecutable compilado desde aquí.

<WMI_Ejemplo1_sources>

<WMI_Ejemplo1_Binary>

Google Maps en Delphi – II

lunes, 29 de junio de 2009 37 comentarios
Share Button

En la última entrada acerca de la API de Google Maps, vimos cómo mostrar un Mapa utilizando la API en un programa Delphi, cómo centrarlo en una posición predefinida y utilizando un Zoom predeterminado.

Además como seleccionar entre los diferentes controles que podemos añadir al mapa (Zoom, Vista general, tipo de mapa…).

También cómo colocar una marca en una ubicación y cómo generar una ventana con información asociada a esa marca (NOTA1).

NOTA1: De forma similar se pueden colocar otros elementos sobre el mapa, como:

  • Líneas, polilíneas y polígonos.
  • Marcas con iconos personalizados.
  • Rutas

Una vez visto cómo mostrar el mapa, lo que nos queda es ver cómo podemos, desde nuestro programa Delphi, interactuar con él; Es decir, que el usuario pueda modificar determinadas características del mapa que tiene en pantalla, y nosotros podamos recuperar esos cambios, para utilizarlos en nuestro programa.

Vamos a continuar con el ejemplo visto en las entradas anteriores; Mostraremos al usuario un Mapa ubicado en una determinada posición. El usuario debe poder «reubicar» la vista del mapa y modificar el Zoom con que está visualizando el mapa, y esos son los valores que obtendremos para posteriormente almacenarlos y actualizarlos en nuestro programa.

  • Coordenada de Longitud
  • Coordenada de Latitud
  • Zoom actual del mapa

La forma de conseguirlo, es añadir a la página web el código necesario para capturar eventos que se produzcan en el mapa. Incluiremos controles de edición, donde se almacenan la longitud/latuitud y Zoom, que después recuperaremos desde el programa Delphi.

GEvent.addListener(map, "click", function (overlay,point)
GEvent.addListener(map, "zoomend", function (oldLevel, newLevel)
GEvent.addListener(map, "mousemove", function(latlng)

Aunque uno no esté muy familiarizado con el tema (yo mismo no lo estoy mucho  ;-D ), no hacen falta muchas explicaciones para comprender los eventos; «Capturaremos» en OnClick, OnZoomEnd y OnMouseMove sobre el mapa. Aquí se puede acceder a la lista de eventos, métodos y propiedades de la clase Gmap.

En el caso del evento OnClick, por ejemplo, utilizaremos un código como este:

GEvent.addListener(map, "click", function (overlay,point){
if (point){
document.posicion.x.value=point.x
document.posicion.y.value=point.y
document.posicion.z.value=map.getZoom()
TipoMapa = map.getCurrentMapType().getName()
document.posicion.t.value=TipoMapa
}

Obtenemos información del punto actual (utilizando un parámetro) y el Zoom actual y el tipo de Mapa utilizando métodos de la clase GMap. Todos ellos se almacenan (como hemos comentado antes) en componentes de tipo Text, que nos sirven como «paso intermedio» para luego capturar esos valores de la página Web desde nuestro programa.

Como resultado final, os dejo el ejemplo que se adjunta con esta entrada. En él he incluído/integrado la parte de Geocodificación (visto en las entradas I y II), y el código y modificaciones necesarias para recuperar posición, Zoom y tipo de Mapa (este incluído a última hora) que el usuario selecciona en un Mapa.

Información capturada

La información de los lugares puede ser guardada y recuperada de un fichero de texto; La estructura es bastante simple y no hace falta mayor explicación. Se almacena en el mismo directorio de la aplicación y recibe el nombre de «Lugares.txt».

Recuperar y Guardar ubicaciones

La información que podemos capturar del Mapa (utilizando la clase GMap) y de otros elementos que estén incluíds en el mapa (imágenes, líneas, marcas,…) es muy extensa y está detallada en las referencias de la API de Google Maps.

Personalmente, creo que las posibilidades de ampliación son muy grandes y bastantes más sencillas de lo que a priori puede parecer.

Se puede descargar el ejemplo completo desde aquí.
<DESCARGAR EJEMPLO>

Espero que estas entradas hayan sido de utilidad. Como siempre cualquier comentario, corrección, sugerencia,… es bienvenida. ;-D

Un saludo.

ACTUALIZACIÓN (10 Febrero 2012): Dado el cambio de política de Google, ahora es necesario (obligatorio) colocar la key que se proporciona desde Google para poder utilizar la API. Es necesario modificar el fichero _mapa.txt del recurso y  recompilarlo utilizando RC.CMD.

 

Cargar datos de un TXT a un TDataset (utilizando ADO) – Parte 2

viernes, 22 de mayo de 2009 19 comentarios
Share Button

Continuando con esta entrada (parte 1), nos queda ver como hacer algo similar, pero con un archivo de texto cuyos datos están separador utilizando algun caracter especial (TAB, coma, punto y coma,…)

Por defecto, para la lectura de un fichero de texto medianto ADO (Jet 4.0) se utiliza la información que hay en el registro de windows, que se considera la configuración por defecto. Esta configuración se encuentra en la clave:
‘\SOFTWARE\Microsoft\Jet\4.0\Engines\Text’

Dentro de HKEY_LOCAL_MACHINE y en el valor Format.

De todas formas, para tener un mayor control sobre el procesos para acceder a los datos del fichero de texto, es recomentable (altamente recomendable diría yo) crear un fichero de esquema.
El fichero de esquema siempre tienen el nombre schema.ini y se encuentra en la misma carperta del origen de datos. En el fichero de esquema se definen:

  • El formato del archivo.
  • El nombre, la longitud y el tipo de cada campo (columnas).
  • El juego de caractreres utilizado en el archivo de datos.
  • Conversiones especiales para los tipos de datos.

Si tuviéramos un archivo similar a este (aunque aquí he utilizado para el ejemplo el separador ‘‘ que no parace muy adecuado):

Sierra eléctrica-1-250
Machete-5-2.70
Detergente-1-10
Delantal-2-7.25
Afilador-3-5
Cortacesped-6-95
Televisor plasma-2-200
Caja clavos-4-12
Ordenador-1-300
Caja lápices-2-11
Paquete folios-1-10

En nuestro archivo schema.ini debemos añadir lo siguiente para conseguir un acceso correcto a los datos:

  • Format=Delimited(-); Para definir nuestro separador de campos
  • ColNameHeader=False;  Puesto que no están definidas dentro del archivo de texto los títulos de las columnas.
  • A continuación nombres y tipos de las columnas.
  • CharacterSet=ANSI; Para definir la codificación del texto.
  • MaxScanRows=0; Define cuantas líneas escanea el motor para determinar el tipo de datos de cada columna. 0 para todas.

Finalmente nuestro archivo de esquema quedará de compleatado de la siguiente manera:

 [Datos.txt]
Format=Delimited(-)
ColNameHeader=False
Col1=Producto char
Col2=Cantidad Integer 
Col3="Precio Total" currency 
MaxScanRows=0
CharacterSet=ANSI

El ejemplo completo para acceder a los datos de un TXT utilizando las opciones del Registro de Windows, se pueden descargar desde aquí.
<Descargar ejemplo>

El ejemplo completo para acceder a los datos de un TXT utilizando las opciones de un archivo de esquema schema.ini, se pueden descargar desde aquí.
<Descargar ejemplo>

Cargar datos de un TXT a un TDataset (utilizando ADO)

viernes, 22 de mayo de 2009 Sin comentarios
Share Button

Una de las muchas posibilidades que ADO provee para acceder a diferentes tipos de datos es la que podemos utilizar para acceder a datos de un fichero de Texto, siempre que estos estén mínimamente organizados.

Básicamente trabajamos con dos tipos de ficheros de texto:

  • Los que los campos son de ancho fijo y por lo tanto no hace falta separador.
  • Aquellos en los que los datos utilizan un separador de campos. Ya sea «punto y coma», «coma» o cualquier otro.

Nuestro primer archivo de datos es como este:

____________________________________________
202548777102120545041
ESTO 1546564LOOTRO
202548345134534545451 EST2 1542344LOOTRO
202548777102120557087 EST3 1546789LOOTRO
752323654273654726534 EST4 2343344UNOMAS
112543456329324792347 EST5 5521973MASAUN
_____________________________________________

He marcado en el primer registro los campos de diferente color para que se diferencien cláramente (4 campos).

Para un archivo de ancho fijo podemos configurar la conexión (TADOConnection) de la siguiente forma:

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\;
Extended Properties="text;HDR=Yes;FMT=Fixed";
Persist Security Info=False

Configuramos el proveedor como Jet 4.0, en este caso en directorio de la Base de Datois está definido como .\ (el mismo de la aplicación) y en las propiedades extendidas es donde realmente se define el tipo de archivo y la organización de los datos (Text y Fixed).

Sólo nos queda definir en el mismo directorio el fichero schema.ini donde detallaremos la estructura de las columnas de nuestro fichero. Éste sería un fichero correcto para este caso:

[datos.txt]
Format=FixedLength
ColNameHeader=False
Col1=ID char Width 21
Col2=Nombre char Width 6
Col3=Valor Integer Width 7
Col4=Descripción char Width 6
CharacterSet=ANSI

De esta forma podemos acceder a los datos del fichero mediante un TADOTable y trabajar con ellos utilizando todas las posibilidades que nos brinde este componente.

El ejemplo completo con el código fuente, el fichero de datos y el fichero de esquema se puede descargar desde aquí.

<Descargar ejemplo>

Continuación (parte2); Ficheros con datos delimitados por un separador.

(Google Maps – API) Codificación Geográfica – II

jueves, 7 de mayo de 2009 4 comentarios
Share Button

Continuando con la entrada (Google Maps – API) Codificación Geográfica – I, vamos a ver cómo obtener más datos de este servicio de Google Maps.

Si habéis revisado el ejemplo sencillo que vimos en la primera entrada, os habréis fijado que hay un parámetro al final de la dirección del que no hemos hablado. Se trata del formato de salida para los datos. Los formatos que acepta el API de Google Maps son los siguientes:

  • XML: Formato extendido en XML/KLM.
  • KLM: Formato extendido en KL; Se diferencia del anterior en los tipos MIME.
  • JSON: La salida de este formato se guarda en formato de objeto JSON (Javascript Object Notation).
  • CSV: Formato comprimido separado por comas (el que se utilizó en el ejemplo).

Para utilizar un formato diferente, basta con añadir al final de la línea de petición el formato deseado:

&amp;output=csv    &amp;output=klm     &amp;output=xml     &amp;output=json

Retomando el tema inicial, vamos a utilizar uno de los formatos extendidos para obtener más información de una dirección dada, además de las coordenadas de Latitud y Longitud.
Si realizamos una petición HTTP utilizando el formato json obtenemos una respuesta como esta por parte del servidor:

{
  "name": "Barcelona,spain",
  "Status": {
    "code": 200,
    "request": "geocode"
  },
  "Placemark": [ {
    "id": "p1",
    "address": "Barcelona, España",
    "AddressDetails":
       {"Country":
        {"CountryNameCode": "ES","CountryName": "España","AdministrativeArea":
          {"AdministrativeAreaName": "CT","SubAdministrativeArea":
            {"SubAdministrativeAreaName": "Barcelona","Locality":
              {"LocalityName": "Barcelona"}}}},"Accuracy": 4},
    "ExtendedData": {
      "LatLonBox": {
        "north": 41.4682658,
        "south": 41.3199988,
        "east": 2.2261223,
        "west": 2.0524766
      }
    },
    "Point": {
      "coordinates": [ 2.1699187, 41.3879170, 0 ]
    }
  } ]
}

Utilizando un sencillo «parser» con este resultado podemos extraer la información para poder utilizarla en nuestros programas.

El ejempo que se ve en la imagen puede descargarse desde aquí.

He creado además una clase derivada de TThread que permite acceder a la imagen. Me ha parecido que en futuros usos me va a ser más útil así, aunque realmente todavía no la he probado en un entorno «multithread».

TThreadGeoCode = class(TThread)
  private
    FDireccion: string;
    FAllText: TStrings;
    FGeoStatusCode: Integer;
    FGeoAddress: string;
    FGeoCountryCode: string;
    FGeoCountryName: string;
    FGeoAdminArea: string;
    FGeoAddressLine: string;
    FGeoLocalityName: string;
    FGeoPostalCode: string;
    FGeoAccuracy: integer;
    FGeoLatitud: string;
    FGeoLongitud: string;

    procedure _ExtractResult();
    function _StatusCodeToStr(ACode:Integer):string;
    function _AccuracyToStr(ACode:integer):string;
  protected
    procedure Execute; override;
  public
    destructor Destroy; override;
    constructor Create(ADireccion:string;
                       ThreadPriority:TThreadPriority=tpNormal);

    // Direccion a buscar
    property Direccion:string read FDireccion write FDireccion;
    // Salida
    property AllText:TStrings read FAllText write FAllText;
    // propiedades de posición
    property GeoStatusCode:Integer read FGeoStatusCode write FGeoStatusCode;
    property GeoAddress:string read FGeoAddress write FGeoAddress;
    property GeoCountryName:string read FGeoCountryName write FGeoCountryName;
    property GeoCountryCode:string read FGeoCountryCode write FGeoCountryCode;
    property GeoAdminArea:string read FGeoAdminArea write FGeoAdminArea;
    property GeoAddressLine:string read FGeoAddressLine write FGeoAddressLine;
    property GeoLocalityName:string read FGeoLocalityName
       write FGeoLocalityName;
    property GeoPostalCode:string read FGeoPostalCode write FGeoPostalCode;
    property GeoAccuracy:integer read FGeoAccuracy write FGeoAccuracy;
    property GeoLatitud:string read FGeoLatitud write FGeoLatitud;
    property GeoLongitud:string read FGeoLongitud write FGeoLongitud;

  published

  end;

Y aun podemos extraer más, ya que si la dirección es ambigua (pero correcta), google puede devolver más de un resultado. De esta forma, con una dirección tipo:

Obtendremos por parte de Google la lista de direcciones correcta que pueden corresponder a esta calle. Cada una de ellas presenta la estructura mostrada anteriormente variando el identificador (id):

  "Placemark": [ {
    "id": "p1",
...
    "id": "p2",
...

Sucesivamente para las distintas direcciones correctas y posibles para esa combinación: Alava, Burgos, Ciudad Real, Cuenca,…

A partir de aquí, no costaría mucho para modificar el ejemplo anterior de forma que se puedan extraer y mostrar los datos, no sólo de la primera dirección, sino de todas las devueltas en la petición.

Hasta aquí estos dos artículos (I y II), que sirven a modo de introducción y prefacio del próximo que estoy preparando.

Está claro, que la idea final y el objetivo que persigo es poder integrar en un programa Delphi las características de Google Maps. El problema actual es, que en nuestras Base de Datos/programas normalmente no tenemos codificadas nuestras direcciones con Latitud/Longitud, así aque para llegar a nueastro objetivo antes tenemos que conseguir estos dos parámetros. Ahí es donde nos és útil el concepto de «Codificación geográfica».

Una vez que tenemos Latitud y Longitud para nuestra dirección, ya podemos avanzar un paso más…