Archivo

Archivo para la categoría ‘Ejemplos’

Perfiles de audio

Miércoles, 20 de Julio de 2016 Sin comentarios
Share Button

AudoioLevelsContinuando con la entrada anterior del blog, donde hablaba de cómo acceder a las propiedades de audio de un dispositivo Android; La idea de esta entrada es avanzar un poco más en el tema y generar una aplicación que nos permita gestionar varios perfiles de audio en nuestro dispositivo.

Una vez que vimos cómo acceder a la información del volumen actual, lo siguiente que nos interesa es poder almacenar diferentes perfiles, de forma que podamos seleccionar uno de los perfiles y configurar todos los parámetros de audio de forma rápida y automática.
Además debemos poder editar los perfiles existentes, borrar os que no nos interesen y tener la posibilidad de crear nuevos.

Contaremos con una serie de perfiles predefinidos, que podrían ser similares a estos:

  • Normal (Volúmenes al 100%)
  • Bajo (Volúmenes al 20%)
  • Sólo llamadas (todo al 0% excepto las llamadas)
  • Silencio total (Todo al 0%)

Leer más…

Share Button
Categories: Android, Delphi, Ejemplos Tags:

Cuestión de volumen…

Martes, 14 de Junio de 2016 4 comentarios
Share Button

volumen-audio-10054183Hace unos días se planteaba en el clubdelphi una cuestión acerca de la gestión de volúmenes en los dispositivos Android. Me llamó la atención porque días atrás me había planteado la cuestión de poder disponer de “perfiles de audio” en mi propio teléfono Android. Se trata de un Xiaomi con versión KitKat instalada y una ROM personalizada.

  • ¿Cómo podemos desde Delphi acceder a los volúmenes del dispositivo para las diferentes características (música, alarmas, llamadas,…)?
  • ¿Cómo podemos cambiarlos?

CONTROL DE VOLUMEN

Lo primero es saber cómo podemos acceder a esta información utilizando las clases de Android. Si revisamos la API de Android llegamos a la clase AudioManager,  que es la que se encarga de estos menesteres (y algunos más).
La descripción de la clase dice lo siguiente:

“AudioManager provides access to volume and ringer mode control.”

Leer más…

Share Button

Procesos y Threads (GLibWMI)

Lunes, 14 de Marzo de 2016 Sin comentarios
Share Button

threadA partir de esta consulta en el clubdelphi, sobre procesos y threads he decidido crear esta entrada; Para ello he compilado la librería GLibWMI en Delphi Seatle. La última versión que hay en la web está compilada y comprobada para Delphi XE7 y funciona sin problemas, así que era de esperar que en Seatle lo hiciera también sin cambios.

Yo mismo la estoy usando en algún proyecto antiguo en Delphi 6/7  y en algunas de las versiones más nuevas de Delphi XE.

Volviendo al tema que nos ocupa, en este caso nos interesa obtener información de los threads asociados a un determinado proceso que está corriendo en la máquina.

Para ello seguiremos los siguientes pasos:

  1. Acceder a la información del proceso
  2. Acceder a la información de los threads asociados a ese proceso.

Me voy a basar en la librería GLibWMI, aunque se puede hacer lo mismo utilizando código, sino deseamos instalar librerías de componentes adicionales.

Dentro de los componentes de GLibWMI, hay algunos que ya nos permiten acceder a clases “destacadas” o “habituales”. Entre ellos se encuentra ProcessInfo, por ejemplo, que nos da información  de los procesos ejecutandose (lo usaremos para el primer paso), pero WMI tiene muchas clases más.

Para acceder a cualquier otra clase o a datos particulares de una concreta, hay un componente llamado WMISQL, que nos permite lanzar “sentencias SQL” (algo parecido) sobre clases de WMI. Este componente es el que nos permitirá acceder a la información de los Threads (para los que no tenemos componente específico).

INFORMACIÓN DEL PROCESO

La información de los procesos funcionando en la máquina nos la da la clase Win32_Process.

Podemos utilizar el componente ProcessInfo. Basta con “soltar” el componente en un formulario y activarlo.

Este componente nos ofrece una lista de objetos TProcessProperties, la propiedad ObjectCount que nos da el número de elementos encontrados y la propiedad ObjectIndex que marca el elemento actual.

Podemos encontrar y obtener datos de un proceso con un código similar a este:

0
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
31
var
  str:string;
  i:integer;
  p:TProcessProperties; // para abreviar
