Ante la inclusión en el Anteproyecto de Ley de Economía sostenible de modificaciones legislativas que afectan al libre ejercicio de las libertades de expresión, información y el derecho de acceso a la cultura a través de Internet, los periodistas, bloggers, usuarios, profesionales y creadores de Internet manifestamos nuestra firme oposición al proyecto, y declaramos que:
Los derechos de autor no pueden situarse por encima de los derechos fundamentales de los ciudadanos, como el derecho a la privacidad, a la seguridad, a la presunción de inocencia, a la tutela judicial efectiva y a la libertad de expresión.
La suspensión de derechos fundamentales es y debe seguir siendo competencia exclusiva del poder judicial. Ni un cierre sin sentencia. Este anteproyecto, en contra de lo establecido en el artículo 20.5 de la Constitución, pone en manos de un órgano no judicial -un organismo dependiente del ministerio de Cultura-, la potestad de impedir a los ciudadanos españoles el acceso a cualquier página web.
La nueva legislación creará inseguridad jurídica en todo el sector tecnológico español, perjudicando uno de los pocos campos de desarrollo y futuro de nuestra economía, entorpeciendo la creación de empresas, introduciendo trabas a la libre competencia y ralentizando su proyección internacional.
La nueva legislación propuesta amenaza a los nuevos creadores y entorpece la creación cultural. Con Internet y los sucesivos avances tecnológicos se ha democratizado extraordinariamente la creación y emisión de contenidos de todo tipo, que ya no provienen prevalentemente de las industrias culturales tradicionales, sino de multitud de fuentes diferentes.
Los autores, como todos los trabajadores, tienen derecho a vivir de su trabajo con nuevas ideas creativas, modelos de negocio y actividades asociadas a sus creaciones. Intentar sostener con cambios legislativos a una industria obsoleta que no sabe adaptarse a este nuevo entorno no es ni justo ni realista. Si su modelo de negocio se basaba en el control de las copias de las obras y en Internet no es posible sin vulnerar derechos fundamentales, deberían buscar otro modelo.
Consideramos que las industrias culturales necesitan para sobrevivir alternativas modernas, eficaces, creíbles y asequibles y que se adecuen a los nuevos usos sociales, en lugar de limitaciones tan desproporcionadas como ineficaces para el fin que dicen perseguir.
Internet debe funcionar de forma libre y sin interferencias políticas auspiciadas por sectores que pretenden perpetuar obsoletos modelos de negocio e imposibilitar que el saber humano siga siendo libre.
Exigimos que el Gobierno garantice por ley la neutralidad de la Red en España, ante cualquier presión que pueda producirse, como marco para el desarrollo de una economía sostenible y realista de cara al futuro.
Proponemos una verdadera reforma del derecho de propiedad intelectual orientada a su fin: devolver a la sociedad el conocimiento, promover el dominio público y limitar los abusos de las entidades gestoras.
En democracia las leyes y sus modificaciones deben aprobarse tras el oportuno debate público y habiendo consultado previamente a todas las partes implicadas. No es de recibo que se realicen cambios legislativos que afectan a derechos fundamentales en una ley no orgánica y que versa sobre otra materia.
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,…
Personalmente soy de los que llevo unos cuantos años utilizando las RxLib. Siempre me han parecido unas librerías muy buenas y estables.
Hace un tiempo realizé una traducción (no oficial) de la versión para Delphi 7, para traducirla a Delphi 2005/2006.
Desde ese día hasta hoy, no son pocos los programadores que se han puesto en contacto conmigo, vía correo electríonico o vía mi web para pedirme esa versión o para comentarme cosas sobre versiones posteriores.
Así que me he decidido ha hacer esta recopilación de diferentes versiones, oficiales, no-oficiales, recursos,…
Os adjunto también algo de información de cada una de ellas. En la mayoría de los casos datos del autor y poco más, extraídos de los fuentes o de los archivos TXT que incluyen.
(08/04/2024)
Está disponible para descarga desde la página «no oficial» www.micrel.RxLib la versión 1.0.22 compatible con las últimas versiones de Delphi, Delphi 12 Athens. También os dejo el enlace de descarga desde mi página.
Está disponible para descarga desde la página «no oficial» www.micrel.RxLib la versión 1.0.21 compatible con las últimas versiones de Delphi, Delphi 10.4 Sydney y 11 Alexandría. También os dejo el enlace de descarga desde mi página.
Está disponible para descarga desde la página «no oficial» http://www.micrel.cz/RxLibwww.micrel.RxLib la versión 1.0.19 compatible con Delphi 10.3 Rio. También os dejo el enlace de descarga desde mi página.
Nueva versión no-oficial, de las RxLib. Revisión 1.08. Incluye soporte para la útltima versión de delphi (XE2) y segun el documento con las modificaciones, también soporte para 64 bits.
Añadida versión no-oficial de las RxLib (2.75 build 1.07); Añade un componente nuevo y corrige algunos bugs de la anterior. Según la documentación comprende versiones delde D2005 hasta Delphi XE2.
Versión «no-oficial» de las RxLib que soporta DelphiXE. Esta incluye nuevas funciones y nuevos componentes (17 según leo). Podéis ver la los cambios principales introducidos en esta versión revisando esta página.
También he subido una recopilación de todos los recursos en los diferentes idiomas para la versión 2.75(Bulgarian, Chinese, Chinese (traditional), Czech, Danish, Dutch, French, Galician, German, Geek, Hungarian, Italian, Korean, Mexican, Polish, Portuguese, Romanian, Serbian, Slovene, Spanish, Slovak, Swedish, Turkish, Ukrainian).
Versión (no oficial) para RAD Studio XE; Compilado sin problemas; Incluye packages para Delphi 6 y posteriores hasta RAD Studio XE, junto con las Demos y la ayuda.
Os adjunto también este link, que permite acceder a la ayuda en línea, a partir de las imágenes de los componentes que aparecen en la paleta de las RxLib.
AÑADIDO: Adjunto esta página (traducción automática al castellano) que también hace un recopilatorio de páginas ynoticias relacionadas con las RxLib. Está originalmente en ruso y traducida utilizando el traductor de Google.
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,…
DanySoft organiza en Barcelona este 26 de Noviembre el evento de presentación de Delphi 2010, como ya viene siendo habitual para cada versión que aparece de Delphi.
También los hay previstos para Madrid y Portugal en los días siguientes.
09.00 a 09.30 | Registro y bienvenida.
09.30 a 11.30 | Novedades Rad Studio 2010 Delphi nos facilita el uso de las últimas tecnologías de programación para aplicaciones Windows y Web, y tanto en la plataforma Win32 como .NET. En esta sesión revisaremos las principales incorporaciones técnicas a esta última versión, como son la biblioteca VCL de controles la entrada a través de interfaces táctiles y mediante gestos naturales, las mejoras en DataSnap, el soporte de Firebird, así como otras ventajas para crear mejores aplicaciones, más robustas y fáciles de mantener.
Entre los temas que se tratarán durante esta sesión, destacan:
> Aplicaciones para dispositivos táctiles
> Soporte para Firebird
> DataSnap: cliente/servidor sobre http.
11.30 a 12.00 | Descanso
12.00 a 13.30 | Windows Communication Foundation con Delphi W32 y .NET En esta sesión crearemos un servidor de datos utilizando WCF en Delphi Prism y lo consumiremos con Delphi Prism y Win32. Aprovecharemos para crear el cliente Win32 con la VCL para la Web integrando Silverlight.
Entre los temas que se tratarán durante esta sesión, destacan:
> Creación de un servicio WCF
> Capa de datos con LINQ
> Consumo de servicios Web desde Delphi W32
> Silverlight con la VCL para la Web
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,…
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:
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);
// 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);
// 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.
(*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.
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,…
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)
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)
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í):
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
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,…
Pues ha llovido mucho desde la primera parte de este «articulillo»; Por lo que he visto en los fuentes del ejemplo, lo empecé hace aproximadamente hace 2 años, así que eso es lo que lleva de retardo… ;-)
En ese primer artículo se daba una visión general de lo que podía ser un sistema de PlugIns. Unas ideas generales y algo de código para empezar. Quedaba en el tintero profundizar un poco más en el tema y ver un ejemplo un poco más «práctico» que pudiera servir en una aplicación real. Eso es lo que he intentado tratar en esta segunda parte, centrandome en un sistema de «PlugIns Homogéneos«, con carga bajo petición (por parte del usuario).
TIPOS DE PLUGINS
Como ya vimos en la primera entrega, podemos dividir los plugIns en dos tipos según las tareas que desempeñan en una aplicación. Así podemos hablar de plugIns o grupos de ellos y catalogarlos como homogéneos si la tarea que realizan es similar o catalogarlos como heterogéneos (no-agrupados) si las tareas que desarrollan son independientes y no “agrupables” según su funcionalidad.
Grupos homogéneos de PlugIns
PlugIns heterogéneos
Esta división no sólo es conceptual en función de las características y desempeños de cada uno, sino que afecta directamente a la estructura con que se diseñarán estos elementos. Así, los PlugIns que pertenezcan a un grupo homogéneo tendrán estructura similar y un punto de entrada común (formulario base o procedimiento de ejecución). Mientras que los heterogéneos posiblemente no tengan una estructura común y la forma se ejecutarlos sea más “tosca” y menos “integrada” que los anteriores.
PLUGINS HOMOGENEOS
En este artículo vamos a tratar más profundamente esta variante de plugIns. Como ya hemos comentado se trata de plugIns con una estructura similar, aunque con variaciones en su funcionalidad. Tal vez con un ejemplo se vea más claro.
Tomemos como grupo homogéneo de PlugIns; Los efectos aplicables a una imagen dentro de un programa de diseño. A partir de una imagen podemos desarrollar plugIns que efectúen un determinado “cambio” de forma que la imagen resultante sea diferente a la original. La estructura y los parámetros de todos ellos parece claro que serán similares o idénticos. Todos ellos toman una imagen inicial y a partir de unos parámetros la modifican, para devolver una imagen de salida.
ESTRUCTURA FÍSICA
Para trabajar con esta estructura de plugins, utilizaremos un sistema de carga dinámica. Los plugins de programarán utilizando packages (BPL) con una estructura común y dependiendo de un package principal que contiene la Clase Base. Todos los plugins derivarán (heredarán) de una clase base que estará programada en el package principal.
Al cargar la aplicación se carga (puesto que está linkado de forma estática -utilizando la clausula USES-) también el package correspondiente a la clase Base. Esto da acceso a todos los métodos que estén definidos en la clase base (y en los derivados) desde el programa principal.
El resto de packages se cargan de forma dinámica y todos deben derivar (sus clases) de la Clase Base programada en el package Base.
PROTOTIPO
El prototipo que vamos a realizar para ilustrar el artículo simula un programa para realizar gráficos y diagramas simples. El programa utilizará un sistema de plugIns para añadir bibliotecas de objetos que puedan añadirse a los gráficos. Cada pluging (BPL) añade una nueva categoría de elementos y cada categoría implementa uno o varios objetos.
Todos los objetos que implementa una categoría derivan de una Clase Base (TShapeExBase) y esta clase base se implementa en un package que está linkado estáticamente a la aplicación principal (se carga siempre al arrancar la aplicación) y es obligatorio que exista, de otra forma la aplicación fallaría al ejecutarse.
En la imagen que se ve ala derecha, vemos la ventana correspondiente al Plugin de «Arrows»; Aquí implementa la clase TShapeExArrow (que deriva de TShapeExBase) y en esta clase se han programado los objetos que se ven en la imagen.
En nuestro ejemplo para este artículo se cargan los plugIns bajo petición. Es decir, en una primera pasada la aplicación revisa la existencia de PlugIns y detecta todos los ficheros presentes. Muestra una ventana con los plugns disponibles y la descripción de cada uno de ellos y a medida que el usuario los selecciona se cargan de forma dinámica. Imagen de la derecha.
El código de la carga es el siguiente:
...// ComprobaciónifnotFileExists(AName)thenbegin
_mens(Format('No se ha podido cargar el package <%s>;'+'No existe en disco.',[AName]));
Exit;end;// Cargar
hndl :=LoadPackage(AName);
desc :=GetPackageDescription(PChar(AName));
Result := hndl;// Acceder a la clase del menu
pName :=ChangeFileExt(ExtractFileName(AName),'');
b := ExClassList.Find(pName, i);// Encontrada?if(b)thenbegin
AClass := TPersistentClass(ExClassList.Objects[i]);end;
...
// Comprobación
if not FileExists(AName) then begin
_mens(Format('No se ha podido cargar el package <%s>;' +
'No existe en disco.',[AName]));
Exit;
end;
// Cargar
hndl := LoadPackage(AName);
desc := GetPackageDescription(PChar(AName));
Result := hndl;
// Acceder a la clase del menu
pName := ChangeFileExt(ExtractFileName(AName), '');
b := ExClassList.Find(pName, i);
// Encontrada?
if (b) then begin
AClass := TPersistentClass(ExClassList.Objects[i]);
end;
CLASE BASE (TShapeExBase)
La clase base para nuestro sistema de plugins se llama TShapeExBase. Esta clase sirve como punto de partida para todas las demás. Además de contener los métodos comunes a todos los plugins nos permitirá acceder desde la aplicación principal a todas las funciones de los plugins. Para ello los métodos importantes estarán definidos en esta clase y luego sobreescritos (override) en las clases derivadas.
{: Clase base lapa las clases implementadas en los plugins.}
TShapeExBase =class(TShape)private
FShapeEx:string;// Marca el tipo de Shapeprocedure SetShapeEx(const Value:string);virtual;protected
W, H, S:Integer;
X, Y:Integer;
XW, YH:Integer;
W2, H2, W3, H3, H4, W4, H8, W8, W16, H16:Integer;// Método de pintadoprocedure Paint;override;procedure CalculateData();// PROCEDIMIENTOS DE INFORMACION//············································// Autor del packagefunction Autor():string;virtual;abstract;// Versión del Packagefunction Version():string;virtual;abstract;// Fecha de creaciónfunction FechaCreacion():TDate;virtual;abstract;public// constructor de la claseconstructor Create(AOwner: TComponent);override;// destructor de la clasedestructor Destroy;override;published// Tipo de Shapeproperty ShapeEx:stringread FShapeEx write SetShapeEx;end;
{: Clase base lapa las clases implementadas en los plugins.}
TShapeExBase = class(TShape)
private
FShapeEx: string;
// Marca el tipo de Shape
procedure SetShapeEx(const Value: string); virtual;
protected
W, H, S: Integer;
X, Y:Integer;
XW, YH:Integer;
W2, H2, W3, H3, H4, W4, H8, W8, W16, H16:Integer;
// Método de pintado
procedure Paint; override;
procedure CalculateData();
// PROCEDIMIENTOS DE INFORMACION
//············································
// Autor del package
function Autor():string; virtual; abstract;
// Versión del Package
function Version():string; virtual; abstract;
// Fecha de creación
function FechaCreacion():TDate; virtual; abstract;
public
// constructor de la clase
constructor Create(AOwner: TComponent); override;
// destructor de la clase
destructor Destroy; override;
published
// Tipo de Shape
property ShapeEx: string read FShapeEx write SetShapeEx;
end;
En nuestro caso es una clase sencilla. La función implementa el dibujo de componentes derivados de un TShape en pantalla.
La propiedad ShapeEx es la más importante, e indica el tipo (identificador) de la figura. Equivalente a lo que en los TShape son los valores stRectangle, stEllipse, stSquare,…
En nuestra clase no puede ser un elemento tipificado como lo es en TShape, puesto que los nuevos plugins irán añadiendo elementos a esta propiedad que a priori no conocemos.
Se añaden también procedimientos de información acerca del plugin como pueden ser el Autor, la fecha de creación o la versión.
El método Paint, que para la clase base está vacío, en las clases derivadas será donde se implementen las instrucciones de pintado para cada uno de los elementos.
Finalmente la clase Base implementa el procedimiento CalculateData y al utiliza algunas variables en la parte protected, que precalculan datos y los ponen a disposición de las clases derivadas (protected), para facilitar la implementación del método Paint y dar acceso a medidas ya precalculadas.
En la clase Base además se definen dos Listas (TStringList) que nos servirán de apoyo a la hora de acceder a los diferentes objetos de los plugIns; Tanto para las clases, como para los Shapes definidos en cada clase.
//: Lista de clases registradas en los packages dinámicos
ExClassList:TStringList;//: Lista de objetos registrados en una clase (tipos de Shapes)
ExShapeList:TStringList;
//: Lista de clases registradas en los packages dinámicos
ExClassList:TStringList;
//: Lista de objetos registrados en una clase (tipos de Shapes)
ExShapeList:TStringList;
En la primera añadiremos la referencia a la Clase y el String correspondiente al nombre del package y en la segunda, para cada Shape implementado en la Clase, su valor de la propiedad ShapeEx (comentada anteriormente) y el apuntador a su clase.
De esta forma, por ejemplo, el PlugIn que implementa la clase TshapeExArrow que corresponde a la imagen que se ve más arriba, añadirá en las lista los siguientes valores:
// Registrar los tipos
ExShapeList.AddObject('stArrorRight',Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorRightW',Pointer(TShapeExArrow));...// registrar la clase
ExClassList.AddObject('PlugArrows',Pointer(TShapeExArrow));
// Registrar los tipos
ExShapeList.AddObject('stArrorRight', Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorRightW', Pointer(TShapeExArrow));
...
// registrar la clase
ExClassList.AddObject('PlugArrows', Pointer(TShapeExArrow));
En las líneas anteriores podemos ver que el plugIn PlugArrow (1) tiene implementada la clase TShapeExArrow (1), y que dentro de esta clase hay 6 objetos diferentes de tipo ShapeEx; Cuyos identificadores son: stArrorRight, stArrorRight, stArrorRightM, stArrorLeft, stArrorUp y stArrorDown.
CLASES DERIVADAS
Tal y como está diseñada la estructura, las clases derivadas de la clase Base (TShapeExBase) deben redefinir el método Paint para definir cómo se define cada uno de los objetos de esa clase.
SISTEMA DE CARGA/DESCARGA
El sistema de carga es simple y lo único que hace de especial en este caso es comprobar primero si el package ya ha sido cargado, y si no es así llama a la función CargarPackage del formulario principal, utilizando el nombre del fichero.
Podemos ver por pasos y comentar qué hace esta función:
// Cargar
hndl :=LoadPackage(AName);
desc :=GetPackageDescription(PChar(AName));
Result := hndl;
En primer lugar (una vez hemos comprobado que el fichero existe) cargamos el package a partir de su nombre. Una vez cargado obtenemos la Descripción. Para ello se llama a la función GetPackageDescription que se encuentra en la Unidad SysUtils.pas y que develve el valor almacenado en el DPK junto a la directiva {$DESCRIPTION} o {$D} que permite almacenar hasta 255 caracteres.
Todos los packages cuentan con una sección de INITIALIZATION donde añaden a las lista de clases (ExClassList) y a la lista de Shapes (ExShapeList) los elementos que ese package implementa. Estas dos clases son importantes puesto que nos facilitan mucho el trabajo a la hora de realizar todo tipo de operaciones con los elementos de cada packages. Además se registra la clase utilizando el método RegisterClass de Delphi. Por ejemplo, el package de “Arrows” contiene esta sección de INITIALIZATION:
//===================================================================//// I N I T I A L I Z A T I O N////===================================================================initialization// Registrar la clase del formRegisterClass(TShapeExArrow);// Registrar los tipos
ExShapeList.AddObject('stArrorRight',Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorRightW',Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorRightM',Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorLeft',Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorUp',Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorDown',Pointer(TShapeExArrow));// registrar la clase
ExClassList.AddObject('PlugArrows',Pointer(TShapeExArrow));//===================================================================
//===================================================================
//
// I N I T I A L I Z A T I O N
//
//===================================================================
initialization
// Registrar la clase del form
RegisterClass(TShapeExArrow);
// Registrar los tipos
ExShapeList.AddObject('stArrorRight', Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorRightW', Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorRightM', Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorLeft', Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorUp', Pointer(TShapeExArrow));
ExShapeList.AddObject('stArrorDown', Pointer(TShapeExArrow));
// registrar la clase
ExClassList.AddObject('PlugArrows', Pointer(TShapeExArrow));
//===================================================================
Lo siguiente que vamos necesitamos, una vez que tenemos cargado el package, es crear la clase que se implementa en el package; Una vez hecho esto ya tendremos total acceso a los métodos que necesitemos y realmente ya habremos conseguido nuestro objetivo.
Para crear la clase utilizamos la lista de clases (ExClassList) que hemos comentado en el párrafo anterior y que hemos rellenado en la sección de inicialización; Otra opción también viable es utilizar GetClass de Delphi mediante RTTI junto con el nombre de la clase registrada (TShapeExArrow). También funcionaría, aunque en este caso, por comodidad, hemos utilizado estas listas auxiliares.
// Crear la clase
b := ExClassList.Find(pName, i);// encontrada?if(b)thenbegin
AClass := TPersistentClass(ExClassList.Objects[i]);// OTRA OPCIÓN:
BClass :=GetClass('TShapeExArrow');end;
// Crear la clase
b := ExClassList.Find(pName, i);
// encontrada?
if (b) then begin
AClass := TPersistentClass(ExClassList.Objects[i]);
// OTRA OPCIÓN:
BClass := GetClass('TShapeExArrow');
end;
Para finalizar y después de haber realizado unas comprobaciones, llamamos al método CargarCategoria, que crea de forma dinámica la ventana asociada a esa categoría (con la descripción) y también crea el elemento individual asociada a cada Shape implementado en esa clase.
En este punto ya hemos hecho uso de todo lo implementado en ese package, puesto que ya hemos creado un objeto de todos los implementados.
// Cargar los objetos de ese plugIn
CargarCategoria(AClass, desc);
En este ejemplo, no descargamos los packages, puesto que los necesitamos para seguir trabajando con los objetos que tenemos en pantalla, lo que hacemos realmente es ocultar la ventana. Si la operación que desempeña el package no necesita que posteriormente esté cargado, bastaría con descargarlo utilizando UnloadPackage.
Hasta aquí las descripción de todo el proceso. Junto con el artículo os adjunto el ejemplo completo y bastante comentado. Es sencillo, pero muestra a la perfección el manejo práctico de este tipo de ficheros.
Espero que haya quedado claro y si hay comentarios o sugerencias, ya sabéis. ¡¡Disparad!! ;-D
Imagen del programa de ejemplo.
El código del ejemplo se puede descargar desde aquí y los binarios (EXE + BPL’s) desde aquí.
Tal como me comenta Salvador, en el proyecto no se incluyen las dos BPL’s de Dephi (de la VCL) que ne necesitan para ejecutar el proyecto. Si no tenéis Delphi 6 instalado, las necesitaréis para ejecutar. Os coloco los links, con el proyecto (binarios incluyendo las BPLs) y un fichero sólo con los dos ficheros (VCL60.BPL y RTL60.BPL).
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,…
Hola a todos.
Bueno llevaba tiempo sin dedicarle algo de tiempo al blog en sí, y hoy me he puesto un poco a realizar tareas de mantenimiento.
Actualización a la versión 2.8.5 de WordPress sin problemas. Utilizando el procedimiento de siempre:
Copia de seguridad de los Datos (NOTA1).
Desactivar todos los plugIns.
Copiar la nueva versión (ficheros), en mi caso de forma manual con FileZilla Portable.
Activar los PlugIns de nuevo y realizar otra Copia de los Datos.
NOTA1: Para las copias de la Base de Datos recomiendo el plugIn de WordPress llamado WordPress Database Backup; No sólo por el mero hecho de realizar copias (cosa que se hace con poco trabajo desde el panel de MySQL) sino porque además incluye Copias Programadas, que se pueden guardar en el servidor o enviar por correo cada x tiempo.
Añadidas encuestas. Pues eso, que he estado probando el plugIn de encuestas. Está en marcha y espero ver cómo funciona y cómo responden los usuarios.
Puntuar entradas. También he añadido este plugin que permite a los usuarios expresar su «nivel de satisfacción» con las entradas del blog y con los comentarios de otros usuarios.
Feed de otros Blogs. En la perte inferior derecha aparecen una especio de Blog-roll, entradas de otros blog relacionados con Delphi y que tienen su cabida en este. Si queréis que añada alguno más, no tenéis más que decirlo, así como en la sección de enlaces.
A parte algunas actualizaciones menores en la forma de mostrar el código (WP-Sintax).
También he creado un MIRROR (http://neftali-mirror.site11.com/) a la página principal, que sirve, no sólo como eso -mirror-, sino también como una especie de «banco de pruebas» y como «copia de seguridad» a los contenidos del blog (que en estos momentos, mientras escribo esto, está caído).
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,…
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).
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.
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».
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.
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.
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,…
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):
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>
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,…
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.
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:
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í.
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,…