Entrar
¿No tienes cuenta? Registrarse
boletin-pascal · Boletín Pascal (Delphi/Kylix)
? ¿Ya tienes membresía? Entra a Yahoo!

Consejos

¿Sabías que...
Puedes acompañar la descripción de tu grupo con una foto.

Mensajes

  Mensajes Ayuda
Avanzado
Boletín Pascal #49 - 30-SEP-2003   Lista de mensajes  
Responder | Reenviar Mensaje #16 de 20 |
Boletín Pascal #49 - 30-SEP-2003

Índice

1. Unas palabras del editor
2. Atributos de clase al estilo Delphi
3. Creando un Experto de Delphi
La forma más simple de crear un Experto de Delphi
4. Dentro de las Clases e Interfaces de Delphi (I)
5. Notas de un desarrollador (III)
Abrir un archivo con la aplicación predeterminada
6. Validando números de CBU
7. Foros / listas de correo
8. Delphi en la Red
- Componentes, librerías y aplicaciones
· Shareware
· Freeware
· Actualizaciones de Delphi y otros productos Borland
- Artículos, trucos y consejos
- Tutoriales y capacitación
- Otros enlaces
- Noticias

________________________________________________________________________

¿Necesitas alojamiento para tu sitio web? http://www.tecnosoftonline.com
________________________________________________________________________


1. Unas palabras del editor


Estoy muy contento de poder anunciar que el boletín alcanzó los 10.000
suscriptores. Muchas gracias a todos los suscriptores que hicieron esto
posible refiriendo el boletín a sus colegas, y también a los webmasters
que publicaron un enlace a nuestro sitio, permitiendo que el sitio web
sea conocido en la comunidad Delphi.

En esta edición tenemos un artículo de Demian Lessa mostrándonos cómo
implementar atributos de clase en Object Pascal, un artículo de Daniel
Wischnewski explicando cómo crear un Experto Delphi sencillo, un
artículo de Ezra Hoch revelando el funcionamiento interno de clases e
interfaces, un artículo de Alirio Gavidia sobre asociaciones de archivos
y uno breve mío mostrando cómo validar número de CBU. Gracias a los
autores por contribuir sus artículos para esta edición, y los premios
disponibles para esta edición son para:

* Demian Lessa ("Atributos de clase al estilo Delphi")
· NTTools 7 For Delphi - por i-tivity (USD 39.95)
¡Basta de batallar con la API de Seguridad de Windows NT! Obtenga su
copia de NTTools 7 para Delphi 4/5/6/7 ahora y ahórrese incontables
horas con esta colección de 40 componentes VCL escritos específica-
mente para tratar con las funciones de Seguridad de Windows NT. Se
incluye código fuente completo.
http://www.i-tivity.biz/nttools.htm

* Daniel Wischnewski ("Creando un Experto de Delphi")
· LMD SearchPack 2.0 - por LMD Innovative (EUR 39)
LMD SearchPack incluye 3 controles para integrar capacidades avanzadas
de búsqueda de textos en su proyecto, incluyendo soporte de operadores
AND, OR, NEAR y NOT. Viene con código fuente y extensivos ejemplos.
http://www.ceberus.com/lmd/products/index.php3#P6

Para la próxima edición tenemos disponibles los siguientes premios para
para dos de los autores que colaboren artículos (en inglés):

* EurekaLog v4.1.1 - por Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
EurekaLog le confiere a su aplicación (GUI, consola, Web, etc.) la
habilidad de capturar cada excepción que se produzca, generar un
registro detallado (con unidad, clase, método y número de línea) y
enviarlo por email. Se integra completamente en el IDE, y Ud. sólo
tiene tiene que hacer un simple "build" para añadir EurekaLog a
sus aplicaciones. No disminuye el rendimiento de las aplicaciones
e incrementa el tamaño del archivo compilado en sólo un 0.5% - 4%.
Compatible con Delphi 3 - 7 y todas las plataformas de Windows.
http://www.eurekalog.com/bannerclick.php?id=15

* SMExport v4.30 - por Scalabium Software ($20 estándar, $35 c/fuentes)
Conjunto de componentes VCL nativos para exportar datos de distintos
orígenes (datasets, grids, cubos de decisión, memoria, árboles DevExp,
etc.). Exporta a MS Excel, MS Access, MS Word, PDF, Text/CSV, HTML,
XML, dBase, RTF, SQL, Lotus 1-2-3, QuattroPro y más.
http://www.scalabium.com/

Bien, eso es todo por ahora. Espero que disfruten esta edición.

Saludos,

Ernesto De Spirito
boletin-pascal-owner@...

__________________

Colaboraron en esta edición: Dave Murray

________________________________________________________________________

Help & Manual 3, 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. Atributos de clase al estilo Delphi

Por Demian Lessa <demian @ knowhow-online.com.br>


En una reciente discusión sobre atributos de clase en el foro delphi-br
en Yahoo! Grupos, tuve la chance de aprender una nueva técnica que
permite la implementación práctica de las atributos de clase en Delphi.
Pero, ¿qué son estos atributos de clase?

Las atributos de clase son valores asociados a una clase y no sus
instancias. Es decir el valor del atributo de clase es el mismo para
todas las instancias de la clase. ¿Y para qué son útiles los atributos
de clase? Puedo sugerir dos utilidades muy obvias: conteo de instancias
de clase y asociación de una instancia objeto a una clase como un todo
(para propósitos de gestión).

Cuando uno necesita llevar la pista del número de instancias de una
clase, puede hacerlo usando una variable global a la unidad en la
sección Implementation. Esto garantiza que la variable no sea cambiada
por código fuera de la unidad, pero otras porciones del código dentro de
la unidad (incluso fuera de la clase) todavía pueden cambiar el valor de
esa variable. Encapsulando este valor en un atributo de clase se
resuelve el problema y la cuenta de instancias sólo puede ser modificada
mediante llamadas apropiadas a los métodos de la clase.