begin
  // ini
  Memo1.Lines.Clear;
  // Activarlo
  ProcessInfo1.Active := True;
  // tenemos elementos?
  if (ProcessInfo1.ObjectsCount "MAYOR QUE" 0) then begin   //!!! Cambiar "MAYOR QUE" por el operador...
    // Buscamos un proceso concreto
    for i := 0 to (ProcessInfo1.ObjectsCount -1 ) do begin
      p := ProcessInfo1.ProcessProperties;
      // es el ibServer
      if (AnsiCompareText('ibserver.exe', p.Caption) = 0) then begin
        Memo1.Lines.Add('Nombre:        ' + p.Name);
        Memo1.Lines.Add('Caption:       ' + p.Caption);
        Memo1.Lines.Add('CommandLine:   ' + p.CommandLine);
        Memo1.Lines.Add('Path del EXE:  ' + p.ExecutablePath);
        Memo1.Lines.Add('Handle:        ' + p.Handle);
        Memo1.Lines.Add('Prioridad:     ' + IntToStr(p.Priority));
        Memo1.Lines.Add('Identificador: ' + IntToStr(p.ProcessId));
        Memo1.Lines.Add('Num. threads:  ' + IntToStr(p.ThreadCount));
 
        Break
      end;
      // Siguiente
      ProcessInfo1.ObjectIndex := ProcessInfo1.ObjectIndex + 1;
    end;
  end;
end;

 

Si lo ejecutamos obtendremos algo como esto:

En este caso, el componente ProcessInfo no es el más adecuado, ya que estamos obteniendo la información de TODOS los procesos, cuando sólo queremos acceder a uno sólo (ibserver, en el ejemplo anterior).

Para este caso, es más conveniente utilizar el componente WMISQL. Ya que podemos “minimizar” el tráfico de datos que solicitamos.

Para ello, este componente posee la propiedad SQL.

Aquí vemos las propiedades de este componente:

Añadiremos esta sentencia:

0
SELECT * FROM Win32_Process WHERE name = "ibserver.exe"

Si tan sólo queremos algunos datos, podemos afinar más la consulta para dejarla así:

0
1
SELECT Caption, CommandLine, ExecutablePath, Name, Handle, Handlecount, 
Priority, ProcessId, ThreadCount FROM Win32_Process WHERE name = "ibserver.exe"

 

Una vez activamos el componente, podemos acceder al resultado de la siguiente manera (vemos 2 opciones diferentes utilizando un TMemo -con la respuesta tal cual la da WMI- y un ValueListEditor -cuadro inferior-).

0
1
2
3
4
5
6
7
8
9
10
   // ini
  Memo1.Lines.Clear;
  // Activar
  WMISQL1.Active := True;
  // tenemos elementos?
  if (WMISQL1.ObjectsCount > 0) then begin
    // respuesta de WMI
    Memo1.Lines.Text := WMISQL1.AllProperties.Text;
    // Lista de propiedades
    ValueListEditor1.Strings.AddStrings(WMISQL1.Properties);
  end;

Como resultado obtendremos algo como esto:

Vemos que la propiedad ThreadCount nos devuelve 5.

 

INFORMACIÓN DE THREADS

Volviendo al tema original, una vez tenemos el identificador de nuestro proceso (en este caso el ProcessID=5848), necesitamos obtener los threads de este proceso y los datos asociados.

Para ver más información, podéis acceder a este link donde están todas las propiedades accesibles, la explicación de cada una de ellas y los diferentes valores que adoptan.

Vamos a utilizar en este caso otro componente WMISQL (o reaprovechar el mismo) y cambiaremos la consulta por esta otra:

0
SELECT * FROM Win32_Thread WHERE ProcessHandle=5848

 

Si activamos el componente en diseño (que se puede hacer) ya podemos ver que la propiedad ObjectCount es 5, por lo tanto ibserver tiene en este momento, 5 threads en marcha que dependen de él.

Con el siguiente código podemos obtener información de cada uno de ellos:

0
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
31
var
  i, j:integer;
  str:string;
  h, m, s:int64;
  p:TStrings;  // para abreviar
