Boletín Pascal #51 - 02-FEB-2005
Índice
1. Unas palabras del editor
2. Cómo correr una sola instancia de una aplicación (y II)
3. Dentro de las clases e interfaces de Delphi (y II)
4. Enumerando todos los recursos de una red LAN
5. Foros / listas de correo
6. Delphi en la Red
- Componentes, librerías y aplicaciones
· Shareware / Comercial
· Freeware
· Actualizaciones de productos Borland
- Artículos, trucos y consejos
- Tutoriales y capacitación
- Noticias
________________________________________________________________________
Tecno Soft Solutions. Reseller Autorizado de Symbol Technologies, líder
mundial en captura de códigos de barras. >>> http://www.tecno-symbol.com
________________________________________________________________________
1. Unas palabras del editor
Ha pasado un largo tiempo sin que se publique el boletín, no por falta
de voluntad, sino por falta de tiempo. Aunque muchos no lo crean, lleva
varias horas armar un número y publicarlo, y en el pasado 2004 la verdad
que me ha sido difícil encontrar esas horas, que siempre son robadas al
necesario descanso y a la familia... Bien, pues ahora que dispongo de un
poco más de tiempo (al menos temporalmente), quiero decirles que no me
he olvidado de ustedes y que en estos días estaré traduciendo las dos
ediciones que me quedan pendientes de publicación, y ojalá que durante
el 2005 podamos publicar una edición cada dos meses como nos hemos
propuesto con Dave, pero no prometo nada, ¿OK?
Si no fuera por los autores que colaboran sus artículos, este boletín no
existiría, así que vaya nuestro agradecimiento en esta ocasión a Furious
Logic, Peter Johnson y Ezra Hoch, este último acreedor del premio
disponible para este número:
* Ezra Hoch - "Dentro de las clases e interfaces de Delphi"
Delphi SWF SDK (Standard) v1.4 - por FeatherySoft ($170)
Librería Object Pascal para crear ficheros SWF sin usar librerías
dinámicas externas. Características: objetos visuales (forma, botón,
texto, forma cambiante, sprite); todos los tipos de relleno (sólido,
gradiente, imagen); fuentes incrustadas; comandos de acciones; sonidos
(eventos, streaming); video; cualquier transición y transformación.
http://www.delphiflash.com/
Los premios para la próxima edición, que dicho sea de paso ya está casi
lista y se publicará próximamente, son:
* KylixDriver v1.1 - por ET Kimberliteware Ltd ($39 / $69 con fuentes)
Conjunto de herramientas para el desarrollo de drivers Linux que
accedan al hardware de la PC, permitiendo desarrollar con Kylix
controladores de dispositivo ISA/PCI para hardware específico.
http://etsoftware.tripod.com/products.html
* InstallAWARE 3.0 Express Edition - por MimarSinan Int. ($69.95)
Desarrolle instaladores para Windows Installer sin necesidad de
conocimiento previo de MSI. InstallAWARE automáticamente convierte en
tiempo de construcción un script de flujo condicional en una base de
datos MSI que cumple con ICE, certificable mediante logo. El IDE
ofrece una interfaz visual que automáticamente genera un script de
instalación por usted, el cual puede ser completamente adaptado.
http://www.installaware.com/landingea.html
* KnowedgeBASE Vortex 2.9 por Delphinium Software ($49.35)
El corazón de KnowledgeBASE es un árbol de información altamente
expandible y con gran capacidad de búsqueda, que puede verse como
esquema o auditado dentro de un procesador de textos incorporado.
Incluye una base de datos para referencias guardadas.
http://www.download.com/KnowledgeBase-Vortex/3000-2064-10342084.html
Estamos orgullosos de ofrecer a los lectores del boletín un descuento
especial para InstallAWARE 3 (30% en cualquier edición), gracias a la
colaboración de MimarSinan International. InstallAWARE 3 ha sido
desarrollado enteramente en Delphi y sirve para crear instaladores MSI
sin necesidad de conocimiento previo sobre Windows Installer. En vez de
limitarse a proveer una interfaz visual (como Wise o InstallShield),
InstallAWARE tiene su propio RAD y lenguaje de programación/scripting,
el que en tiempo de construcción es automáticamente convertido a base
de datos MSI, certificable mediante con logo. Las características
únicas incluyen distribución Web parcial, programación genuina para
Windows Installer, un poderoso editor de diálogos con controles únicos
(como contenedores Flash y HTML) y compresión 7ZIP avanzada (¡el
runtime para .NET es de 11MB en vez de 23MB!). Por un tiempo limitado,
los lectores pueden obtener un descuento de 30% en cualquier edición de
InstallAWARE 3 siguiendo los enlaces que se publican en este número del
boletín.
¿Alguien ha tenido oportunidad de usar el nuevo Delphi 2005? Recibimos
sus comentarios en <eds2004 @ latiumsoftware.com>.
Para más información sobre Delphi 2005: http://www.borland.com/delphi
Saludos,
Ernesto De Spirito y Dave Murray
boletin-pascal-owner@...
__________________
Colaboraron en esta edición: Furious Logic, Peter Johnson y Ezra Hoch
________________________________________________________________________
Help & Manual 3.50 por EC Software · Shareware ($ 279) - Una herramienta
visual de autoría de ayuda para generar archivos WinHelp (.HLP), Adobe
PDF, páginas HTML y los nuevos archivos HTML HELP (.CHM) introducidos
en Windows 98, así como otros formatos de archivo y documentación
impresa, todo desde una misma fuente. Una herramienta imprescindible
para cualquier desarrollador de software. http://www.helpandmanual.com/
________________________________________________________________________
2. Cómo correr una sola instancia de una aplicación (y II)
Parte 2: Una solución reutilizable
Por Peter Johnson, Copyright (c) 2003
<delphidabbler at tiscali dot co dot uk>
http://www.delphidabbler.com/
Visión general de una solución orientada a objetos
--------------------------------------------------
Esta sección presenta una solución al problema de correr una sola
instancia de una aplicación, solución que es orientada a objetos y
extensible.
El código principal está centralizado en una sola unidad
(USingleInst.pas) que implementa y crea un objeto singleton
(TSingleInst) que maneja la instancia única de la aplicación y se
encarga de enviar y recibir datos de parámetros. Mientras que
TSingleInst provee un nombre para la clase de ventana del formulario
principal, el método de nombre de clase de ventana puede (y debe) ser
redefinido (overridden) para proveer un nombre de clase único. También
puede proveerse una marca de agua al redefinir el método.
Se requiere alguna alteración al archivo de proyecto y al formulario
principal, pero los cambios no son tan significativos como en el
ejemplo anterior (presentado en la primera parte del artículo, publicada
en el Boletín Pascal #50) y la funcionalidad principal está aislada en
USingleInst.pas.
El procedimiento para habilitar el soporte de una sola instancia de la
aplicación en un proyecto es como sigue:
* Añadir USingleInst.pas al proyecto.
* Crear una nueva clase derivada de TSingleInst y redefinir los métodos
que devuelven el nombre de clase de ventana y (opcionalmente) la marca
de agua.
* Registrar la nueva clase como la clase a usar al crear un objeto
singleton SingleInst.
* Modificar los fuentes del formulario principal y del proyecto para
llamar al punto de entrada requerido del objeto SingleInst.
En el resto de esta sección repasaremos la unidad USingleInst, luego
daremos un vistazo a cómo derivar y registrar una nueva clase a partir
de ella y finalmente describiremos los cambios a realizar a los archivos
de código fuente del proyecto y del formulario principal.
La unidad USingleInst
---------------------
Repasaremos las partes de la unidad en orden. El código fuente de la
unidad acompaña este artículo. Esta es la sección de Interfaz de la
unidad que declara la clase y las funciones de apoyo:
unit USingleInst;
interface
uses
Windows, Controls, Messages;
type
TSingleInstParamHandler = procedure(const Param: string) of object;
TSingleInstClass = class of TSingleInst;
TSingleInst = class(TObject)
private
fOnProcessParam: TSingleInstParamHandler; // manejador de evento
fEnsureRestoreMsg: UINT; // mensaje único para pedir restauración
protected
function WdwClassName: string; virtual:
function WaterMark: DWORD; virtual;
function FindDuplicateMainWdw: HWND; virtual;
function SendParamsToPrevInst(Wdw: HWND): Boolean; virtual;
function SwitchToPrevInst(Wdw: HWND): Boolean;
procedure EnsureRestore(var Msg: TMessage); dynamic;
procedure WMCopyData(var Msg: TMessage); dynamic;
public
constructor Create;
procedure CreateParams(var Params: TCreateParams);
function HandleMessages(var Msg: TMessage): Boolean;
function CanStartApp: Boolean;
property OnProcessParam: TSingleInstParamHandler
read fOnProcessParam write fOnProcessParam;
end;
function SingleInst: TSingleInst;
procedure RegisterSingleInstClass(Cls: TSingleInstClass);
Repasemos primero las declaraciones de tipo. TSingleInstParamHandler es
el tipo del manejador de evento OnProcessParam que es invocado por cada
parámetro pasado a la aplicación en un mensaje WM_COPYDATA, mientras que
TSingleInstClass es el tipo de clase ("class of") de la clase
TSingleInst y clases derivadas.
Cubriremos los métodos de la clase en la sección de Implementación. El
otro único elemento que merece ser mencionado ahora es el campo
fEnsureRestoreMsg. El mismo se usa para almacenar el Id del mensaje
usado para solicitar a una aplicación que restaure y muestre su ventana.
El Id de mensaje es provisto por Windows y está garantizando que es
único. Desafortunadamente, el uso de ese mensaje significa que no
podemos usar el manejador de mensajes de Delphi para manejar el mensaje
y debemos recurrir a interceptar mensajes en el bucle de mensajes (ver
más abajo).
Finalmente la función SingleInst se usa para devolver una instancia del
objeto singleton TSingleInst (o descendiente) mientras que el
procedimiento RegisterSingleInstClass se usa para registrar el tipo de
la clase a ser usada para crear el objeto singleton.
Examinaremos la sección de Implementación en segmentos. He aquí el
primero:
implementation
uses
SysUtils, Forms;
var
// Globales almacenando singleton SingleInst y la clase de SingleInst
gSingleInst: TSingleInst = nil;
gSingleInstClass: TSingleInstClass = nil;
function SingleInst: TSingleInst;
begin
if not Assigned(gSingleInst) then
begin
if Assigned(gSingleInstClass) then
gSingleInst := gSingleInstClass.Create
else
gSingleInst := TSingleInst.Create;
end;
Result := gSingleInst;
end;
procedure RegisterSingleInstClass(Cls: TSingleInstClass);
begin
gSingleInstClass := Cls;
end;
Las variables globales privadas gSingleInst y gSingleInstClass almacenan
una referencia al objeto singleton y al tipo del objeto singleton (tal
como se registra en RegisterSingleInstClass) respectivamente.
De la implementación de SingleInst se puede ver que el objeto singleton
es creado la primera vez que el objeto se referencia. Si se registró una
clase derivada, ésta se usa para crear el singleton, de lo contrario se
usa la clase base. Esto significa que cualquier clase derivada de
TSingleInst debe ser registrada antes que el objeto sea accedido por
primera vez - se recomienda que RegisterSingleInstClass sea llamada en
la sección de Initialización de la unidad donde se define la clase
derivada. Esto también explica por qué el objeto singleton no se crea en
la sección de Inicialización de esta unidad, puesto que esta sección
sería llamada antes que las de las unidades de las clases derivadas.
Yendo a la definición de la clase, primero observemos el constructor de
la clase que simplemente registra a Windows el mensaje definido por el
usuario:
constructor TSingleInst.Create;
begin
inherited;
fEnsureRestoreMsg :=
RegisterWindowMessage('USINGLEINST_ENSURERESTORE');
end;
Hay varios "puntos de entrada" en la clase que deben ser llamados desde
la unidad principal o desde el archivo de proyecto. Los veremos a
continuación:
function TSingleInst.CanStartApp: Boolean;
var
Wdw: HWND;
begin
Wdw := FindDuplicateMainWdw;
if Wdw = 0 then
Result := True
else
Result := not SwitchToPrevInst(Wdw);
end;
procedure TSingleInst.CreateParams(var Params: TCreateParams);
begin
inherited;
StrPLCopy(Params.WinClassName, WdwClassName,
SizeOf(Params.WinClassName) - 1);
end;
function TSingleInst.HandleMessages(var Msg: TMessage): Boolean;
begin
if Msg.Msg = WM_COPYDATA then
begin
WMCopyData(Msg);
Result := True;
end
else if Msg.Msg = fEnsureRestoreMsg then
begin
EnsureRestore(Msg);
Result := True;
end
else
Result := False;
end;
El primero de estos "puntos de entrada" es CanStartApp, el que se llama
desde el archivo de proyecto e indica si la aplicación debe ser iniciada
o no. Funciona de modo similar a la función CanStart de la primera parte
de este artículo (publicada en el Boletín Pascal #50).
El método CreateParams establece el nombre de clase de ventana del
formulario principal actualizando los parámetros de creación del
formulario. El formulario principal debe redefinir su
TForm.CreateParamsSingleInst.CreateParams desde dentro de ese método.
El "puntos de entrada" más complejo es el método HandleMessages, que
intercepta el mensaje WM_COPYDATA y el campo fEnsureRestoreMsg del
formulario principal y maneja el procesamiento delegándolo a WMCopyData
y EnsureRestore respectivamente (ver más abajo). Esto método devuelve
verdadero si maneja el mensaje y falso en caso contrario. El formulario
principal debe redefinir el método TForm.WndProc y desde allí llamar a
SingleInst.HandleMessages, llamando su método TForm.WndProc heredado si
el método HandleMessages devuelve falso.
Examinemos ahora los métodos de soporte protegidos. Primero tenemos dos
métodos que deben ser redefinidos en clases descendientes:
function TSingleInst.WdwClassName: string;
begin
Result := 'SingleInst.MainWdw';
end;
function TSingleInst.WaterMark: DWORD;
begin
Result := 0;
end;
WdwClassName simplemente devuelve el nombre a usar como el nombre de
de ventana del formulario principal. Este debería ser redefinido para
devolver algo único a la aplicación. Similarmente, Watermark devuelve
0 como el valor de marca de agua (las marcas de agua se trataron en la
primera parte de este artículo -publicada en el Boletín Pascal #50-).
Este método debería ser redefinido para devolver algún valor inusual si
se emplearán marcas de agua.
Ahora siguen los dos métodos de soporte que manejan mensajes:
procedure TSingleInst.EnsureRestore(var Msg: TMessage);
begin
if IsIconic(Application.Handle) then
Application.Restore;
if Assigned(Application.MainForm) and not Application.MainForm.Visible
then Application.MainForm.Visible := True;
Application.BringToFront;
end;
procedure TSingleInst.WMCopyData(var Msg: TMessage);
var
PData: PChar;
Param: string;
begin
if TWMCopyData(Msg).CopyDataStruct.dwData = WaterMark then
begin
PData := TWMCopyData(Msg).CopyDataStruct.lpData;
while PData^ <> #0 do
begin
Param := StrPas(PData);
if Assigned(fOnProcessParam) then
fOnProcessParam(Param);
Inc(PData, Length(Param) + 1);
end;
Msg.Result := 1;
end
else
Msg.Result := 0;
end;
Nótese que estos métodos se basan bastante en los métodos de manejo de
mensajes tratados en la primera parte de este artículo, excepto que ya
no se implementan directamente en la unidad del formulario. El único
cambio significativo es que WMCopyData ahora invoca al evento
OnProcessParam en vez de llamar a un método fijo para procesar los
parámetros directamente.
Finalmente examinaremos los tres métodos protegidos restantes:
function TSingleInst.FindDuplicateMainWdw: HWND;
begin
Result := FindWindow(PChar(WdwClassName), nil);
end;
function TSingleInst.SendParamsToPrevInst(Wdw: HWND): Boolean;
var
CopyData: TCopyDataStruct;
I: Integer;
DataSize: Integer;
Data: PChar;
PData: PChar;
begin
DataSize := 0;
for I := 1 to ParamCount do
Inc(DataSize, Length(ParamStr(I)) + 1);
Inc(DataSize);
Data := StrAlloc(DataSize);
try
PData := Data;
for I := 1 to ParamCount do
begin
StrPCopy(PData, ParamStr(I));
Inc(PData, Length(ParamStr(I)) + 1);
end;
PData^ := #0;
CopyData.lpData := Data;
CopyData.cbData := DataSize;
CopyData.dwData := WaterMark;
Result := SendMessage(Wdw, WM_COPYDATA, 0, LPARAM(@CopyData)) = 1;
finally
StrDispose(Data);
end;
end;
function TSingleInst.SwitchToPrevInst(Wdw: HWND): Boolean;
begin
Assert(Wdw <> 0);
if ParamCount > 0 then
Result := SendParamsToPrevInst(Wdw)
else
Result := True;
if Result then
SendMessage(Wdw, fEnsureRestoreMsg, 0, 0);
end;
Estos métodos son análogos a las rutinas equivalentes en la primera
parte de este artículo y no serán descritos nuevamente aquí.
Modificaciones al archivo de proyecto
-------------------------------------
El archivo de proyecto debe pasar por un simple cambio para usar el
objeto SingleInst a fin de determinar si iniciar o no la aplicación.
Primero debe añadirse la unidad USingleInst al proyecto y luego se debe
modificar el archivo de proyecto para envolver la creación del
formulario y el código de ejecución de la aplicación en una sentencia
condicional, como sigue:
...
begin
if SingleInst.CanStartApp then
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end;
end.
Modificación al formulario principal
------------------------------------
Se necesita más trabajo en la unidad del formulario principal. Primero,
agregue las siguientes declaraciones en la sección protegida de la clase
del formulario:
protected
procedure WndProc(var Msg: TMessage); override;
procedure HandleParam(const Param: string);
procedure CreateParams(var Params: TCreateParams); override;
Ahora implemente estos métodos para llamar a SingleInst como sigue:
procedure TForm1.CreateParams(var Params: TCreateParams);
begin
inherited;
SingleInst.CreateParams(Params);
end;
procedure TForm1.WndProc(var Msg: TMessage);
begin
if not SingleInst.HandleMessages(Msg) then
inherited;
end;
El método CreateParams llama al método heredado (inherited) y luego
llama a SingleInst.CreateParams para establecer el nombre de clase de
ventana. El método redefinido WndProc llama a SingleInst.HandleMessages
para determinar si el mensaje es uno de los manejados por SingleInst (la
función devuelve verdadero si maneja el mensaje). Si el mensaje no es
manejado por SingleInst.CreateParams se llama al método WndProc heredado
para manejarlo.
También queremos manejar el evento TSingleInst.OnProcessParam para que la
aplicación sea notificada cuando se pasen parámetros con un mensaje
WM_COPYDATA. En este ejemplo agregaremos los parámetros a un cuadro de
lista. Asignamos el manejador de evento en FormCreate, donde también
procesaremos los parámetros pasados al programa la primera vez que se
inicia:
procedure TForm1.FormCreate(Sender: TObject);
var
I: Integer;
begin
SingleInst.OnProcessParam := HandleParam;
for I := 1 to ParamCount do
HandleParam(ParamStr(I));
end;
procedure TForm1.HandleParam(const Param: string);
begin
ListBox1.Items.Add(Param);
end;
Redefiniendo TSingleInst
------------------------
Ahora veremos un ejemplo de como redefinir TSingleInst. Simplemente
proveemos una nueva marca de agua y un nuevo nombre de clase de ventana.
La unidad entera (UMySingleInst.pas) se lista abajo. El único punto a
notar es cómo se registra la nueva clase como la clase a usar para el
objeto singleton SingleInst.
unit UMySingleInst;
interface
uses
Windows,
USingleInst;
type
TMySingleInst = class(TSingleInst)
protected
function WdwClassName: string; override;
function WaterMark: DWORD; override;
end;
implementation
{ TMySingleInst }
function TMySingleInst.WaterMark: DWORD;
begin
Result := $DE1F1DAB;
end;
function TMySingleInst.WdwClassName: string;
begin
Result := 'DelphiDabbler.SingleInst.1';
end;
initialization
RegisterSingleInstClass(TMySingleInst);
end.
Conclusión
----------
Este artículo ha demostrado como asegurar que sólo una instancia de una
aplicación se ejecute. También demuestra cómo pasar los parámetros de
línea de órdenes a la instancia que ya está en ejecución, asegurando que
su ventana se muestre prominentemente.
El método usado es detectar la presencia de la clase de ventana de la
ventana principal de la aplicación entre las ventanas del nivel más
alto. La comunicación con la instancia previa se hace por medio de
mensajes enviados a la ventana principal de la instancia. En particular,
se usa una un mensaje definido por el usuario para asegurar que la
ventana se restaure y se haga visible, y se usa el mensaje WM_COPYDATA
para enviar los parámetros de línea de órdenes cruzando las fronteras de
los procesos.
Se provee el esqueleto de algo de código fuente para una aplicación que
corre como una única instancia.
Finalmente se presentó una clase reutilizable que puede ser usada
en el desarrollo de un programa que corra una única instancia de la
aplicación.
Se incluye también una aplicación demostrativa junto con el código
fuente que acompaña esta edición.
__________________
Peter Johnson es un programador hobbyista que vive en West Wales (Reino
Unido) y que "chapotea" en Delphi. Mantiene el sitio web DelphiDabbler
(http://www.delphidabbler.com/) donde publica sus artículos y sus
aplicaciones y componentes Delphi gratuitos. Una versión completa de
este artículo se encuentra disponible en:
http://www.delphidabbler.com/articles.php?article=13
________________________________________________________________________
JfControls Lib. Multilenguaje. Multiapariencia. Skins. Privilegios. Más
de 40 componentes integrados y personalizables. Múltiples problemas de
programación resueltos. Administración centralizada de recursos. Para
Delphi 3-7 y C++ Builder 3-6. http://www.jfactivesoft.com/spindex.htm
________________________________________________________________________
3. Dentro de las clases e interfaces de Delphi (y II)
Por Ezra Hoch
La primera parte de "Dentro de las clases e interfaces de Delphi" se
publicó en el Boletín Pascal #49. Debería leerse antes de este artículo:
http://www.latiumsoftware.com/es/pascal/0049.php#4
En esta parte finalizaremos cubriendo la implementación de interfaces en
Delphi, y repasaremos unas conclusiones útiles.
Comencemos con un ejemplo en profundidad:
type
IInterface1 = interface
procedure ActA;
procedure ActB;
end;
IInterface2 = interface(IInterface1)
procedure ActC;
procedure ActD; stdcall;
end;
TSampleClass = Class(TInterfacedObject, IInterface1, IInterface2)
procedure ActA;
procedure ActB;
procedure ActC;
procedure ActD; stdcall;
end;
var
Interface1 : IInterface1;
Interface2 : IInterface2;
Sample : TSampleClass;
begin
Sample := TSampleClass.Create;
Interface1 := Sample;
Interface2 := Sample;
Interface1.ActA;
Interface1.ActB;
Interface2.ActA;
Interface2.ActB;
Interface2.ActC;
Interface2.ActD;
end;
En vez de ver el código compilado de este ejemplo, simplemente notaré
sus aspectos interesantes. Primero, al asignar un valor a Interface1,
esperaríamos que Delphi lo tome como la dirección apuntada por 'Sample',
más una cantidad específica ($10) y que eso sea todo. Al asignar un
valor a Interface2, esperaríamos que Delphi haga lo mismo, sólo que
sumaría ($0C) porque las interfaces se almacenan en memoria de la última
a la primera.
Pero Delphi no hace esto. Asigna tanto a Interface1 como a Interface2
la dirección apuntada por 'Sample' más $0C. Esto es porque IInterface2
hereda de IInterface1. Por lo tanto IInterface2 incluye Interface1, de
modo que cualquier llamada a Interface1 en realidad será ejecutada a
través de la lista de métodos de IInterface2.
Segundo, cuando llamamos a Interface1.ActA, se llama al cuarto método
de la lista de métodos de IInterface2 (porque IInterface2 hereda de
IInterface1 y a su vez hereda de IUnknown). Llamando a Interface1.ActB
se llama al quinto método de la lista de métodos de IInterface2.
Cuando llamamos a Interface2.ActA se llama al cuarto método de la lista
de métodos de IInterface2, al igual que Interface1.ActA. Esto es porque
IInterface2 hereda de IInterface1.
Tercero, cuando llamamos a Interface2.ActD, Delphi añade una
instrucción adicional antes de llamar al séptimo método de IInterface2.
Esto es porque hemos declarado el método con una convención diferente de
llamada (stdcall). Nótese que todos los métodos de IUnknown se definen
con la directiva stdcall.
La estructura del código de los métodos de la lista de métodos de una
interfaz siempre sigue la siguiente regla:
Primer método
.
.
Último método
Lista de métodos de la interfaz madre
En nuestro caso, el código de los métodos de la lista de métodos de
IInterface2 es como sigue:
ActC
ActD
// Lista de métodos de IInterface1
ActA
ActB
// Lista de métodos de IUnknown
QueryInterface
_AddRef
_Release
NOTA: La estructura de arriba es cómo se organiza el código de los
métodos en memoria, pero la primera entrada en una lista de métodos
pertenece a QueryInterface (el primer método de IUnknown), aunque
apuntará a un lugar en memoria (la implementación de ese método
QueryInterface específico de la interfaz) que está más arriba que la
implementación de los métodos propios de la interfaz. En nuestro caso,
la implementación del método QueryInterface de IInterface2 está más
arriba en memoria que la implementación del método ActB de
IInterface2, que a su vez está más arriba en memoria que la
implementación del método ActD, aunque ActD sea la séptima entrada en
la lista de métodos de IInterface2, ActB la quinta y QueryInterface la
primera.
Para entender acabadamente lo que sucede cuando Delphi llama a un
método de una interfaz, démosle un vistazo al código ensamblador de
las llamadas a los métodos de la lista de métodos de IInterface2 en el
ejemplo de arriba. El siguiente código es una copia exacta del código
compilado (excepto por los comentarios):
// ActC
add eax, -$0C
call TSampleClass.ActC
// ActD
add dword ptr [esp + $04], -$0C
call TSampleClass.ActD
// ActA
add eax, -$0C
call TSampleClass.ActA
// ActB
add eax, -$0C
call TSampleClass.ActB
// QueryInterface
add dword ptr [esp + $04], -$0C
call TInterfacedObject.QueryInterface
// _AddRef
add dword ptr [esp + $04], -$0C
call TInterfacedObject._AddRef
// _Release
add dword ptr [esp + $04], -$0C
call TInterfacedObject._Release
Como se recordará, un método de un objeto es una función o procedimiento
ordinario que acepta como primer parámetro una instancia de la clase del
método. Como puede notar, antes de cada llamada al método real (por ej.
"TSampleClass.ActD") hay una línea de código que cambia el valor de
"eax" o de "dword ptr [esp + $04]", dependiendo de la convención de
llamada. Como puede notarse, en todos los casos se resta $0C de una
variable. Pero, ¿por qué 12 ($0C = 12)? Porque resulta que esta interfaz
(IInterface2) está en el tercer lugar después del puntero a la VMT de la
clase TSampleClass (FRefcount e IUnknown están antes). Por consiguiente,
el valor de cualquier instancia de IInterface2 de TSampleClass
(Interface2 por ejemplo) es en realidad el valor del puntero a la
instancia de la clase más 12.
Aquí hay otro ejemplo que ayudará a entender la sección de arriba. El
siguiente código continúa las definiciones del código de arriba:
type
IAnotherInterface = interface
procedure ActE;
end;
TAnotherSample = class(TInterfacedObject, IInterface2,
IAnotherInterface)
procedure ActA;
procedure ActB;
procedure ActC;
procedure ActD; stdcall;
procedure ActE;
end;
var
Interface2: IInterface2;
begin
Interface2:= TAnotherSample.Create;
Interface2.ActC;
end;
Ahora comparemos la entrada para este ejemplo de IInterface2 y el
anterior:
// IInterface2 de TAnotherSample:
add eax, -$10
call TAnotherSample.ActC
// IInterface2 de TSampleClass:
add eax, -$0C
call TSampleClass.ActC
Hay dos cambios obvios:
a) La función real que es llamada (TAnotherSample.ActC o
TSampleClass.ActC)
b) La cantidad por la que se modifica EAX. Nótese que al cambiar
IInterface2 de TAnotherSample, EAX se desplaza en 16 ($10 = 16), en
vez de ser desplazado en 12. Esto es porque en TAnotherSample,
IInterface2 es la segunda interfaz en la estructura de la instancia
en memoria, y por consiguiente está "más lejos" que la instancia
misma y debe desplazarse 4 bytes adicionales.
Ahora veamos algunas cosas útiles.
Primero, si quiere chequear si dos (o más) variables de interfaz son de
la misma instancia, no puede simplemente compararlas, incluso si son del
mismo tipo. Debe "QueryInterfacearlas" (convertirlas) a un mismo tipo de
interfaz, y luego comparar. Como regla general, si desea comparar
interfaces, conviértalas a IUnknown y luego compare.
Ejemplo:
type
IBooA = interface
end;
IBooB = interface
end;
TBoo = class(TInterfacedObject, IBooA, IBooB)
end;
var
Boo : TBoo;
BooA : IBooA;
BooB : IBooB;
begin
Boo := TBoo.create;
BooA := Boo;
BooB := Boo;
// Esto no compilará
if BooA = BooB then
begin
Beep;
end;
if Integer(BooA) = Integer(BooB) then
begin
// Nunca llegará aquí
Beep;
end;
if IUnknown(BooA) = IUnknown(BooB) then
begin
// Nunca llegará aquí
Beep;
end;
// La palabra "as" es la mismo que QueryInterface al actuar con
// interfaces
if (BooA as IUnknown) = (BooB as IUnknown) then
begin
// Siempre llegará aquí
Beep;
end;
end;
Explicación: La primera comparación no compilará porque BooA y BooB son
de dos tipos diferentes. La segunda y la tercera comparación compilarán,
pero nunca devolverán verdadero. Esto es porque la conversión de tipos
(typecasting) no cambiará el valor de la variable que está siendo
convertida. Sólo permite al compilador compilar el código aunque haya
dos tipos diferentes involucrados. He aquí que, si BooA es diferente de
BooB, la comparación nunca devolverá verdadero, sin importar qué
conversión de tipos se les hagan.
Pero, ¿por qué BooA y BooB tienen diferentes valores si ambas fueron
asignadas con la sentencia ":= Boo;". La respuesta es simple. Recuerde
cuando dije que el valor de una variable de interfaz es en realidad el
valor de la instancia misma (en realidad es el valor del puntero a la
instancia) más un número por cada interfaz- En nuestro caso, BooA es
lo mismo a lo que apunta Boo, más 16. Y BooB es lo mismo a lo que Boo
apunta, más 12. Por eso es que BooA y BooB no son lo mismo.
La cuarta comparación sí funciona. Esto es porque si una interfaz es
del mismo tipo, entonces compararla con otra interfaz del mismo tipo
devolverá el resultado esperado (si ambas interfaces fueron adquiridas
a través de QueryInterface, no por conversión de tipos). Es así porque
si son del mismo tipo, entonces la diferencia entre ambas y la instancia
es la misma. Y si son de la misma instancia, entonces deberían ser
iguales.
Esto es, cada interfaz es igual a su instancia más un desplazamiento
Delta específico (el Delta depende de la interfaz). En otras palabras,
Interfaz = Instancia + Delta. Si Instancia es la misma para ambas
interfaces, y el Delta es el mismo (porque son del mismo tipo de
interfaz), entonces ambas interfaces serán iguales.
Nota: Esta es la forma en que Delphi trabaja, para bien o para mal.
Debería tomar esto en cuenta al escribir código para propiedades de
tipo interfaz. El siguiente código no funcionará apropiadamente:
TSample = class
private
FData : IUnknown;
procedure SetData(Value : IUnknown);
protected
procedure Changed; virtual; abstract;
public
property Data : IUnknown read FData write SetData;
end;
procedure TSample.SetData(Value : IUnknown);
begin
// Esto es incorrecto.
if Value <> FData then
begin
FData := Value;
Changed;
end;
end;
Puede parecer que ese código debería funcionar, pero no funcionará
cuando alguien asigna la propiedad Data con un IUnknown obtenido por
simple conversión de tipos. El código correcto debería ser:
procedure TSample.SetData(Value : IUnknown);
begin
if (Value as IUnknown) <> (FData as IUnknown) then
begin
FData := Value;
Changed;
end;
end;
Segundo, una interfaz declarada como implementada por una clase (con
excepción de las interfaces que herede de otras interfaces) significa
que cada instancia de aquella clase tomará 4 bytes más de memoria. Puede
parecer poco (y probablemente lo es) excepto en un caso. Considere el
siguiente código:
IInterfaceA = interface
end;
IInterfaceB = interface
end;
TSampleClass1 = class(TInterfacedObject, IInterfaceA)
end;
TSampleClass2 = class(TSampleClass1, IInterfaceA, IInterfaceB)
end;
Podría parecer que cada instancia de TSampleClass1 debería ocupar 16
bytes, y que cada instancia de TSampleClass2 debería ocupar 20 bytes
(4 bytes más, porque soporta una interfaz más). Este no es el caso.
Cada instancia de TSampleClass1 sí ocupa 16 bytes, pero cada instancia
de TSampleClass2 ocupa 24 bytes. Esto es porque Delphi crea una entrada
de interfaz incluso para interfaces que ya están implementadas en la
clase madre.
La solución a esto es simple. Sólo remueva la declaración de
IInterfaceA en TSampleClass2. Esto no cambiará el hecho de que
TSampleClass2 implementa IInterfaceA, porque TSampleClass2 hereda de
TSampleClass1, la que implementa IInterface1. Esto no habría sucedido
si IInterfaceB fuera un descendiente de IInterfaceA.
Esto podría sumar mucho si realiza su herencia inapropiadamente. Por
ejemplo:
TSampleClass1 = class(TInterfacedObject, IUnknown)
end;
TSampleClass2 = class(TSampleClass1, IUnknown)
end;
TSampleClass3 = class(TSampleClass2, IUnknown)
end;
TSampleClass4 = class(TSampleClass3, IUnknown)
end;
TSampleClass5 = class(TSampleClass4, IUnknown)
end;
Cada instancia de TSampleClass5 ocupará 32 bytes de memoria, a pesar que
no tiene datos reales (excepto por FRefCount de TInterfacedObject).
________________________________________________________________________
Ayúdanos a conseguir más suscriptores votando por el Boletín Pascal
(Pascal Newsletter) en estos rankings:
http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________
4. Enumerando todos los recursos de una red LAN
Desde Lima, Perú, Furious Logic nos envía un programa que enumera todos
los recursos de una LAN.
Como puede observarse en el código fuente del programa, que se adjunta
a esta edición, el núcleo del programa es un procedimiento (MostrarRed)
que hace uso de la API WNetEnumResource para enumerar los recursos de
la red. Antes de llamar a WNetEnumResource es necesario obtener un
handle llamando a la API WNetOpenEnum, y al final debemos liberarlo con
una llamada a la API WNetCloseEnum.
El proceso obtiene la dirección IP de un recurso con la función
GetHostByName, la que se pasa como parámetro a la función inet_ntoa
para convertirla en una cadena en formato www.xxx.yyy.zzz, que es lo
que finalmente se muestra.
En caso que un recurso sea a su vez un contenedor de recursos, el
procedimiento se llama recursivamente a sí mismo para enumerar los
recursos del contenedor, y así hasta el máximo nivel de anidamiento.
Otro aspecto a destacar es que el procedimiento corre en un hilo de
ejecución (thread) diferente del programa principal, una sana práctica
para no congelar el programa mientras dura el proceso de detección.
En el Boletín Pascal #53 presentaremos otro aporte de Furious Logic.
________________________________________________________________________
5. Foros / listas de correo
Recordamos a los suscriptores las direcciones de nuestros foros. Para
unirse a algún foro, lo más recomendable es hacerlo desde la web para
así tener acceso a todas las áreas del foro y la configuración de las
opciones de suscripción, pero también es posible suscribirse por email.
Para suscribirse desde la web es necesario poseer un ID de Yahoo! (si
no tienes el tuyo, puedes conseguirlo gratis registrándote como usuario
de Yahoo!).
* Delphi-abierto. Programación en Delphi (todos los niveles). Si estás
en la etapa de aprendizaje o si no te agradan los foros discriminados
por niveles, este foro es para ti.
http://espanol.groups.yahoo.com/group/delphi-abierto
Suscripción:
http://espanol.groups.yahoo.com/group/delphi-abierto/join
delphi-abierto-subscribe@...
* Delphi-intermedio. Programación en Delphi (nivel intermedio). Si ya
sabes mucho de Delphi, pero todavía te falta un largo trecho para ser
un gurú (o no tanto), este foro es para ti.
http://espanol.groups.yahoo.com/group/delphi-intermedio
Suscripción:
http://espanol.groups.yahoo.com/group/delphi-intermedio/join
delphi-intermedio-subscribe@...
* Delphi-avanzado. Programación en Delphi. Sólo para gurús.
http://espanol.groups.yahoo.com/group/delphi-avanzado
Suscripción:
http://espanol.groups.yahoo.com/group/delphi-avanzado/join
delphi-avanzado-subscribe@yahoogroups.com
* GrupoKylix. Programación en Kylix.
http://espanol.groups.yahoo.com/group/GrupoKylix
Suscripción:
http://espanol.groups.yahoo.com/group/GrupoKylix/join
GrupoKylix-subscribe@yahoogroups.com
* FreePascal-es. Programación en Free Pascal (freepascal.org).
http://espanol.groups.yahoo.com/group/freepascal-es
Suscripción:
http://espanol.groups.yahoo.com/group/freepascal-es/join
freepascal-es-subscribe@yahoogroups.com
* Desarrolladores-Software. Un lugar para tratar todos aquellos temas
relacionados con el desarrollo de software y su comercialización, y
para compartir experiencias en el ámbito laboral, profesional o
comercial con otros.
http://es.groups.yahoo.com/group/desarrolladores-software
Suscripción:
http://es.groups.yahoo.com/group/desarrolladores-software/join
desarrolladores-software-subscribe@yahoogroups.com
* Componentes. Un foro para buscar/recomendar componentes de software
(componentes VCL y CLX, objetos ActiveX, librerías DLL, etc.), así
como utilidades, tutoriales, información, etc.
http://espanol.groups.yahoo.com/group/componentes
Suscripción:
http://espanol.groups.yahoo.com/group/componentes/join
componentes-subscribe@yahoogroups.com
________________________________________________________________________
Delphi BUGS?
Catch & Log every BUG showing Unit, Class, Method, Line #.
Now with support for IntraWeb applications and Anti-Freeze feature.
http://www.eurekalog.com/bannerclick.php?id=15
________________________________________________________________________
6. Delphi en la Red
Por Dave Murray <irongut at vodafone dot net>
Componentes, librerías y aplicaciones
=====================================
Shareware / Comercial
---------------------
* KylixDriver v1.1 - by ET Kimberliteware Ltd ($39 / $69 with source)
KylixDriver is a RAD Kylix-oriented and integrated toolkit for PC
hardware access. This toolkit can be efficiently used for writing
Linux device drivers for ISA and PCI hardware.
http://www.geocities.com/etkimberliteware/kylixdriver/index.html
* Delphi SWF SDK (Standard) v1.4 - by FeatherySoft ($170)
Object Pascal library for creating SWF files, without using of any
external dynamic libraries. Released features: visual objects (shape,
button, text, morphing shape, sprite); all types of filling (solid,
gradient, image); device and embedding fonts; action commands;
sound (events, streaming); video; any transition and transformation.
http://www.delphiflash.com/
Freeware
--------
* PGP Components for Delphi v4.0 - Michael in der Wiesche (with source)
These sources provide a Delphi (2-7) direct interface to PGP requiring
a preceding full installation of PGP 6.5.x, 7.x or 8.x. Features
include: Encoding and decoding (encrypt/decrypt/sign/verify); Creating
and verifying file detached signatures; Key management; Key generation
(DH/DSS, RSA); X509 Certificate support; Keyserver functions.
http://home.t-online.de/home/idw.doc/PGPcomp.htm
* Synapse TCP/IP Library v.34 - by Lukas Gebauer (with source)
TCP/IP library for Delphi, Kylix and FreePascal using blocking
sockets. Contains simple non-visual objects for easy programming of
command line utilities, visual projects, NT services, etc. New:
FreePascal 1.9.4 support; Experimental Delphi 8 support; Optional
support for ICONV library; New flexible FTP directory listing parser.
http://synapse.ararat.cz/
* TPJDropFiles + TPJFormDropFiles v4.1 - by Peter Johnson (with source)
Two components that catch files dragged and dropped from Explorer.
TPJFormDropFiles provides a window that can contain other controls and
catch any files dropped anywhere on it or child controls. TPJDropFiles
is a non-visual component that subclasses a form to catch files that
are dropped anywhere on the form.
http://www.delphidabbler.com/software.php?id=dropfiles
* Merkes' Tiny Hex Editor v1.5.0.10 - by Merkes Pages
A free hex editor for binary files. Allows you to edit multiple files
(mdi), disk sectors and virtual memory of other processes. Tiny Hex
Editor is scriptable, lets you view data structures and has a plugin
interface for third party extensions.
http://www.mirkes.de/en/freeware/tinyhex.php
Actualizaciones de productos Borland
------------------------------------
* Public Beta: Delphi 7.1 Update - Database Supplemental
This is a public beta of database runtime files that address defects
introduced in the Delphi 7.1 update.
http://community.borland.com/article/0,1410,32492,00.html
Artículos, trucos y consejos
============================
* Interview with Danny Thorpe about Diamondback
Danny Thorpe talks about the next Delphi release.
http://community.borland.com/article/0,1410,32708,00.html
* Interview with Corbin Dunn about the Diamondback IDE
Corbin Dunn, Software Engineer, Research and Development at Borland,
talks about the Delphi IDE.
http://community.borland.com/article/0,1410,32719,00.html
* Borland "Diamondback" Data Services over .NET Remoting
Details on data remoting with the BorCon preview edition of
"Diamondback", the next version of Delphi.
http://community.borland.com/article/0,1410,32718,00.html
* Diamondback Preview License Update
A license update that does not require an NDA or Beta Agreement.
http://community.borland.com/article/0,1410,32717,00.html
* BDNtv: Diamondback Preview of Data Remoting
Demonstrates the ease of remoting data in a heterogeneous database
environment with Diamondback. Includes setting up a local DataHub for
SQL Server and InterBase then making it a remote server. And, creating
a client that updates tables in both databases simply by calling one
method of the DataHub component. Flash
http://dotnet.borland.com/bdntv/delphi/dataremoting.html
* BDNtv: Diamondback Sneak Peek
A sneak peek at Diamondback's new IDE features and the new Delphi
language feature for enumeration. The multiple personality IDE,
refactoring for both .NET and Win32, Error Insight, Help Insight, the
History View and more are shown. The for .. in .. do (foreach)
enumerator syntax is also revealed. Flash
http://dotnet.borland.com/bdntv/delphi/diamondbacksneakpeek.html
* Delphi 8 and Microsoft .NET version 1.1 Service Pack 1
Delphi 8 has trouble compiling projects after .NET 1.1 Service Pack 1
has been installed. This article explains why and offers a workaround.
Also affects the BorCon Diamondback preview release.
http://community.borland.com/article/0,1410,32713,00.html
* Borland CEO Touts Software Process Management
InfoWorld Editor-at-Large Paul Krill spoke with Dale Fuller, president
and CEO of Borland, at the BorCon conference last week about Borland's
tools and ALM strategies and issues such as Java vs. .Net, Web
services, and outsourcing.
http://www.computerworld.com.au/index.php/id;954592276;fp;16;fpid;0
* Interview: Borland Aims for Better Code
Better collaboration tools are the only route to superior software,
argues Borland's David Intersimone.
http://www.computing.co.uk/analysis/1157073
* DB2 Web Service Engines on Linux with Kylix 3: Part 1 - by Bob Swart
Demonstrates how to build a SOAP Web service engine with Kylix 3,
exposing the data from DB2 UDB database tables to the outside world.
www-106.ibm.com/developerworks/db2/library/techarticle/dm-0406swart/
* DB2 Web Service Engines on Linux with Kylix 3: Part 2 - by Bob Swart
Demonstrates how to build the user interface for a SOAP Web service
engine with Kylix 3 on Linux, exposing the data from DB2 UDB database
tables to the outside world.
www-106.ibm.com/developerworks/db2/library/techarticle/dm-0407swart/
* Producing Dynamic Data-Entry Forms from DB2 Tables on Linux - B. Swart
Uses Kylix 3 and dbExpress to analyze DB2 UDB database tables, fields
(names and types) to allow the user to select a specific table, toggle
which fields are shown, and dynamically view the output in both a
datagrid and individual data-aware controls.
www-106.ibm.com/developerworks/db2/library/techarticle/dm-0407swart2/
* Use Delphi Code to Create/Drop DB2 UDB Database Tables - by Bob Swart
Examines the design and implementation of a Delphi application you can
use to create or delete / drop tables inside IBM DB2 databases. It
provides several examples of sending SQL DDL to the DB2 DBMS using
Delphi and the cross-platform dbExpress data access technologies.
www-106.ibm.com/developerworks/db2/library/techarticle/dm-0409swart/
* Work with IBM DB2 databases and SQL in Delphi for .NET - by Bob Swart
Using Delphi code to create/drop DB2 database tables, focuses on the
use of SQL queries to build simple and more complex SQL SELECT queries
to end up with master-detail relations. Also examines SQL joins in
detail, covering examples of inner joins, left/right outer joins, and
the differences between them.
www-106.ibm.com/developerworks/db2/library/techarticle/dm-0409swart1/
Tutoriales y capacitación
=========================
* Free Web Seminars
More than 10 on-demand Web seminars from Borland to help you optimize
your software delivery.
http://community.borland.com/article/0,1410,32698,00.html
Noticias
========
* Borland Delphi 2005 Boosts Microsoft Windows Productivity
Borland today announced Delphi 2005, previously codenamed Diamondback.
Delphi 2005 combines Win32, .NET, Delphi and C# support all within one
environment, significantly advances developer and team productivity
and integrates with Borland's leading ALM solutions.
http://www.tmcnet.com/usubmit/2004/Oct/1081925.htm
* Software Delivery Strategy Gets Under Way at Borland
Kicking off its Software Delivery Optimization campaign, Borland
announced upgrades to CaliberRM requirements management and StarTeam
configuration management software at BorCon. Also at the conference,
the company demonstrated the next version of its Delphi IDE for
Windows application development.
http://sdtimes.com/news/111/story7.htm
* Borland Scheme Aims to Maximise Business Value of Software Work
Borland aims to turn software development into a simple business
process with its Software Delivery Optimisation programme, announced
at the BorCon 2004 earlier this month.
http://www.computerweekly.com/articles/article.asp?liArticleID=133397
* Borland Moving Forward with SDO
Borland took a new direction this week, with the announcement of
Software Delivery Optimization. SDO will see three technology concepts
delivered around Borland's ALM tools, as the company tries to lure
C-level executives and vice presidents of application development with
a message that software and the business should - and can - function
as one.
http://www.cbronline.com/article_feature.asp?
guid=E077757F-B5CD-415C-8CCC-F10E19F6CC11
* (Turn and Face the Strain) Software Changes
Borland this week stood atop its soapbox preaching the evils of
software projects gone awry, with projects beset by issues such as
last-minute changes and differing perspectives on the potential
success of development efforts. To stem the tide of botched projects,
Borland pitched its Software Delivery Optimization strategy.
http://weblog.infoworld.com/techwatch/archives/000712.html
* Borland Adds Project-Management Features To CaliberRM
Borland announced CaliberRM 2005 this week, a product designed to help
software project managers take some of the guesswork out of software
development. New features include tools for estimating the cost,
scheduling and staffing of a project before any code gets written.
http://informationweek.com/story/showArticle.jhtml?articleID=47208433
* Business Management for Software Projects
End users will be able to manage software projects like a business
with Borland's Software Delivery Optimisation. It aims to enable users
to manage software projects like a business, according to Boz Elloy,
senior vice-president of software products.
http://www.computerweekly.com/articles/article.asp?liArticleID=133333
* Borland challenges Visual Studio with Diamondback
With the Diamondback release of its Delphi tool for Windows
applications, Borland will challenge Microsoft while accommodating
.Net, Win32 and Delphi development. Michael Swindell, Borland director
of product management for developer tools, said with Diamondback
Borland will compete with Microsoft's Visual Studio.
http://www.computerweekly.com/articles/article.asp?liArticleID=133332
* Borland Touts Software Delivery Optimization
At BorCon, Borland will reveal its software delivery optimization
strategy, which leverages the company's ALM and developer products to
ease software development and maintenance. The strategy ultimately
will feature a bundle of the company's products code-named Themis, due
out in the first half of 2005, which purports to provide a platform
for integrated, repeatable development processes.
http://www.javaworld.com/javaworld/jw-09-2004/jw-0913-iw-borland.html
* Borland Outlines Vision for Transforming Software Development
Today at BorCon 2004, Dale Fuller, President and CEO of Borland,
presented Borland's vision and product strategy for transforming
software development from an unpredictable art form into a more
manageable and repeatable business process. Borland's vision for
Software Delivery Optimization builds on the technical efficiencies of
ALM, and incorporates the business processes and management
capabilities companies seek to ensure business-to-IT alignment, and
the delivery of quality software, on time, within budget, for maximum
business value.
http://home.businesswire.com/portal/site/google/index.jsp?
ndmViewId=news_view&newsId=20040913005322&newsLang=en
* Borland and NEC Team on Online Communications
Borland and NEC will partner to develop adaptor software in order to
rapidly integrate web-based applications with voice and video. This
will target communications over IP telephony, IP video and
conferencing over online applications.
http://www.cbronline.com/article_news.asp?
guid=2FE9728E-9350-49C4-BC59-2C25C62987BE
* Borland Acquires Software Project Planning Tool
Borland has acquired of Estimate Professional, a software project
planning and estimation tool from Software Productivity Center. This
newly acquired tool will be embedded within the next version of the
Borland CaliberRM requirements management solution.
http://www.infoworld.com/article/04/08/25/HNborlestimate_1.html
* Borland Joins ECMA to Help Shape Standards for the .NET Framework
Borland has been elected as a member of ECMA International. As a
member of ECMA, Borland will help shape standards for the .NET
Framework and the C# and C++ programming languages.
http://home.businesswire.com/portal/site/google/index.jsp?
ndmViewId=news_view&newsId=20040812005195&newsLang=en
* Borland Developer News - .NET Edition, August 2004
Your source for Delphi and C# related news. Covering mostly .NET with
some Win32 development.
http://community.borland.com/article/0,1410,32491,00.html
________________________________________________________________________
Irongut's Delphi Pages
Dedicada a la programación con Borland Delphi y Kylix. Tenemos artículos
sobre programación, noticias Borland y Delphi, código fuente y componen-
tes para usar en sus aplicaciones y más. http://www.paranoia.clara.net/
________________________________________________________________________
¡Tú puedes ayudarnos!
Por favor danos una mano y ayúdanos a llegar a los 20.000 suscriptores
en los próximos meses. Una forma en que puedes ayudarnos es enviando
este enlace a tus amigos:
http://www.latiumsoftware.com/es/pascal/index.php
boletin-pascal-subscribe@...
Otra forma es votándonos en alguno de estos rankings para darle más
visibilidad a nuestro sitio web y aumentar así el número de suscrip-
ciones al boletín:
http://news.optimax.com/delphi/links/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
Por favor vota. Son sólo unos segundos para ti que REALMENTE pueden
hacer la diferencia. Necesitamos tu ayuda para poder continuar.
________________________________________________________________________
Si no has recibido el archivo con el código fuente completo de los
ejemplos que se presentan en este boletín, puedes descargarlo de la
siguiente dirección: http://www.latiumsoftware.com/descarga/p0051.zip
________________________________________________________________________
Página principal: http://www.latiumsoftware.com/es/pascal/index.php
Página del grupo: http://espanol.groups.yahoo.com/group/boletin-pascal/
Para suscribirse / apuntarse: boletin-pascal-subscribe@...
Para cancelar / removerse: boletin-pascal-unsubscribe@...
Para reportar problemas con la suscripción: eds2004 @ latiumsoftware.com
________________________________________________________________________
Este boletín se provee "TAL Y COMO ESTA", sin garantía de ninguna clase.
Su uso implica la aceptación de nuestros términos de licencia y de la
ausencia de garantía que puedes leer en nuestro sitio web. Allí también
encontrarás una nota sobre marcas registradas. Te animamos a que redis-
tribuyas este boletín, siempre y cuando lo hagas en forma completa
(incluyendo la información de copyright), sin modificaciones y de manera
gratuita. Los artículos son copyright de sus respectivos autores y se
reproducen aquí con el permiso de los mismos.
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/es/index.php
Irongut's Delphi Pages http://www.paranoia.clara.net/
Copyright 2004 by Ernesto De Spirito + Dave Murray. All rights reserved.
________________________________________________________________________