Otro uso importante de las atributos de clase se relaciona con el uso de
objetos de gestión o de apoyo. Imagínese, por ejemplo, que en vez de
contar las instancias de una clase deseamos guardar una lista de las
instancias de nuestra clase que están corriendo. Todo lo que tenemos que
hacer es definir un atributo de clase para mantener una lista de las
instancias de la clase. Este objeto lista puede ser instanciado cuando
sea necesario, y destruido por ejemplo en la sección Finalization de la
unidad. ¡Esto puede incluso utilizarse como base para un mecanismo
simple de colección de basura!

La implementación de los atributos de clase en Delphi se presenta abajo.
Los valores de los atributos de clase se ocultan dentro de la clase y
sólo se pueden cambiar con llamadas a los métodos apropiados. El truco
de cómo encapsular el valor me fue presentado por Marcelo Almeida, uno
de los moderadores del foro delphi-br en Yahoo! Grupos.

type
TMiClase = class
private
class function Attribute: PInteger;
class function InstanceList: Pointer;
class procedure DestroyInstanceList;
public
constructor Create;
class function GetAttribute: Integer;
class function GetInstanceList: TObjectList;
class procedure SetAttribute(Value: Integer);
end;

class function TMiClase.Attribute: PInteger;
{$J+}
const
placeholder: Integer = 0;
{$J-}
begin
Result := @placeholder;
end;

class function TMiClase.InstanceList: Pointer;
{$J+}
const
placeholder: TObjectList = nil;
{$J-}
begin
if (TObjectList(Pointer(@placeholder)^) = nil) then
// destruyamos nuestros objetos
placeholder := TObjectList.Create(false);
Result := @placeholder;
end;

class procedure TMiClase.DestroyInstanceList;
begin
if (GetInstanceList <> nil) then
begin
GetInstanceList.Free;
TObjectList(InstanceList^) := nil;
end;
end;

class function TMiClase.GetAttribute: Integer;
begin
Result := Attribute^;
end;

class function TMiClase.GetInstanceList: TObjectList;
begin
Result := TObjectList(InstanceList^);
end;

class procedure TMiClase.SetAttribute(Value: Integer);
begin
Attribute^ := Value;
end;

constructor TMiClase.Create;
begin
inherited Create;
SetAttribute(GetAttribute + 1);
GetInstanceList.Add(Self);
end;

destructor TMiClase.Destroy;
begin
SetAttribute(GetAttribute - 1);
GetInstanceList.Remove(Self);
if (GetInstanceList.Count = 0) then
DestroyInstanceList;
inherited Destroy;
end;

En TMiClase, los métodos de clase Attribute e InstanceList son los
responsables de encapsular los valores de los atributos de clase. En
estos métodos se usan constantes tipadas locales (directiva $J+) para
alojar los atributos de clase. Las constantes tipadas pueden cambiar
su valor en tiempo de ejecución igual que las variables. Pero las
constantes que usamos son locales, así que, ¿cómo pueden almacenar
valores globales para la clase? La respuesta es bastante simple: no
utilizamos los valores de las constantes. Las constantes se declaran
para que el compilador reserve la memoria apropiada para sus tipos de
valores. Y, aunque declaradas como locales, la memoria que el compilador
reserva para ellas (representado por un simple puntero) no se cambia a
través de la ejecución del programa y, por lo tanto, podemos utilizar
esta memoria para implementar nuestros atributos de clase. Astuto, ¿no?
Los métodos Attribute e InstanceList devuelven punteros a la memoria
reservada por el compilador para las constantes tipadas locales. ¡Éste
es el gran truco!

En el código adjunto encontrarán los fuentes completos para TMiClase y
una pequeña aplicación mostrando el uso de los atributos de clase de
TMiClase.

________________________________________________________________________

¡Vote por el Boletín Pascal en el DPSC Top 100 Programming web sites!
(sólo cliquea "here" donde dice "Click here to vote!", y eso es todo)
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
________________________________________________________________________


3. Creando un Experto de Delphi
La forma más simple de crear un Experto de Delphi

Copyright © 2003 Daniel Wischnewski.
Visite mi empresa
http://www.gatenetwork.com
Versión en alemán de este artículo disponible en
http://www.delphipraxis.net/referenzen.php


Introducción
============

A veces uno desea definir algunas rutinas para hacer su vida más fácil
mientras usa Delphi. Una manera simple de hacer esto es creando un
Experto. Este primer artículo le muestra los fundamentos.

Este artículo lo introduce al mundo de los Expertos de Delphi. Los
Expertos de Delphi son DLLs que serán cargadas durante la secuencia de
inicialización de Delphi. Este artículo apareció primero en alemán en
Delphi-PRAXiS: http://www.delphipraxis.net/viewtopic.php?t=5300

NOTA: Las técnicas mostradas en este artículo son válidas comenzando
con Delphi 3 o 4 y son desaprobadas desde Delphi 7, aunque
todavía siguen siendo completamente soportadas por el IDE de
Delphi.


Instalación de un Experto para el IDE de Delphi
===============================================

Cada Experto Delphi debe ser registrado en el Registro de Windows. Para
cada versión de Delphi instalada en una máquina, así como para cada
usuario usando la máquina, el Experto Delphi debe registrarse separada-
mente.

En el Registro, el Experto Delphi debe registrarse bajo la clave:

HKCU\Software\Borland\Delphi\X.0\Experts

donde X tiene que ser substituido por la versión apropiada de Delphi que
se soporta. Puede suceder que la clave Experts no esté instalada, y en
tal caso debe ser creada.

Bajo la clave Experts usted tiene que crear un valor de cadena para el
Experto de Delphi. El nombre debe ser único y el valor debe apuntar a la
DLL del Experto, incluyendo tanto el camino completo como el nombre del
archivo del Experto de Delphi. La vez próxima que Delphi levante, el
Experto será cargado automáticamente.


La interfaz del Experto de Delphi
=================================