begin
  // ini
  Memo1.Lines.Clear;
  ValueListEditor1.Strings.Clear;
  // Activar
  WMISQL1.Active := True;
  // tenemos elementos?
  if (WMISQL1.ObjectsCount > 0) then begin
    // recorrer los threads y obtener datos
    for i := 0 to (WMISQL1.ObjectsCount - 1) do begin
      p := WMISQL1.Properties;
      j := StrToIntDef(p.Values['ElapsedTime'], 0); // milisegundos
      if (j > 0) then begin
      h := (j DIV 3600000);                        // horas
      m := (j - (h * 3600000)) DIV 60000;          // minutos
      s := (j MOD 60000) DIV 1000;                 // segundos
        Memo1.Lines.Add(Format('Tiempo ejec.:   %d:%d:%d', [h, m, s]));
      end;
      Memo1.Lines.Add('Handle:         ' + p.Values['Handle']);
      Memo1.Lines.Add('Prioridad:      ' + p.Values['Priority']);
      Memo1.Lines.Add('Prioridad base: ' + p.Values['PriorityBase']);
      Memo1.Lines.Add('Id. proceso:    ' + p.Values['ProcessHandle']);
      Memo1.Lines.Add('Estado:         ' + p.Values['ThreadState']);
      Memo1.Lines.Add('··········································');
    end;
  end;
end;

 

El resultado al mostrarlo por pantalla será algo similar a esto:

Con esto ya hemos acabado. La idea es mostrar la potencia de WMI y la sencillez con la que podemos utilizar esa información accediendo desde Delphi. Como os he dicho, podéis acceder a WMI sin necesidad de componentes, utilizando código delphi.

En entradas anteriores hemos comentado cómo hacerlo.

Un saludo y hasta la próxima.

Share Button
Categories: Delphi, Ejemplos, GLibWMI, WMI Tags: , ,

Internacionalizar aplicaciones con DKLang

Viernes, 10 de Enero de 2014 6 comentarios
Share Button

1326079952_297898748_1-Traductor-Espanol-Rumano-Rumano-Espanol-Coche Ya he hablado anteriormente de varios sistemas y paquetes de  componentes para internacionalizar aplicaciones en el blog. Por ejemplo, aquí y aquí. A raiz de un comentario de otro usuario, esta vez, por necesidad en este proyecto (IBCC) he decidido probar los componentes DKLang.

A primera vista me han sorprendido,  pues cuenta con versión para XE5 incluyendo aplicaciones móviles (Android/iPhone) así como para VCL y FMX. Más adelante hablaré de la versión para XE5 (versión 5), aunque en esta entrada y para este proyecto he usado la versión 3, que es la que soporta Delphi 6. 

Para la compilación del componente, al menos en esta versión (Delphi 6), hacen falta los componentes TNT para unicode. Gratuítos y con código fuente que podéis bajar desde esta misma web o desde internet sin problemas.

Imagen1138 La compilación e instalación de los packages se hace sin problemas. Basta con añadir un par de directorios al path para que encuentre los ficheros necesarios. Una vez instalado el package de diseño, ya me aparece el componente DKLanguageController en la pestaña de System.

He echado en falta algún manual sencillo para poder seguir a la hora de empezar con un proyecto nuevo. En la web y en la ayuda no hay nada que de una guía rápida de funcionamiento. Aun así, no lleva más de 10 minutos ver cómo se maneja el componente.

Todos los ejemplos que se incluyen están realizados utilizando los componentes TNT, aunque es fácil sustituirlos en el DFM por componentes estándar y el funcionamiento es correcto.

Leer más…

Share Button

Probando los sensores (Delphi XE5) – Parte I

Jueves, 3 de Octubre de 2013 5 comentarios
Share Button

La mayoría de dispositivos Android (teléfonos y tablets) actuales cuentan con un gran númeroimages de sensores, de diferentes tipos y de variada funcionalidad. Algunos más conocidos que otros y algunos más útiles que otros.

La idea de esta entrada y de las siguientes es mostrar cómo funcionan y cómo acceder a la información que nos proporcionan los diferentes sensores presentes.

Los sensores presentes en el dispositivo se gestionan utilizando la clase TSensorManager, que se encuentra en la unit System.Sensors. Además podemos encontrar otras units que completan las definiciones para cada una de las plataformas destino (System.IOS.Sensors, System.Win.Sensors, System.Mac.Sensors,…)

Leer más…

Share Button
Categories: Delphi, Ejemplos, Sensores, XE5 Tags: , , ,

Contenido actualizado en Dropbox

Jueves, 1 de Agosto de 2013 Sin comentarios
Share Button

He actualizado el contenido de la web en DropBox para que estén en todo momento accesibles los ejemplos, artículos, documentación,… Más detalles de todo ello en esta entrada.

He incluido los últimos ficheros añadidos a las entradas, la última versión de las librerías GLibWMI y los últimos ficheros de otras secciones como la de las rxLib en este blog.

Si os vais a dar de alta os agradecería que usarais esta invitación, de esta forma a ambos nos ofrecen un poco más de espacio, que nunca va mal…  ;-)

 

