Al final de la página también tenéis la lista de las publicadas hasta ahora, con las opciones para acceder a ellas y votar.
Básicamente, se trata de hacer una aplicación que utilice la API de la NASA y que muestre características de las últimas versiones de RAD Studio. Cualquier plataforma disponible y con el único límite de la imaginación.
Os muestro un vídeo de la mía en funcionamiento (Windows + Android)
Se puede descargar el binario para windows desde el repositorio de github. El código completo de la aplicación lo publicaré en el blog y en el repositorio, una vez que acabe la competición
Sólo me queda esperar que os guste y si es así que la votéis.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Después de las dos entradas sobre Codificacióin Geográfica (*), toca entrar de lleno en la Visualización e Integración de Google Maps en nuestro programa, que por otra parte era el objetivo inicial de esta serie de entradas. La Codificación Geográfica (obtención de Latitud y Loingitud a partir de una dirección postal) era un «escollo» a salvar en nuestro camino, hasta nuestro verdadero objetivo.
(*) Lo normal es tener en nuestros programas/aplicaciones una serie de direcciones postales o direcciones de correo que deseamos mostrar o señalar en un Mapa. Para utilizar esas direccones con la API de Google Maps necesitamos obtener las coordenadas de Latitud y Longitud apropiadas. Para ello ya vimos aquí (Codificación Geográfica – I) y aquí (Codificación Geográfica – II) cómo Google provee métodos para obtener las coordenadas de posicionamiento a partir de direcciones postales.
La idea para conseguir la integración es sencilla. Utilizar un componente TWebBrowser para mostrar una página HTML. Desde Delphi debemos «modificar» esa página para que muestre lo que nosotros deseemos.
Utilizando una sencilla página HTML con un Script, podemos visualizar el mapa correspondiente a coordenadas de Latitud y Longitud. Con un componente TWebBrowser podemos visualizar esa página dentro de una aplicación delphi.
La página en sí sólo contiene el Script para Visualizar un Mapa.
Dentro del Script vemos cómo se crea un elemento de tipo «map»:
map =new GMap2(document.getElementById("map"));
map = new GMap2(document.getElementById("map"));
Se añaden los controles que queremos visualizar en el mapa; En este caso, la selección para el tipo de mapa y control de zoom y posición grande.
// Controles del mapa
map.addControl(new GMapTypeControl());
map.addControl(new GLargeMapControl());
// Controles del mapa
map.addControl(new GMapTypeControl());
map.addControl(new GLargeMapControl());
El tipo de mapa que queremos que inicialmente aparezca (Mapa, visión por satélite o lo que Google llama híbrido).
// Tipo de mapa
map.setMapType(G_NORMAL_MAP);
// Tipo de mapa
map.setMapType(G_NORMAL_MAP);
Y por último colocamos la posición (latitud y longitud) donde queremos que el mapa salga centrado.
Pero no acaban aquí (ni mucho menos) las posibilidades de Google Maps. Una de las opciones, que dentro de lo sencillo, es muy interesante, es la inclusión de marcas señalando puntos del mapa o incluso ventanas de información no es mucho más complejo.
Para añadir una nueva marca, basta con conocer el punto exacto donde queremos situarla y utilizar un objeto GMarker para mostrarla en el mapa. En cuanto a la ventana, de información, sólo necesitamos el código HTML necesario para crearla.
En este ejemplo la ventana tiene un código sencillo (texto, imagen y link) que se almacena en una variable.
Para mostrarla basta con que utilicemos en método OpenInfoWindowHtml (cuyo nombre es bastante descriptivo, por cierto ;-D ) de la siguiente forma:
// Visualización de la mrcavar point =new GLatLng(41.381655,2.122829);var marker =new GMarker(point);
marker.openInfoWindowHtml(html);
// Visualización de la mrca
var point = new GLatLng(41.381655,2.122829);
var marker = new GMarker(point);
marker.openInfoWindowHtml(html);
Hay más opciones y basta con echarle una vistazo a la API de Google Maps para conocerlas. Además hay muchos ejemplos de utilización que pueden servir para aclarar los conceptos y para ver más cláramente cómo se utilizan los diferentes elementos.
Todo lo visto hasta aquí, está puesto en práctica en un ejemplo Delphi.
Podéis descargar el código completo (incluye EXE -comprimido UPX-) desde aquí:
<Descargar Ejemplo>
Y aquí acabamos esta entrada, que no será la última. Me dejo para una segunda parte, algunos detalles finales, como interactuar con el mapa y obtener datos de él y fusionar los dos conceptos vistos hasta ahora.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
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:
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:
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».
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",
...
"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…
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Muestra como utilizar un BITMAP (en este caso extraído de un TImage) para modificar el cursor activo. Modificando un poco el Tip/Truco es fácil obtener la imagen de disco o desde un recurso.
Se utiliza la API CreateIconIndirect para generar el cursor que posteriormente se activará.
Se puede usar un color de fondo como transparente para obtener un cursos «opaco» o un segundo BITMAP para combinarlo con el primero y así obtener también efectos de transparencia en el cursor generado.
// Crear los bitmaps
BitmapMask := TBitmap.Create;
Bitmap := TBitmap.Create;// protecciontry// Cargar las imágenes
BitmapMask.Assign(Image2.Picture.Bitmap);
Bitmap.Assign(Image1.Picture.Bitmap);// Crear el icono del cursorwith iconInfo dobegin
fIcon :=false;
xHotspot :=(Bitmap.Widthdiv4);
yHotspot :=(Bitmap.Heightdiv3);
hbmMask := BitmapMask.Handle;
hbmColor := Bitmap.Handle;end;// Asignar el icono
Screen.Cursors[1]:= CreateIconIndirect(iconInfo);Self.Cursor:=1;finally// Liberar
BitmapMask.Free;
Bitmap.Free;end;
// Crear los bitmaps
BitmapMask := TBitmap.Create;
Bitmap := TBitmap.Create;
// proteccion
try
// Cargar las imágenes
BitmapMask.Assign(Image2.Picture.Bitmap);
Bitmap.Assign(Image1.Picture.Bitmap);
// Crear el icono del cursor
with iconInfo do begin
fIcon := false;
xHotspot := (Bitmap.Width div 4);
yHotspot := (Bitmap.Height div 3);
hbmMask := BitmapMask.Handle;
hbmColor := Bitmap.Handle;
end;
// Asignar el icono
Screen.Cursors[1] := CreateIconIndirect(iconInfo);
Self.Cursor := 1;
finally
// Liberar
BitmapMask.Free;
Bitmap.Free;
end;
Es ejemplo completo se puede descargar <AQUÍ>. Descargar.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
Éste ejemplo muestra cómo utilizar la API LockFile para detectar aplicaciones que están ejecutándose.
La situación es la siguiente: Una aplicación que se ejecuta en Red. Puede haber muchos puestos/estaciones que la están ejecutándo simultáneamente. Y nos interesa saber en cada momento qué puestos la ejecutan.
Las ventajas de éste método son su sencillez (poco código), fiabilidad (ya que al ser bloqueos controlados por el sistema operativo, si algunas estación «se cuelga» no hace falta ningun código de recuperación de identificadores, el sistema librera el bloqueo) y pocos recursos, ya que aunque bloqueemos mucha posiciones del fichero, el tamaño de éste simpre será de 0 bytes.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
var
i:Integer;
bContinue:BOOL;begin// Limpiar la lista
ListBox1.Items.Clear;// Recoge la lista de procesos en éste momento
aSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
aProcessEntry32.dwSize:=SizeOf(aProcessEntry32);// Acceder al primer proceso
bContinue := Process32First(aSnapshotHandle, aProcessEntry32);// Recorerr los procesos activoswhile(Integer(bContinue) <> 0)dobegin// Añadirlo a la lista
ListBox1.Items.Add(ExtractFileName(aProcessEntry32.szExeFile));// Hay más?
bContinue := Process32Next(aSnapshotHandle, aProcessEntry32);end;// cerrar la estructura
CloseHandle(aSnapshotHandle);
var
i: Integer;
bContinue: BOOL;
begin
// Limpiar la lista
ListBox1.Items.Clear;
// Recoge la lista de procesos en éste momento
aSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
aProcessEntry32.dwSize := SizeOf(aProcessEntry32);
// Acceder al primer proceso
bContinue := Process32First(aSnapshotHandle, aProcessEntry32);
// Recorerr los procesos activos
while (Integer(bContinue) <> 0) do begin
// Añadirlo a la lista
ListBox1.Items.Add(ExtractFileName(aProcessEntry32.szExeFile));
// Hay más?
bContinue := Process32Next(aSnapshotHandle, aProcessEntry32);
end;
// cerrar la estructura
CloseHandle(aSnapshotHandle);
Utilizando aProcessEntry32 se puede obtener más información de cada uno de los procesos, como:
* Identificador
* Nombre competo
* …
IntToHex(aProcessEntry32.th32ProcessID, 4)
aProcessEntry32.szExeFile
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
La idea de éste ejemplo llega a partir de una petición de obtener en un formulario unas barras de herramientas (toolbars) similares a las que aparecen en los Expertos para Delphi CnPack/cnWizard(muy buenos y gratuítos, por cierto).
En el caso de los CnPack, cuando aparece un formulario en el IDE de Delphi, aparecen varias barras de herramientas «flotantes» que se «pegan» literalmente al formulario.
De forma que si mueves el form, automáticamente se mueven las barras también. Una imagen descriptiva podría ser esta:
La forma de conseguirlo es utlizando el mensaje WM_WINDOWPOSCHANGING accesible desde los descencientes de TCustomForm.
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…
procedure TForm1.Image1MouseDown(Sender:TObject;
Button: TMouseButton;
Shift: TShiftState; X, Y:Integer);var
h: HMENU;
p:TPoint;begin// El componente que llama deriva de TControl?if(Sender is TControl)thenbegin// Posicion del click
p.X:= x;
p.Y:= y;// Calculamos las coordenadas relativas
P :=Self.ScreenToClient(TControl(Sender).ClientToScreen(P));// Mostrar el menú
h := GetSystemMenu(handle,false);
TrackPopupMenu(h, TPM_LEFTALIGN or TPM_LEFTBUTTON,
ClientOrigin.X+ p.X,
ClientOrigin.Y+ p.y,0, handle,nil);end;end;
procedure TForm1.Image1MouseDown(Sender: TObject;
Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
h: HMENU;
p:TPoint;
begin
// El componente que llama deriva de TControl?
if (Sender is TControl) then begin
// Posicion del click
p.X := x;
p.Y := y;
// Calculamos las coordenadas relativas
P := Self.ScreenToClient(TControl(Sender).ClientToScreen(P));
// Mostrar el menú
h := GetSystemMenu(handle, false);
TrackPopupMenu(h, TPM_LEFTALIGN or TPM_LEFTBUTTON,
ClientOrigin.X + p.X ,
ClientOrigin.Y + p.y, 0, handle, nil);
end;
end;
Embarcadero MVP.
Analista y Programador de Sistemas Informáticos.
Estudios de Informática (Ingeniería Técnica Superior) en la UPC (Universidad Politécnica de Barcelona).
Llevo utilizando Delphi desde su versión 3. Especialista en diseño de componentes, Bases de Datos, Frameworks de Persistencia, Integración Continua, Desarrollo móvil,…