A fin de que el Experto de Delphi interactúe con el IDE de Delphi tiene
que exportar una función con el nombre ExpertEntryPoint, usando los
siguientes parámetros:

function InitExpert(
ToolServices: TIToolServices;
RegisterProc: TExpertRegisterProc;
var Terminate: TExpertTerminateProc):
Boolean; export; stdcall;

El primer parámetro, ToolServices, ofrece todas los interfaces
"documentadas" al IDE de Delphi. El segundo parámetro, RegisterProc, se
utiliza para cargar el Experto en el IDE de Delphi. El último parámetro,
Terminate, se emplea para notificar a la DLL del Experto cuando esté a
punto de ser descargada por el IDE de Delphi.

El método InitExpert devuelve True si el Experto ha sido cargado con
éxito; de lo contrario devuelve Falso o bien genera una excepción para
descargar la DLL del IDE de Delphi (véase la muestra de código para la
solución).


La clase PlugIn TIExpert
========================

Cualquier experto de Delphi debe ser derivado de la clase TIExpert que
está declarada en la unidad ExptIntf. Esta clase define algunos métodos
abstractos que deben ser implementados por cada PlugIn: GetName,
GetAuthor, GetComment, GetPage, GetGlyph (diferente para Windows y
Linux), GetStyle, GetState, GetIDString, GetMenuText y Execute. El
propósito de cada método se explica en el código fuente que se adjunta.


El más simple Experto de Delphi
===============================

Este Experto de Delphi no hará demasiado, pero sirve para mostrar la
forma básica de hacer el trabajo. Mostrará una entrada en el menú Help
(comportamiento predeterminado). Una vez que el usuario cliquea el
elemento de menú se llamará el método Execute del Experto. Se deben
respetar los siguientes puntos a fin de tener el Experto trabajando:

* El método GetState debe devolver [esEnabled]
* El método GetStyle debe devolver esStandard
* El método GetMenuText devuelve el texto a mostrar en el menú Help
* El método Execute define la acción del experto al activarse

El código fuente completo de este experto simple se encuentra adjunto.

________________________________________________________________________

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
________________________________________________________________________


4. Dentro de las Clases e Interfaces de Delphi (I)

Por Ezra Hoch


Algunas palabras antes de comenzar:

- Primero, deseo comenzar este artículo diciendo que todo el conoci-
miento en este artículo se deriva de ver el desensamblador de Delphi
5. Por lo tanto todo lo escrito aquí es válido solamente para Delphi 5
y pudo cambiar por cualquier actualización o versión diferente.

- Segundo, para entender completamente lo que se escribe en este
artículo, usted tendrá que zambullirse en algo de código ensamblador.
Explicaré lo que hace el código ensamblador, pero esté preparado,
puede ser bastante complicado.

Y ahora, a la substancia. En Delphi, una instancia de una clase es un
simple puntero. Esto puede parecer extraño a algunas personas puesto
que han usamos instancias en Delphi muchas veces y nunca tuvieron que
tratarlos como punteros. Eso es correcto, pero sólo porque Borland fue
bastante amable de envolver bellamente los punteros. Estos punteros en
realidad apuntan a una estructura complicada en memoria, la que
intentaremos comprender. Primero, demos un vistazo a la definición de
una clase simple:

TBoo1 = class
FDataA, FDataB : Integer;
end;

var
Boo1 : TBoo1;
begin
Boo1 := TBoo1.Create;
end;

Ahora miremos a lo que Boo1 apunta (Boo1 es un puntero , ¿recuerda?).
Boo1 apunta a los siguientes valores, cada uno de 4 bytes de tamaño:

Un puntero a la VMT de TBoo1
FDataA
FDataB

N. de T.: VMT = Virtual Methods Table = Tabla de métodos virtuales

Ahora examinemos un descendiente de TBoo1:

TBoo2 = class(TBoo1)
FDataC, FDataD : Integer;
end;

var
Boo2 : TBoo2;
begin
Boo2 := TBoo2.Create;
end;

Boo2 apuntará a los siguientes valores en memoria:

un puntero a la VMT de TBoo2
FDataA
FDataB
FDataC
FDataD

Nótese que los valores a los que apunta Boo2 incluyen algunos de los
valores a los que apunta Boo1. Eso es muy fácil de explicar - TBoo2
hereda de TBoo1 y por consiguiente debe incluir todos los campos que
tiene TBoo1.

Como regla general, podemos indicar que cada instancia de la clase
apunta a los siguientes valores:

un puntero a la VMT de la clase
una lista de los campos de la clase madre
una lista de los campos de la clase

Ahora es tiempo de investigar las interfaces. Antes que podamos entender
completamente las interfaces debemos entender la manera en que Delphi
hace una llamada de método a una instancia de una clase. Lo que Delphi
hace realmente es llamar a la función (o procedimiento) con un parámetro
más aparte de los declarados, y ese parámetro es la misma instancia.
Veamos un ejemplo:

TMoo = class
FData: Integer;
procedure Act(Value: Integer);
end;

procedure TMoo.Act(Value: Integer);
begin
if Self.FData = Value then Self.FData := FData + 1
else Self.FData := Value;
end;

var
Moo: TMoo;
begin
Moo := TMoo.Create;
Moo.Act(15);
end;

¿Cómo hace Delphi para implementar esto? Simple, 'TMoo.Act' en realidad
se compila como un procedimiento que acepta dos(!) parámetros. Uno es el
parámetro definido -'Value', de tipo entero- y el otro es una instancia
de la clase TMoo. Cada vez que Delphi llama a 'Moo.Act' efectúa un
cierto preprocesamiento de antemano, es decir, pasa la instancia de
TMoo que está haciendo la llamada. Básicamente usted podría decir que
cualquier llamada a un método de un objeto es traducida a una llamada
regular a un procedimiento o función que acepte el objeto que hace la
llamada como parámetro.

En el ejemplo anterior, 'TMoo.Act' en realidad se compila a algo como
esto:

procedure TMoo_Act(Self: TMoo; Value: Integer);
begin
if Self.FData = Value then Self.FData := FData + 1
else Self.FData := Value;
end;

Es hora de volver a las interfaces. Considere el siguiente código:

IKoo = interface
function Calculate(Value: Integer): Double;
end;

function Evaluate(Koo: IKoo; Value: Integer): Double;
begin
Result := Koo.Calculate(Value);
end;

TKooA = class(TInterfacedObject, IKoo)
function Calculate(Value: Integer) : Double;
end;

TKooB = class(TInterfacedObject, IKoo)
procedure DoNothing;
function Calculate(Value: Integer): Double;
end;

Cualquier clase que soporte IKoo puede ser pasada como una variable a la
función 'Evaluate'. Cuando pasamos una instancia de TKooA a 'Evaluate'
necesitamos llamar al primer método de TKooA, pero cuando pasamos una
instancia de TKooB, necesitamos llamar al segundo método de TKooB! ¿Cómo
sabrá Delphi qué función llamar cada vez?!

Para comprender la respuesta, debemos repasar qué es realmente una
interfaz (y cómo se implementa en Delphi). Una interfaz es simplemente
una lista de métodos que una clase declara que implementa. Es decir,
cada método en el interfaz se implementa en la clase. La manera que
Delphi pone en práctica esto es como sigue:

Cada interfaz que una clase soporta es realmente una lista de punteros
a los métodos. Por lo tanto, cada vez que se hace una llamada a un
método de una interfaz, la interfaz en realidad traslada esa llamada a
uno de sus punteros a método, así dando la ocasión de actuar al objeto
que en realidad implementa la interfaz. Explicaré esto vía el ejemplo
de 'Koo' arriba:

Cada vez que la función 'Evaluate' obtiene un parámetro del tipo IKoo,
lo que realmente obtiene es una lista (con 4 elementos - IKoo hereda
de IUnknown) de punteros a métodos. Si obtuviera una interfaz de IKoo
que fue implementada por por TKooA, entonces el cuarto elemento en la
lista de punteros-a-métodos apuntaría a 'TKooA.Calcualte'. Si no,
apuntaría 'TKooB.Calcualte'. Por lo tanto, cuando se hace una llamada
a 'IKoo.Calculate', en realidad se llamará al método al que apunta
'IKoo.Calculate' (ya sea 'TKooA.Calculate' o 'TKooB.Calculate'). Ésta
es la manera en que Delphi implementa las interfaces.

Y ahora veamos cómo Delphi almacena interfaces en memoria. Para cada
instancia de una clase que soporte 'N' interfaces, necesitamos 'N'
diferentes listas de punteros-a-método (una por cada interfaz). Pero
estas listas son las misma dentro del ámbito de una misma clase, por lo
tanto, para ahorrar memoria, mantenemos solamente 'N' punteros a estas
listas por cada instancia (en vez de las listas mismas).

Considere el siguiente código:

ILooA = interface
end;

ILooB = interface
end;

TLoo = class(TInterfacedObject, ILooA, ILooB)
FLooA, FLooB: Integer;
end;

Así es como se vería una instancia de TLoo en memoria:

un puntero a la VMT de TLoo
FRefcount
IUnknown
FLooA
FLooB
ILooB
ILooA

En general, cualquier instancia se varía así:

un puntero a la VMT de la clase
la estructura de la clase madre (excepto por el puntero a la VMT)
el primer miembro de datos de la clase
.
.
el último miembro de datos de la clase
última interfaz en la lista de interfaces de la clase
.
.
primera interfaz en la lista de interfaces de la clase

Como dije al comienzo de este artículo, para realmente captar la manera
en que Delphi instrumenta las clases y las interfaces debemos mirar el
código ensamblador que Delphi produce. Primero aprenderemos un poco de
ensamblador para entender el código que seguirá. En ensamblador hay una
cosa llamada 'registro'. Un registro es un lugar en la CPU que puede
alojar un valor de 32 bits. En una CPU Pentium hay 8 registros
principales (EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP). La mayoría de las
acciones que se realizan en ensamblador se hacen sobre registros. Aquí
están algunos comandos en ensamblador:

(Mueve el valor en un registro)
Mov Registro, Valor

(Mueve el valor en Registro2 a Registro1)
Mov Registro1, Registro2

(Mueve el valor apuntado por Registro2 a Registro1.
Esto es lo mismo que el siguiente código: "Registro1 := Registro2^;")
Mov Registro1, [Registro2]

(Mueve el valor al que apunta Registro2+Valor a Registro1.
Lo mismo que: "Registro1 := Pointer(Integer(Registro2) + Valor)^;")
Mov Registro1, [Registro2 + Valor]

Ejemplos:

MOV EAX, 10
MOV EBX, EAX
MOV EAX, [EBX + 6]

EBX tendrá el valor 10 y EAX tendrá el valor que está en la dirección
16 ($10).

Apenas para cerciorarse de que usted entendió esta parte, daré un
ejemplo de cómo Delphi asigna un valor al miembro de los datos de una
instancia.

TGoo = class
FDataA, FDataB: Integer;
end;

var
Goo: TGoo;
begin
Goo := TGoo.Create;
Goo.FDataA := 5;
Goo.FDataB := 7;
end;

Si abre el desensamblador de Delphi, verá el siguiente código:

// Goo.FDataA := 5;
mov eax, [ebp-$08]
mov [eax + $04], $00000005
// Goo.FDataB := 7;
mov eax, [ebp-$08]
mov [eax + $08], $00000007

¿Por qué el valor apuntado por "ebp-$08"? Simple, allí es donde se
almacena la variable Goo. Note que acceder a FDataA es lo mismo que
acceder a la dirección "eax+$04" y que acceder a FDataB es lo
mismo que acceder a la dirección "eax+$08". Esto es porque la
dirección a la que apunta "eax" es el puntero a la VMT de TGoo, y (como
mencioné antes) los siguientes valores en memoria son los miembros de
dato de TGoo.