Un saludo.

Share Button
Categories: Código, Componentes, Ejemplos Tags:

Programas multiidioma con Delphi

Jueves, 25 de Octubre de 2012 16 comentarios
Share Button

flags-all-countries_6130Ya he hablado en otras ocasiones de cómo generar un aplicación multiidioma en Delphi y de paquetes tanto comerciales, como los componentes siComponents, como de código abierto como GNU GetText. En esta entrada hablaba de ambos y explicaba cómo acometer este proceso.

Aplicación multiidioma con GNU GetText

Hace tiempo había revisado el sistema de internacionalizar aplicaciones de Delphi (en este caso en la versión 6) y no me pareció muy intuitivo, tal vez también por falta de algo de documentación. Por lo que he visto en las versiones nuevas, pocas cosas han variado en el proceso y en las herramientas que trae el IDE.

En este caso me he visto obligado por las circunstancias a utilizarlo, y aunque a priori me ha resultado un poco “confuso”, como en su momento, una vez puesto en marcha, el sistema la verdad es que no es complejo y funciona de forma bastante sencilla. Se echa en falta que determinados aspectos sean un poco más potentes, como el editor de traducciones o el repositorio y la forma en que funcionan. Estos dos elementos realizan su función pero son bastante básicos en comparación con otros paquetes que hay en el mercado.

El sistema de traducción de Delphi, se basa en añadir todos los recursos traducidos a una DLL; Una para cada idioma que necesitamos añadir a nuestra aplicación.


EL PROYECTO

Imagen44Para ver el proceso completo de internacionalización crearemos un proyecto sencillo, con dos formularios y veremos que es relativamente rápido montar toda la estructura para que funcione en varios idiomas.

Algunas etiquetas, un memo con algunos strings, unos botones y un segundo formulario para comprobar un ejemplo con más de uno y un TComboBox que nos permitirá modificar el idioma en tiempo de ejecución.

Una vez que tenemos nuestro proyecto funcionando, comencemos el proceso para añadirle dos nuevos idiomas, en este caso el catalán y el inglés, al que ya tiene por defecto (español o castellano).


INTERNACIONALIZACIÓN

Para ello lo primero que debemos hacer es añadir los 2 nuevos idiomas desde el menú de Project.

en la imagen inferior podéis ver las pantallas del asistente, aunque no tiene ninguna complicación y lo que hacemos con él es añadir los idiomas (tantos como necesitemos) a la aplicación.

internacionalizacion

Una vez finalizado el asistente, veremos que el IDE ha generado dos proyectos más (en nuestro caso) correspondientes a los idiomas que hemos seleccionado.

Imagen45

Podemos probar a compilar y grabar todos los proyectos.

Lo siguiente es comenzar a traducir las cadenas para poder utilizar múltiples idiomas en la aplicación. El editor de cadenas es similar a muchas otros aplicaciones que hay para esta función. Se trata de una pantalla que nos muestra las cadenas actuales y donde debemos introducir las cadena introducidas.

Para acceder al “Translation Manager” podemos hacerlo desde el menú en: “Project / Languages / Update resource DLLs”.

Imagen47

En esta pantalla vemos a la izquierda la estructura del proyecto y los diferentes formularios que lo componen. A la derecha la zona que nos permite traducir las diferentes cadenas. Hay columnas que identifican el elemento (ID), la que contiene las cadenas en el lenguaje original de la aplicación y la que contendrá las cadenas traducidas, en este caso con el título de “Inglés (estados Unidos)”.

He marcado en rojo una cadena que ya aparece traducida automáticamente (&Cerrar – &Close).  Este es debido a que esta cadena ya está traducida en el repositorio.


EL REPOSITORIO

El “Transation Repository” o “Repositorio” es como un diccionario de traducciones que podemos ir ampliando a medida que traducimos aplicaciones. De esta forma, podemos reutilizar las cadenas que ya hemos traducido anteriormente (en la misma aplicación o en otras). En el ejemplo que estamos viendo, mi repositorio ya tiene incluida la traducción desde el Español (internacional) al Inglés (Estados unidos) de la palabra &Cerrar. Por eso al acceder a las traducciones, esta palabra ya aparece traducida.

Imagen48El repositorio nos permite acelerar la traducción de términos. Además posee opciones para importar y exportar traducciones, con lo que podemos compartirlos o incluso utilizar herramientas de traducción automáticas externas e importar las traducciones a él.