Volvamos a las interfaces. Mire el siguiente código:

IRoo = interface
end;

TRoo = class(TInterfacedObject, IRoo)
end;

var
Roo: TRoo;
RooIntf: IRoo;
begin
Roo := TRoo.Create;
RooIntf := Roo;
RooIntf._AddRef;
end;

El siguiente código ensamblador no es exactamente lo que produce Delphi
pero hace lo mismo y sirve al propósito:

// RooIntf := Roo;
// eax contiene el valor devuelto por TRoo.Create, es decir, la
// variable Roo
// ecx contiene el valor que más tarde debería ser asignado a RooIntf
mov ecx, eax
// Esto es lo mismo que: "ecx := ecx + $0C;"
add ecx, $0C
// RooIntf._AddRef
// Empujar "ecx" en la pila de la CPU
push ecx
mov ecx, [ecx]
// "call ecx" le dice a la CPU que salte a la dirección guardada como
// un valor en "ecx"
call ecx

Miremos el código al que nos lleva "call ecx":

// obtener (POP) en "ecx" el valor que empujamos en la pila
pop ecx
// Lo mismo que: "ecx := ecx - $0c;"
sub ecx, $0C
// Llamar al método "_AddRef" con "ecx" como variable.
call TInterfacedObject._AddRef(ecx)

Se impone una pequeña explicación. ¿Por qué Delphi sumó "$0C" a "ecx"?
Recuerde cómo Roo se almacena en la memoria (un indicador a la VMT,
FRefCount (de InterfacedObject), IUnknown (de TInterfacedObject), IRoo).
IRoo es el cuarto valor en la lista a la cual el "ecx" señala. Cada
valor tiene 4 bytes de largo, así que IRoo está 12 bytes (4*4) después
de "ecx", y "$0C" es 12 en notación hexadecimal. Así pues, básicamente,
sumando "$0C" a "ecx" hizo que "ecx" apunte al valor correcto, es decir,
que apunte a IRoo de Roo (una instancia de TRoo).

¿Por qué empujamos ecx en la pila? Esto es porque necesitaremos usarlo
más tarde, al llamar al verdadero método "_AddRef". Recuerde, "ecx" es
la dirección de Roo + 12.

Después de eso, movemos en "ecx" el valor al que "ecx" apunta. ¿Recuerda
cuándo dije que en vez de contener las listas de punteros-a-método
Delphi almacena sólo los punteros a los mismos (para ahorrar memoria)?
Esto es por qué "ecx" era en realidad un puntero, pero ahora contiene el
valor al cual apuntaba antes.

El siguiente comando es llamar al método al que "ecx" apunta. Ahora
observemos ese método. Es muy corto. Lo único que hace es modificar el
valor de "ecx" (después de restaurarlo de la pila) de modo que sea
igual que el valor de Roo (es decir, apunta a la variable Roo). Entonces
el método 'TInterfacedObject._AddRef' se llama con "ecx" (Roo) como
parámetro. Éste es igual que cuando he escrito que Delphi en realidad
compila un método de clase como una función o un procedimiento regular
que acepta un parámetro adicional - la instancia de la clase.

¿Para qué es bueno esto? Sumamos un valor a un indicador, luego hicimos
ese salto por la memoria, luego restamos el mismo valor del puntero y
¡finalmente llamamos a la función a la que apunta el puntero! ¿Por qué
molestarse? ¡Podríamos simplemente llamar la función sin sumar y restar
valores!

Aquí es donde el poder de la indirección entra en juego. Note que la
llamada a 'RooIntf._AddRef' no sabía que RooIntf era realmente de una
instancia de TRoo. Simplemente llamó al método que estaba allí para
llamar. La implementación de este método es donde se hizo la reasig-
nación del valor del puntero. Es decir, solamente la implementación a
la que RooIntf apunta (IRoo de TRoo) sabía cuánto fue sumado o restado
del puntero salvado en la pila. Si tuviéramos otra variable de tipo
TRoo2, que también implementara IRoo, y hubiésemos hecho la asignación
'RooIntf := variable de tipo TRoo2' y luego llamado el método
'RooIntf._AddRef', entonces se hubiera restado un valor diferente del
valor salvado en la pila, así haciendo que la llamada del método vaya al
lugar correcto en la clase TRoo2.

__________________

El autor puede ser encontrado en ezra.hoch@...

________________________________________________________________________


5. Notas de un desarrollador (III)
Abrir un archivo con la aplicación predeterminada

Por Alirio A. Gavidia

La presente es parte de una serie de pequeños artículos narrando expe-
riencias en el desarrollo de una aplicación.


El menú contextual o "cómo con un par de clics
convertir un archivo de un formato a otro"
==============================================

Lo que refiero aquí como Menú Contextual es la facilidad del Explorador
de Windows (y similares ventanas de Windows) de mostrarnos un menú con
el botón derecho que es diferente para cada archivo seleccionado. Para
que quede claro ejecute el Explorador busque un archivo cualquiera y
haga clic con el botón derecho. En mi caso he seleccionado un MP3 y la
primera opción del menú es "Play in Winamp". Tengo más abajo una opción
que dice "Agregar en ZIP" entre otras.

Recientemente en RentACoder solicitaron un programa para conversión de
archivos BMP/JPG y BMP/GIF. Me pareció que esto se puede combinar con el
uso de menúes contextuales (originalmente los uso en HalZip imitando
WinZip).

Del artículo anterior de esta serie tenemos como convertir archivos de
distintos formatos. Ahora vamos a concentrarnos en el manejo del menú
contextual como extensión del Explorador de Windows.


Abrir un archivo con una aplicación predeterminada
==================================================

Esto es simple comparativamente, tomando el ejemplo de Wimamp sólo
tenemos que manipular el Registro de Windows. Comencemos con REGEDIT y
vamos a HKEY_CLASSES_ROOT desde allí buscamos '.mp3'. Por lo pronto sólo
nos interesa el valor "Default" contenido. Esto programáticamente sería
así:

Registry es de tipo TRegistry, lo asumo ya creado.

Registry.RootKey := HKEY_CLASSES_ROOT;
if Registry.OpenKey('\.mp3',True) then
appasoc := Registry.ReadString('');

Nota: Para leer el valor "default" o por defecto de una clave ("key")
simplemente use el método de lectura que corresponda sobre un
identificador en blanco.

Obtenido 'appasoc' (que debe ser 'Winamp3.File') buscamos este valor en
HKEY_CLASSES_ROOT y encontramos información interesante como la descrip-
ción del tipo dada en el valor por defecto, el icono por defecto tomado
del archivo que señalemos, y las opciones relativas al "Shell", en este
caso nos interesa "Play", dentro de Play hallamos el comando que
queremos asociar. Si siguieron todo esto usando Regedit verán que es
bastante simple.

El ejemplo anexo a este artículo ('test03') permite revisar las defini-
ciones presentes en la máquina y adicionalmente crear algunas nuevas.

En el segundo ejemplo anexo a este artículo ('gconvert') usamos la aso-
ciación a BMP, JPG, WMF, EMF, ICO y GIF para conversiones. Simplemente
creamos la entrada "Convertir a .." esto sin dañar el valor "Open" por
defecto.

"Gconvert" es casi una aplicación de consola (sin interfaz Windows) que
acepta un parámetro. El parámetro aceptado se asume como un archivo de
tipo jpg, gif, ico, wmf, emf. Para probarlo simplemente suelte un
archivo de cualquiera de estos tipos sobre el programa y... voila.
Obtendrá un archivo bmp.

Además "gconvert" opera con los parámetros /r y /u el primero asocia
los archivos convertibles, el segundo parámetro elimina esta asociación.

Compile "gconvert" y obtenga el ejecutable correspondiente. Ciertamente
al soltar un archivo jpg o gif o de cualquiera de los tipos convertibles
obtendrá un bmp. Ejecute el archivo registro.bat para asociar los
archivos convertibles al menú de contexto, busque un archivo de los
tipos convertibles y revise el menú que despliega con el botón derecho
del ratón.


Sensitivo a contexto
====================

Ni WinZip y HalZip usan este enfoque más allá de las opciones "abrir"
e "imprimir". La razón es poder manejar múltiples archivos con una
llamada. Con el esquema dado hasta ahora si se selecciona tres archivos
"txt" y con el menú derecho se opta por "Abrir" tendremos tres
instancias del programa.

El otro problema es la interactividad de los menúes. Para ello basta ver
que WinZip y HalZip generan entradas de menú de forma dinámica. Verán
que Winzip genera un menú de tipo e-mail <nombre archivo>. Donde <nombre
archivo> cambia según el menú seleccionado.

Delphi trae un ejemplo de esto en

...\Borland\Delphi5\Demos\Activex\Shellext

Revísenlo si quieren. Será analizado con más propiedad próximamente en
esta serie de artículos.

Este tema será analizado más profundamente en el próximo artículo.


Alirio A. Gavidia.
desde www.gavidia.org

__________________

Próximo tema: DLL y su registro

________________________________________________________________________

¡Vote por el Boletín Pascal en el DPSC Top 100 Programming web sites!
http://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
________________________________________________________________________


6. Validando números de CBU

Por Ernesto De Spirito


Las cuentas bancarias en Argentina se identifican por un número de CBU
(Clave Bancaria Uniforme), formado por 22 dígitos, divididos en dos
bloques. El primer bloque, formado por 8 dígitos, identifica al banco y
sucursal, mientras que el segundo bloque, formado por los restantes 13
dígitos, identifica la cuenta bancaria. El último dígito de cada bloque
es el dígito verificador del mismo según el algoritmo clave 10 con
ponderador 9713.

Para validar un número de CBU se deberán computar los dígitos verifica-
dores de ambos bloques y compararlos con los respectivos valores para
ver si coinciden o no. La siguiente función realiza ese trabajo:

function CBU_Valido(const CBU: string): boolean;
{
Copyright (c) 2003 Ernesto De Spirito
http://www.latiumsoftware.com/es/index.php

Determina si un número de CBU (Clave Bancaria Uniforme)
es válido.

La cadena que se pasa como parámetro debe estar formada
por 22 dígitos numéricos (no se admiten guiones, barras
ni espacios como parte de la cadena con el CBU).
}
var
i: integer;

function Verificador(const s: string; i1, i2: integer): char;
// Devuelve el dígito verificador para los dígitos
// de las posiciones "i1" a "i2" de la cadena "s"
// usando clave 10 con ponderador 9713
const
ponderador: array[0..3] of integer = (3,1,7,9); // 9713
var
i: integer; // subíndice para recorrer la cadena
j: integer; // subíndice del ponderador (módulo 4)
suma: integer; // sumatoria de los productos parciales
digito: integer; // dígito verificador
begin
suma := 0; j := 0;
for i := i2 downto i1 do begin
inc(suma, (Ord(s[i])-Ord('0')) * ponderador[j mod 4]);
inc(j);
end;
digito := (10 - suma mod 10) mod 10;
Result := Chr(digito + Ord('0'));
end;

begin
Result := False;
// Comprueba la longitud de la clave
if Length(CBU) <> 22 then exit;
// Comprueba que esté integrada sólo por dígitos numéricos
for i := 1 to 22 do
if not (CBU[i] in ['0'..'9']) then exit;
// Comprueba el primer dígito verificador
if CBU[8] <> Verificador(CBU, 1, 7) then exit;
// Comprueba el segundo dígito verificador
if CBU[22] <> Verificador(CBU, 9, 21) then exit;
// Pasó todas las pruebas. Es válido.
Result := True;
end;

Llamada de ejemplo:

procedure TForm1.btnValidarClick(Sender: TObject);
begin
if CBU_Valido(edtCBU.Text) then
ShowMessage('El CBU ingresado es válido')
else
ShowMessage('El CBU ingresado no es válido');
end;

________________________________________________________________________

¡Vote por el Boletín Pascal en The Programming Pages!
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
________________________________________________________________________

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
________________________________________________________________________


7. 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-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

________________________________________________________________________

Merlin's Delphi Forge
Delphi and Kylix news, FAQ, downloads, links, forums and more.
Accepting uploads and submissions.
http://www.delphifaq.net/
________________________________________________________________________


8. Delphi en la Red

Por Dave Murray <irongut @ vodafone.net>


Componentes, librerías y aplicaciones
=====================================


Shareware/Comercial
-------------------

* LMD SearchPack 2.0 - by LMD Innovative (EUR 39)
LMD SearchPack includes 3 controls for integrating advanced text
search capabilities into your projects including support of AND, OR,
NEAR and NOT operators. Full source code and extensive demo projects
included. http://www.ceberus.com/lmd/products/index.php3#P6

* EurekaLog v4.2 - by Fabio Dell'Aria (Std $24, Pro $49, Ent $99)
Gives your application the ability to catch every exception, generate
a detailed log and send it via email. Integrated with Delphi 3 - 7, a
single rebuild adds EurekaLog to your app. NEW: save modified files on
exception; detailed Log when the application freezes; customizable
email for every exception; speed and stability improvements.
http://www.eurekalog.com/bannerclick.php?id=15


Freeware
--------

* WinDowse v5.1 - by Greatis Software (free for non-commercial use)
Unique windows analyzer, best Borland's WinSight replacement. Greatis
WinDowse is an extremely convenient tool for obtaining necessary
technical information about any window. Place a mouse cursor on a
window, and WinDowse will show all parameters of the window and window
class. Full Delphi 3-7 source code available after 100 Euro donation.
http://www.greatis.com/windowse.htm

* Inno Setup v4.0.8 - by JR Software (with source)
A free installer for Windows that rivals commercial installers in
features and stability. Features include: all 32-bit Windows versions;
create a single EXE or disk spanning; standard interface; customizable
setup types; complete uninstall capabilities; zip / bzip2 compression;
create shortcuts, registry + .INI entries; silent install / uninstall;
register DLL, OCX and type libraries; install fonts; Pascal Script.
http://www.jrsoftware.org/isinfo.php

* TPages v1.2 - by Angus Johnson (with source)
Visual component for simple, non-data-aware reports. Features include:
text wrapped between margins, in columns or at specific offsets;
multiple alignment options; multi-line page headers, footers and
column headers; angled text; bitmaps, lines, boxes and arrows; page
numbering; prevent blocks of text spanning across pages.
http://www.users.on.net/johnson/delphi/


Actualizaciones de Delphi y otros productos Borland
---------------------------------------------------

* Fixes for Kylix 3 Issues on Newer Distros (updated) - Andrés Colubri
Kylix 3 (particularly C++) on newer Linux distros (eg. RedHat 8+,
Madrake 9+, SuSE 8.2) has a number of bugs: compilation errors with
STL, unresolved references when linking, installer and IDE hangs, etc.
This package contains a collection of fixes to address these issues.
http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=20136


Artículos, trucos y consejos
============================

* Come learn about Octane! Sneak peeks around the world! - by A Ohlsson
First Octane sighting at Entwickler Konferenz in Frankfurt, Germany.
http://bdn.borland.com/article/0,1410,30387,00.html

* Using D7 to Consume Web Services and Transform XML - by Anders Ohlsson
In this BDNtv episode, Anders shows how you can consume web services
that return XML data. Anders uses Delphi 7 Enterprise to create a
simple application that consumes an XML web service, transforms the
result and displays custom picked data in a regular DBGrid.
Format(s): Flash, Duration: 9:34.
http://community.borland.com/article/0,1410,30379,00.html

* Customizing the DBNavigator
Enhancing the TDBNavigator component with modified graphics (glyphs),
custom button captions, and more. Exposing the OnMouseUp/Down event
for every button.
http://delphi.about.com/library/weekly/aa090203a.htm

* Accessing and managing MS Excel sheets with Delphi - by Zarko Gajic
How to retrieve, display and edit Microsoft Excel spreadsheets with
ADO (dbGO) and Delphi. This step-by-step article describes how to
connect to Excel, retrieve sheet data, and enable editing of data
(using the DBGrid). You'll also find a list of most common errors (and
how to deal with them) that might pop up in the process.
http://delphi.about.com/library/weekly/aa090903a.htm

* Delphi History: from Pascal to Octane - by Zarko Gajic
Concise descriptions of Delphi's versions and its history, along with
a brief list of features and notes. Find out how Delphi evolved from
Pascal to a RAD tool that can help you solve development problems not
only for Windows but also for Linux and .NET.
http://delphi.about.com/cs/azindex/a/dhistory.htm

* Drop Down List Inside a DBGrid: Part 1 - by Zarko Gajic
Here's how to place a drop down pick list into a DBGrid. Create
visually more attractive user interfaces for editing lookup fields
inside a DBGrid - using the PickList property of a DBGrid column.
http://delphi.about.com/library/weekly/aa092703a.htm

* How to Darken or Lighten TColor?
http://www.swissdelphicenter.ch/en/showcode.php?id=1411

* How to execute a Javascript function in a Webbrowser / IE Document?
http://www.swissdelphicenter.ch/en/showcode.php?id=1732

* How to display the items in a listview control as a group? (WinXP)
http://www.swissdelphicenter.ch/en/showcode.php?id=1782

* How to detect if an Application is running within VMware?
http://www.swissdelphicenter.ch/en/showcode.php?id=1819

* How to mix two colors using transparency coefficient?
http://www.swissdelphicenter.ch/en/showcode.php?id=1832

* THvHQuery for exporting query to CSV file - by Henk van Hoek
Export a query to a Comma Separated CSV File.
http://www.delphi3000.com/articles/article_3763.asp

* TEdit and EConvertError - by Andrew Kennaugh
Checking TEdit for StrToFloat using OnKeyPress not OnChange.
http://www.delphi3000.com/articles/article_3765.asp