Una vez que las cadenas están traducidas para los formularios podemos añadirlas al repositorio desde el “Translation Manager” , para tenerlas disponibles más adelante.


EJECUCIÓN

Una vez traducidas y añadidas al repositorio todas las cadenas de los diferentes idiomas, compilamos los proyectos, tanto el original, como los de los diferentes idiomas.

Para probar la ejecución, podemos seleccionar desde el menú de “Project” cual es el idioma que queremos por defecto. Si probamos con alguno de los 2 idiomas y ejecutamos, veremos que efectivamente la aplicación, como era de esperar.

Por último, nos quedaría ver cómo modificar el idioma durante la ejecución de la aplicación. Es bastante simple y para ello hay una sección en la ayuda del propio Delphi a la que podéis acceder; Dentro de la “internacionalización de aplicaciones” hay un tema concreto llamado “Dynamic switching of resource DLLs”. Allí se puede leer que basta con añadir la unit Reinit en el uses, y utilizar una línea como la siguiente para cambiar el idioma.

0
1
2
3
// Cargar los recursos y releer los forms
if (LoadNewResourceModule(lang) < > 0) then begin
  ReinitializeForms;
end;

Comentar que si en alguna versión de Delphi, no encontráis la unit ReInit, podéis buscar dentro del directorio de Demos.

Al final el código que hay más arriba va a ser el único que vamos a necesitar en la aplicación.

Para apoyar la entrada, además del código de ejemplo, he añadido en este caso un vídeo.

 

[youtube dTIo5Oh-wmw]

Como siempre podéis descargar el código del ejemplo desde este link.

<DESCARGAR CÓDIGO FUENTE>

Espero que os haya sido útil y hasta la próxima.

Share Button

Testeando XE2; (LiveBindings) – Parte 1

Miércoles, 21 de Septiembre de 2011 Sin comentarios
Share Button

imagesEsta es otra de las nuevas características que se anuncian en el nuevo Delphi XE2. A priori con  el nombre me hago una idea de lo que puede ser y se que hay otros lenguajes que poseen características similares (si es lo que yo me pienso).

De todas formas, como no lo tengo claro, me he puesto a buscar qué hay sobre esta palabra…

______________________________________________

“…permite conectar cualquier elemento visual a cualquier tipo de datos utilizando LiveBindings ™”

______________________________________________

“LIBÉRATE DE LAS REJILLAS | VISUALIZA DATOS VIVOS
El nuevo LiveBindings de Delphi te permite conectar cualquier fuente de datos a cualquier interfaz de usuario o elemento gráfico VCL o FireMonkey.
LiveBindings te da la potencia y libertad creativa para presentar datos a usuarios en las formas más intuitivas e interactivas.
LiveBindings también incluye expresiones, dándote la increíble potencia y flexibilidad para construir “dinámicamente” enlaces a datos calculados y actualizados.”

______________________________________________

“¡Nuevo! Conecta cualquier elemento visual a cualquier tipo de dato con LiveBindings”

______________________________________________

Bueno, no se si con eso os he aclarado algo más. Al menos una idea sí parece que nos da de los que pueden ser.

Los LiveBindings permiten completar y ampliar las posibilidades de visualizar datos que nos provee la VCL (y sobre todo los componentes de Base de Datos). Hace unos años, arrastrar un componente DBEdit sobre un formulario, asignarle un DataSource y desde ahí “engancharlo” a un campo de una tabla/consulta era lo más. Ha pasado el tiempo y las tecnologías van cambiando (y también las necesidades).

No es que este modelo ya no sirva, pero sí que en algunas ocasiones queda un poco “corto” o un poco “cuadriculado” (pensemos en desarrollos por capas). La solución en estos casos pasaba por utilizar código para salvar esas limitaciones. Ahora esa parte puede quedar mucho más simplificada.

Sirve además para “completar” todo lo que nos ofrece la librería FireMonkey (de la que ya he hablado a modo de introducción antes), ya que los LiveBindings están tanto en la VCL como en FireMonkey.

Podemos dividir los LiveBindings (LB) en tres varios tipos, dependiendo de los tipos de elementos que vayan a relacionar.

TIPOS DE LIVEBINDINGS

TBindScopeDB

Nos permite “conectar” componentes con DataSets; Utilizando el Inspector de objetos o el asistente, podemos definir como “proveedor de datos” los elementos de un Dataset y como “destino” cualquier componente.

Un ejemplo pasa a paso de utilización de TBindScopeDB podría ser el de un formulario con componentes DB (pero sin ellos –vamos a utilizar los estándar-).

Imagen869

Para ellos crearemos una nueva aplicación FireMonkey y colocaremos los componentes normales para realizar una conexión a Base de Datos (en mi caso he utilizado ADO). Para mostrar los Datos utilizaremos un TStringGrid.

Para mostrar los datos utilizaremos un TBindScopeDB, aunque no hace falta arrastrar el componente desde la paleta (aunque se puede hacer) porque podemos hacerlo utilizando las opciones del menú utilizando el asistente.

 Imagen870Si seleccionamos en Grid, tanto en el menú contextual, como en la parte inferior del “Object Instector” aparece la opción “Link to DB DataSource”. El propio wizard ya nos muestra las fuentes de datos disponibles para poder seleccionar la que queramos.

Imagen871

Una vez  hecho esto, veremos que el asistente ha hecho todo trabajo por nosotros.

Imagen872

Por un lado ha creado 2 componentes nuevos:

  • BindingScopeDB1: El comentado que nos permite “linkar” una fuente de datos con componentes de edición estándar (en nuestro caso).
  • BindingsList1: Es el componente que almacena toda la lista de “Bindings” que vamos a ir creando para este formulario.  En este momento sólo posee uno, pero añadiremos más (más adelante los veremos en detalle).

Vamos ahora a utilizar componentes de edición estándar para mostrar los datos que aparecen en el grid; En este caso 2 TLabel y dos TEdit (TEdit y TCalendar) para los campos de código de empleado y fecha. Los labels los utilizaremos para visualizar el título de los campos (propiedad DisplayLabel –no sólo los podemos utilizar con los datos, sino con cualquier otra propiedad-) de cada campo.

Imagen873

Imagen875Para el Label, lo que necesitamos hacer es “linkar” la propiedad Text del Label, con la propiedad DisplayLabel del campo EmpNo de la Base de Datos (cuya propiedad DisplayLabel tiene el valor “Código”, como se puede ver en la imagen del Grid).

Para esto utilizaremos un TBindExpression.

Desde el propio “Object Inspector” podemos configurar cómo queremos que funcione. Por un lado El TLabel y su propiedad Text y por otro lado el TField EmpNo y su propiedad DisplayLabel, tal y como se ve en la imagen siguiente.

Una vez configuradas las opciones, ya vemos que automáticamente el cambio se ve reflejado en el Label. Si modificamos la propiedad del TField (por ejemplo para mostrarla en otro idioma), automáticamente se modificará el texto del Label.

Imagen874

Para el campo de Edición podemos seguir los mismos pasos que hemos realizado para el Grid, seleccionando el campo que queremos mostrar; Y de la misma forma para el segundo Label y para el TCalendarEdit que mostrará la fecha.

Una vez concluido esto, podemos revisar qué contiene nuestro componente BindingsList1.

Imagen876

Como era de esperar, contiene los 5 “Links” que hemos realizado en nuestro formulario. Podemos ver el nombre del componente y a la derecha una pequeña descripción de cada unos de ellos; Si accedemos (para ver más detalles) por ejemplo, al “binding” del componente de Fecha, veremos la siguiente pantalla (corresponde a lo que hemos configurado en el Inspector de objetos).

Imagen877

Nos dice que el control CalendarEdit1, en su propiedad Text, recibe notificaciones (assign to control -operation-) desde BindScopeDB1,HireDate en su propiedad DisplayText.

El resultado es bastante simple y en este caso no os puedo poner código de ejemplo, Al menos aquí pegado, porque todo se hace sin teclear nada (eso es bueno ¿no?  ;-))

Todo el proyecto posee las siguientes líneas:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.Button1Click(Sender: TObject);
begin
  // cerrar
  Self.Close;
end;
 
procedure TForm1.Edit3Click(Sender: TObject);
begin
  // Abrir una web
  ShellExecute(Handle, 'open', PChar(Edit3.Text), nil, nil, 0);
end;
 
procedure TForm1.Image1Click(Sender: TObject);
begin
  // Animación del titulo
  Layer3D1.AnimateFloat('RotationAngle.Y', 360, 6);
end;

Os animo a que reviséis el proyecto y hagáis vuestras pruebas. Al principio es todo nuevo y cuesta un poco, pero a medida que uno se acostumbra el procedimiento se vuelve bastante ágil.

Os dejo los fuentes del proyecto y el ejecutable.

<DESCARGAR FUENTES>

<DESCARGAR BINARIO>

Un Saludo.

Share Button

Testeando XE2… (soporte nativo para ficheros ZIP)