* Inline Assembler in Delphi (I): Introduction - by Ernesto De Spirito
Reprinted from this newsletter, Ernesto's Assembler tutorial.
http://www.delphi3000.com/articles/article_3766.asp

* Inline Assembler in Delphi (II): ANSI strings - by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3767.asp

* Inline Assembler in Delphi (III): Static Arrays - Ernesto De Spirito
http://www.delphi3000.com/articles/article_3768.asp

* Inline Assembler in Delphi (IV): Records - by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3769.asp

* Inline Assembler in Delphi (V): Objects - by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3770.asp

* Inline Assembler in Delphi (VI): Calling External Procedures
- by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3771.asp

* Inline Assembler in Delphi (VII): 128-bit Integer Arithmetic
- by Ernesto De Spirito
http://www.delphi3000.com/articles/article_3772.asp

* Playing Sounds Thru The Built-In PC Speaker - by Ernesto De Spirito
Using inline assembler to play sounds with the built-in PC speaker.
http://www.delphi3000.com/article.asp?id=3773

* Determining if a Logical Drive Exists - by Ernesto De Spirito
How to know if there is a drive assigned to a letter.
http://www.delphi3000.com/articles/article_3774.asp

* Using TList's and Pointers in delphi (Part II) - by Stewart Moss
Demonstration of how to create records on a TList object.
http://www.delphi3000.com/articles/article_3775.asp

* Adding HTML Resources to DLL/EXE that IE can Reference - Matt Harrison
Creating an RC file to store HTML and Images as resources that works
with IE's res:// format.
http://www.delphi3000.com/articles/article_3776.asp

* Horizontal Modularization - by Hang Liu
This article introduces a modular approach to building large
applications.
http://www.delphi3000.com/articles/article_3777.asp

* Borland DataSnap vs Microsof ADO.NET - by Pablo Reyes
A comparison between the tools provided by these technologies for
building data aware applications.
http://www.delphi3000.com/articles/article_3778.asp

* Simple Winsock Component for Console App - by J3N7iL Jones
How can I create a TCP/IP internet connection in a console application
using winsock?
http://www.delphi3000.com/articles/article_3779.asp

* PageControl Without Border - by Tommy Andersen
http://www.delphi3000.com/articles/article_3783.asp

* Adding new Standard Actions - by Andreas Schmidt
http://www.delphi3000.com/articles/article_3784.asp

* Create a Sizeable Dialog - by Terrance Hui
How to create a sizable dialog (with sizegrip) without using any 3rd
party components.
http://www.delphi3000.com/articles/article_3785.asp

* Selecting Files - by Teun Spaans
In which ways can you let your user choose a file or directory?
http://www.delphi3000.com/articles/article_3786.asp

* Debugging Tricks - by Andreas Schmidt
How to read the content of a TStrings in the integrated debugger.
http://www.delphi3000.com/articles/article_3787.asp


Tutoriales y capacitación
=========================

* BorCon 2003 to be be held in San Jose, California November 1-5, 2003
http://info.borland.com/conf2003/


Otros enlaces
=============

* Public Beta: QualityCentral Java Client - by John Kaster
Use a smart client for Borland QualityCentral from wherever you can
run JDK 1.4.x.
http://community.borland.com/article/0,1410,30348,00.html

* San Francisco East Bay Delphi User Group
Our goal is to connect the Delphi developers in the Bay Area. We meet
the 1st Wednesday of every month and have great speakers and sessions.
We organize Delphi events with the help of eBig - the East Bay IT
Group (www.ebig.org). The group will explore Delphi and how Borland's
Delphi 7-8 Studio provides a migration path to Microsoft .NET for
developers as well as Delphi and Linux (Kylix).
http://www.ebig.org/sig/sig.aspx?SIGid=20


Noticias
========

* Altova XMLSPY to be Included in Borland Development Tools
Special Edition of Altova XMLSPY Available in Borland Delphi Studio,
C++ Builder, and C# Builder for the Microsoft .NET Framework.
http://www.altova.com/press/2003-08-28_borland.pdf

________________________________________________________________________

¿Cómo calificaría al boletín? ¡Califique al Boletín Pascal en el ranking
Top 200 Delphi! · http://top200.jazarsoft.com/delphi/rank.php3?id=latium
________________________________________________________________________


¡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://www.sandbrooksoftware.com/cgi-bin/TopSite2/rankem.cgi?id=latium
http://news.optimax.com/topdelphi/links.exe/click?id=70C517ECAE6E
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://www.top219.org/cgi-bin/vote.cgi?delphi&83
http://top100borland.com/in.php?who=20
http://top200.jazarsoft.com/delphi/rank.php3?id=latium
http://213.65.224.200/cgi-bin/toplist.cgi/hits?Id=80
http://www.programacion.net/votar-enlace.php?id=474
http://www.lawebdelprogramador.com/buscar/enlace.php?id=615

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/p0049.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@...
¿Problemas con tu suscripción? boletin-pascal-owner@...
________________________________________________________________________

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

Copyright (c) 2003 por Ernesto De Spirito. Todos los derechos reservados
________________________________________________________________________


Mar, 30 de Sep, 2003 4:38 am

edspirito
Sin conexión Sin conexión
Enviar correo Enviar correo

Archivo adjunto:
p0049.zip
Tipo:
application/octet-stream
Reenviar Mensaje #16 de 20 |
Desplegar mensajes Autor Ordenar por fecha

Boletín Pascal #49 - 30-SEP-2003 Índice 1. Unas palabras del editor 2. Atributos de clase al estilo Delphi 3. Creando un Experto de Delphi La forma más...
Ernesto De Spirito
edspirito
Sin conexión Enviar correo
30 de Sep, 2003
4:42 am
Avanzado

Copyright © 2009 Yahoo! Inc. Todos los derechos reservados.
Normativa de confidencialidad - Condiciones del servicio - Reglas - Ayuda