Miércoles, 14 de Septiembre de 2011 16 comentarios
Share Button

ZIPFile   Otra de las nuevas funcionalidades que trae la versión de XE2 es el soporte para ficheros ZIP. No es que sea especialmente transcendental, pero en mi caso la he utilizado bastante en mis desarrollos y hasta ahora lo había tenido que hacer mediante componentes externos (he  probado varios paquetes).

   Para ello se ha añadido a la unit System.ZIP, todo lo necesario para el trabajo con este tipo de ficheros.

   En sistema de trabajo es bastante sencillo. Para trabajar con un fichero de este tipo tenemos que crear un objeto de la clase TZIPFile y abrirlo (utilizando la función Open). Tenemos diferentes modos de apertura dependiendo de las operaciones a realizar con el fichero (read,write o readwrite).

0
1
2
// Abrir un fichero
procedure Open(ZipFileName: string; OpenMode: TZipMode); overload;
procedure Open(ZipFileStream: TStream; OpenMode: TZipMode); overload;

Una vez abierto el fichero, podemos utilizar las operaciones básicas.
Extraer ficheros existentes dentro del archivo:

0
1
2
3
4
// Extraer un fichero sobre una ubicación
procedure Extract(FileName: string; Path: string = '';
                  CreateSubdirs: Boolean=True); overload;
procedure Extract(Index: Integer; Path: string = '';
                  CreateSubdirs: Boolean=True); overload;

O extraerlos todos:

0
1
// extraerlos todos hacia un directorio
procedure ExtractAll(Path: string = '');

Añadir ficheros a un archivo comprimido existente:

0
1
2
// Añadir ficheros a un archivo comprimido
procedure Add(FileName: string; ArchiveFileName: string = '';
              Compression: TZipCompression = zcDeflate); overload;

(esta tienen bastantes variantes sobrecargadas con diferentes parámetros)

Y también podemos comprobar la integridad de un fichero comprimido existente mediante la función IsValid (que en este caso está definida como función de clase).

0
class function IsValid(ZipFileName: string): Boolean; static;

No son todas las funciones, pero sí las básicas; También hay algunas más definidas como procedimientos de clase, que nos permiten realizar operaciones de forma más sencilla y/o rápida.

Para ponerlo en práctica y probarlo he realizado un sencillo ejemplo que incluye las operaciones básicas; Y podéis comprobar que con pocas líneas es fácil hacer casi todo lo que se espera de estos ficheros.

 

TestZIPFile

Por ejemplo, el código para extraer todo el contenido sobre un directorio seleccionado es el siguiente:

0
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
31
32
33
34
35
36
37
38
39
40
41
42
43
procedure TForm3.ActionExtractExecute(Sender: TObject);
var
  b:boolean;
  DirOut:String;
begin
  // El nombre es vacío?
  if (zipFileName = '') then begin
    // Abrir uno
    ActionOpen.Execute;
    // Correcto?
    if (zipFileName = '') then begin
      Exit;
    end;
  end;
 
  // Es Valido
  b := xf.IsValid(zipFileName);
 
  // no correcto?
  if not (b) then begin
    MessageDlg('Error al abrir el fichero. Parece que es' +
               ' incorrecto o está corrupto.',
               mtError, [mbOK], 0);
    exit;
  end;
 
  // Extraer  // Path de salida
  b := SelectDirectory('Seleccione el directorio para extraer ficheros',
                       '', DirOut);
  if (b) then begin
    // protección
    try
      // Extraer al directorio seleccionado
      xf.Open(zipFileName, zmRead);
      xf.ExtractAll(DirOut);
      xf.Close;
      MessageDlg('La extracción se ha producido correctamente',
        mtInformation, [mbOK], 0);
    except
      MessageDlg('Se ha producido un error al extraer los ficheros.',
        mtError, [mbOK], 0);
    end;
  end;
end;

El código para añadir uno o varios ficheros seleccionados en un OpenDialog sería similar a este:

0
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
procedure TForm3.ActionAddFilesExecute(Sender: TObject);
var
  b:Boolean;
  i:integer;
begin
 
  // No está creado?
  if not Assigned(xf) then begin
    // Si no lo está lo creamos
    ActionNuevoZIPExecute(nil);
  end;
  // Selecciconar ficheros a añadir
  b :=  OpenDialog1.Execute;
  if (b) then begin
    // Abrirlo
    xf.Open(zipFileName, zmReadWrite);
 
    // Para 1 fichero
    //     xf.Add(OpenDialog1.FileName);
 
    // Para n ficheros
    for i := 0 to (OpenDialog1.Files.Count - 1) do begin
      xf.Add(OpenDialog1.Files[i]);
    end;
    // cerrar
    xf.Close;
  end;
  // Actualizar la pantalla
  _UpdateFiles();
end;

Para cada fichero que hay incluído en un archivo ZIP contamos con una estructura que nos permite acceder a todas la información de forma rápida. Definido como packed record, en System.ZIP podéis encontrar la definición completa y la documentación de esta estructura:

Podéis revisar el código completo del ejemplo; Está disponible aquí y podéis descargarlo junto con el fichero  compilado.

[SOURCES + BIN]

Un saludo.

Share Button
Categories: Delphi, Ejemplos, XE2 Tags: , , ,

Testeando XE2… (Estilos)

Martes, 13 de Septiembre de 2011 13 comentarios
Share Button

Otra de las cosas de las que ya he hablado y que llaman la atención en esta nueva versión de Delphi, son los estilos. Es una primera implementación y es mejorable en muchos aspectos, pero es una paso más y un avance más para poder personalizar nuestras aplicaciones.

Hay que decir que el funcionamiento general es muy sencillo.

estilos1

Estaría bien, por ejemplo, mejorar el generador de estilos para que se pudieran importar estilos desde otros archivos similares. En mi caso el generador se ha mostrado “poco estable” cuando he intentado hacer algo más complejo (cambio de imágenes) que intentar modificar los colores del estilo cargado.

Por internet podéis descargar varios videos sobre el uso del “VCL Style Designer”, que así es como se llama la herramienta para crear y modificar los estilos. Aunque es bastante sencilla e intuitiva. Una vez cargado el estilo, podemos modificar los diferentes elementos. Se puede exportar la imagen del estilo completo, modificarla desde un editor externo y luego volverla a cargar, para poder así asignar elementos de esa nueva imagen a los diferentes componentes. Se pueden cargar varias imágenes y combinar elementos de varias de ellas; Pero como he dicho en estas operaciones se ha mostrado “inestable”

Los componentes que derivan de los estándar cogen de forma correcta los estilos.  Lo que no he podido probar (y no parece que exista ahora solución -digo esto sin habérmelo mirado mucho-) es qué posibilidades hay para componentes “externos” que no deriven de uno estándar.

Una creado o modificado un estilo podemos cambiar los campos que identifican al creador, desde la misma herramienta de creación (autor, versión, página web y correo electrónico). Mientras que la previsualización desde el “Style Designer” funciona bastante bien (salvo cuando hay algun error que no muestra nada -tampoco el error-), desde el IDE de Delphi la previsualización es defectuosa (podrían haber utilizado el mismo método que desde el Designer) o “floja” por decirlo así.

En resumen, aunque el sistema tiene algunos detalles todavía faltos de pulir, en general me parece un acierto el poder dotar de esta posibilidad a las aplicaciones que se realicen. El sistema es muy sencillo de utilizar y aunque tiene algunas limitaciones, funciona bastante bien.

Actualmente al cargar instalar Delphi XE2 contamos contamos con 5 estilos que podemos utilizar.

Desde la web de Rodrigo podeís descargar algunos que él ya ha creado y es de esperar que los miembros de la comunidad vayan “colgando” los suyos propios a medida que los vayan creando (para eso supongo que se ha distribuido). Desde ahí mismo podéis consultar la explicación detallada de cómo crear nuevos estilos a partir de los existentes.

El código para cargar el estilo es bastante simple a partir de su nombre:

0
1
2
3
4
5
6
7
8
9
10
Var
  Estilo:TStyleManager;
  i:integer;
begin
  Estilo := TStyleManager.Create;
  try
    i := Random(6);
    Estilo.SetStyle(lEstilos[i]);
  finally
    Estilo.Free;
  end;</p>

En mi caso cargo los estilos de forma aleatoria a partir de un array donde los tengo definidos.

0
1
2
3
4
5
6
// Ini estilos</p>
lEstilos[0] := 'Windows';
lEstilos[1] := 'Aqua Graphite';
lEstilos[2] := 'Aqua Light Slate';
lEstilos[3] := 'Emerald Light Slate';
lEstilos[4] := 'Golden Graphite';
lEstilos[5] := 'Ruby Graphite';</p>

Hasta aquí esta primera visión. En general me ha parecido positivo. Algunos aspectos por pulir, pero creo que es un detalle más, que hace subir puntos a esta versión.

Un saludo.

Share Button
Categories: Ejemplos, XE2 Tags: , , ,