Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 23-11-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
En qué versión de Delphi se ha corregido cierto problema en Vcl.OleCtrls.pas

Hola a todos,

Tratando de solventar el problema descrito en este artículo, he hecho los cambios en la unidad Vcl.OleCtrls.pas, tal como se indica en el artículo enlazado. Parece ser que se trata de un error bastante antiguo y que, al menos en Delphi XE2, todavía existe. Ahora bien, mi pregunta es, ¿podéis revisar la unidad Vcl.OleCtrls.pas en vuestro Delphi y decirme si el error está corregido, así como la versión de Delphi de que se trate?

Creo que se entiende lo que quiero decir, pero, puesto que no sea así, por favor, decídmelo y trato de explicarlo mejor.

¡Muchas gracias a todos!
__________________
David Esperalta
www.decsoftutils.com

Última edición por dec fecha: 23-11-2015 a las 20:21:51.
Responder Con Cita
  #2  
Antiguo 23-11-2015
JOSEPE JOSEPE is offline
Miembro
 
Registrado: feb 2005
Posts: 45
Poder: 0
JOSEPE Va por buen camino
Thumbs up

En Delphi 10 Seattle.
Saludos.

Código Delphi [-]
function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;
var
  Temp: TVarData;
begin
  GetProperty(Index, Temp);
  Result := IDispatch(Temp.VDispatch);
  IDispatch(Temp.VDispatch) := nil;
end;
Responder Con Cita
  #3  
Antiguo 23-11-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Gracias por responder JOSEPE. Es curioso, porque, el código de Delphi 10 no es el mismo que en Delphi XE2 (que se supone todavía es erróneo) pero también es distinto a la solución propuesta en el artículo enlazado:

Cita:
Empezado por Código en Vcl.OleCtrls.pas de Delphi XE2
Código Delphi [-]
function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;
var
  Temp: TVarData;
begin
  GetProperty(Index, Temp);
  Result := IDispatch(Temp.VDispatch);
end;
Cita:
Empezado por Solución propuesta en el artículo enlazado
Código Delphi [-]
function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;
var
  Temp: TVarData;
begin
  GetProperty(Index, Temp);
  Pointer(Result) := Temp.VDispatch;
end;
¿Alguien se anima con otra versión de Delphi? ¿Y qué hay de la diferencia entre el código propuesto como solución en el artículo y el código que el compañero muestra y se encuentra en Delphi 10?

Gracias de nuevo a todos.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #4  
Antiguo 23-11-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Por cierto JOSEPE, ¿podrías poner aquí también la implementación de "GetIUnknownProp" en Delphi 10? Está al lado de la de "GetIDispatchProp" y ambos parecen estar implicados en el problema.

¡Gracias!
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #5  
Antiguo 24-11-2015
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Hola David.

El artículo que enlazas contiene esto en la cabecera:
Cita:
Empezado por Marc Durdin
Update 21 Sep 2015: This bug has been fixed in Delphi 10 Seattle.
Creo que podrías asumir que la falla está presente en todas las versiones anteriores. Aunque da más confianza cuando algún documento oficial del fabricante lo confirma (al menos esta fecha de corrección nos permite inferirlo).

Ahora bien, revisando su propuesta y la solución que Embarcadero implementó, te diría que ambas son equivalentes en resultado. Sin embargo, no hace falta sabiduría para darnos cuenta de que la segunda opción consume más ciclos de CPU, mientras que la primera es parca pero más eficiente. En la solución de Embarcadero, la sentencia "Result := IDispatch(Temp.VDispatch)" obtiene una copia de la interfaz contenida en Temp.VDispatch e incrementa en uno su contador de referencias. Luego la sentencia "IDispatch(Temp.VDispatch) := nil" disminuye en 1 ese mismo contador, lo cual, dada la sentencia anterior, se vuelve necesario. En cambio, en la solución que Marc Durdin propone, "Pointer(Result) := Temp.VDispatch" obtiene una copia de la interfaz sin incrementar su contador de referencias, por lo tanto sin necesidad de hacer un decremento explícito.

La solución del artículo es más elegante y eficiente. Según los enlaces del autor, al parecer lo tomó de aquí. Mientras que el programador que escribió la corrección en Delphi Seattle parece haberse limitado a añadir una línea de parche, sin atender el problema de fondo. (La única justificación, aunque ligera, que podríamos darle a añadir esa línea de más, es que estuviera previendo que Embarcadero revisara el manejo de la estructura de los variants por parte del compilador).

La causa del problema reside en que la estructura interna de un valor Variant —el tipo TVarData— es, valga la redundancia, un registro con parte variante. El compilador de Delphi no admite que en la parte variante de un record aparezca declarado un campo cuyo tipo lo haga emplear un contador de referencias, como es el caso de las cadenas de caracteres, las interfaces y algunos otros. Así que, para salvar esa limitante —que es bastante razonable y justificada—, algunos campos del registro variante TVarData fueron declarados como punteros genéricos:
Código Delphi [-]
  TVarData = packed record
    ...
                      case Integer of
                        varDispatch: (VDispatch: Pointer);
                        ...
                        varUnknown:  (VUnknown: Pointer);
                        ...
                        varString:   (VString: Pointer);
                        ...
                        varUString:  (VUString: Pointer);
    ...
El problema con estos es que, al quedar el registro fuera de ámbito (la variable local Temp queda fuera de ámbito cuando GetIDispatchProp llega a su end), nada se encarga de revisarlos para ver si contienen algo que haga falta ser liberado. Muy al contrario de si VDispatch fuera un campo normal declarado de tipo IDispatch en lugar de Pointer.

Así que al extraer valores que usan contadores de referencias de variables, parámetros, propiedades o campos explícitamente declarados con un tipo "comodín", como el Pointer, es menester recordar que ahí hay algo que habrá de ser descontado tras la extracción (solución de Embarcadero), o bien, evitar que aumente el contador utilizando un molde de tipo sobre el receptor (solución del artículo). El truco con esta opción es que el contador se mantiene intacto, y transfiere la responsabilidad de reducirlo al receptor del valor. En el ejemplo que nos ocupa, GetProperty pone en Temp.VDispatch una interfaz a la cual le incrementa en uno su contador de referencias, y la responsabilidad de restar ese 1 queda en el llamador de GetIDispatchProp (puesto que a él le pertenece Result). El intermediario GetIDispatchProp ni se entera de que está contrabandeando una interfaz.

Espero esta pequeña contribución dé algún valor al tema.

Al González.

P.D. David: Te confirmo que en Delphi XE7 Update 1 el código de los métodos mencionados aún presentaban esa falla:
Código:
function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;
var
  Temp: TVarData;
begin
  GetProperty(Index, Temp);
  Result := IDispatch(Temp.VDispatch);
end;

...

function TOleControl.GetIUnknownProp(Index: Integer): IUnknown;
var
  Temp: TVarData;
begin
  GetProperty(Index, Temp);
  Result := IUnknown(Temp.VUnknown);
end;

Última edición por Al González fecha: 24-11-2015 a las 01:16:20.
Responder Con Cita
  #6  
Antiguo 24-11-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola a todos,

Qué buena respuesta Al, me alegro mucho de no haber leído que el problema se ha resuelto en Delphi 10, con tal de haber podido leer tu respuesta. Muchas gracias, de verdad, puesto que además uno dudaba de qué solución emplear (la del artículo o la de Delphi 10) y ahora parece claro cuál puede ser mejor.

El caso es que debe haber mucha confusión en todo esto, seguramente, porque algunos que nos llamamos a nosotros mismos programadores, en realidad pecamos de no saber de la misa la media de muchísimas cosas, como queda claro en mi caso, sin ir más lejos, con este problema conque me he topado.

No sé si me excusará algo el hecho de que, buscando por internet sobre los problemas de la "ocupación" de memoria del control "TWebBrowser", algún que otro bien considerado programador (del que jamás dudaría de su capacidad) no llegó tampoco a acertar con una solución. Pero seguro que no tuvo tiempo.

El caso es que de lo que dices entiendo que este problema puede estar también en otro tipo de controles, no sólo en el "TWebBrowser", y, en verdad puede ser un problema bastante curioso, puesto que este control en concreto (a fuerza de crear y destruir unos cuantos de ellos) puede terminar provocando un grave error.

Yo no había notado el problema hasta mi proyecto App Builder, puesto que este hace un uso intensivo (demasiado intensivo, en mi opinión, habría que tratar de reducirlo al máximo) del control "TWebBrowser". Un usuario del programa me reportó el problema, que, yo también tenía, sin llegar nunca a un "out of memory" como en su caso.

Ahora parece que el problema está solucionado, aunque, como vemos, hay que tocar algunas cosas como los componentes de "EmbeddedWB" (que yo uso en mi programa) y hasta la VCL... que es la primera vez que toco en todos estos años trabajando con Delphi. Jamás había tenido que tocar nada de la VCL hasta hoy.

En fin, cualquier otro comentario será bienvenido, pero, vuelvo a darte las gracias por tu estupenda respuesta Al.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #7  
Antiguo 24-11-2015
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por dec Ver Mensaje
Jamás había tenido que tocar nada de la VCL hasta hoy.
Es preferible que no lo hagas. Yo he tenido la inmensa fortuna de conseguir darle la vuelta a este tipo de problemas casi siempre que me he topado con alguno, sin tener que modificar código fuente ajeno. Más importante aún si tal código no es libre e implica volver a hacer lo mismo con otras versiones de Delphi.

Eché un vistazo a TOleControl y su método GetProperty:
Código Delphi [-]
procedure TOleControl.GetProperty(Index: Integer; var Value: TVarData);
var
  Status: HResult;
  ExcepInfo: TExcepInfo;
begin
  CreateControl;
  Value.VType := varEmpty;
  Status := FControlDispatch.Invoke(Index, GUID_NULL, 0,
    DISPATCH_PROPERTYGET, DispParams, @Value, @ExcepInfo, nil);
  if Status <> 0 then DispatchInvokeError(Status, ExcepInfo);
end;
Creo que hay oportunidad de sustituir el valor del campo FControlDispatch ahí visto, que es una interfaz, por una segunda interfaz que envuelva a la primera, pero copiando desde el nuevo método Invoke el valor devuelto por el viejo Invoke en el seudo-variante Value (cuando éste sea una interfaz) hacia una variable que posteriormente usemos para reducir el contador de forma controlada, en tiempo y forma. Evitando así la inundación y potencial desborde de la memoria.

Ahora no dispongo de mucho tiempo, pero en estos días podemos desarrollarlo aquí mismo entre los compañeros interesados en el tema. Podría ser un buen ejercicio colectivo.

Un saludo.

Al.
Responder Con Cita
  #8  
Antiguo 24-11-2015
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.037
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por Al González Ver Mensaje
Ahora no dispongo de mucho tiempo, pero en estos días podemos desarrollarlo aquí mismo entre los compañeros interesados en el tema. Podría ser un buen ejercicio colectivo.
Un saludo.
Al.
Sería estupendo, aunque la mayoría solamente podamos participar viendo trabajar a los verdaderos maestros
Responder Con Cita
  #9  
Antiguo 24-11-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola a todos,

Tampoco a mí me hace mucha gracias tocar la VCL, pero, digo un poco lo que Casimiro: buscando una respuesta al problema la encontré, dicho de otra forma: jamás hubiese podido idear la solución al problema en cuestión. Afortunadamente existís los que sabéis más que nosotros. La solución que propones implica poder usar nuestro propio "OleControl" modificado e "interpuesto", si no me equivoco, de modo que no hiciese falta tocar la VCL. Yo me comprometo a hacer las pruebas que sean menester y poco más, me temo.

Ciertamente la VCL no es libre, pero, en todo caso, creo que se trata de algo más que comprensible, si no existe otra forma de hacerlo. Al fin y al cabo estamos tratando de solucionar un problema que puede causar un error grave de desbordamiento de memoria. Tal vez no se pueda/deba modificar la VCL, pero, a falta de otra solución, ¿quién estaría dispuesto a continuar con el problema estando ahí disponible una posible solución? Si es cierto que se trata de un bug de Delphi, han tenido desde 1999 para solucionarlo.

¡Gracias de nuevo Al y gracias a todos!
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #10  
Antiguo 24-11-2015
JOSEPE JOSEPE is offline
Miembro
 
Registrado: feb 2005
Posts: 45
Poder: 0
JOSEPE Va por buen camino
Thumbs up

Aunque creo que ya no es necesario, igual pongo el metodoGetIUnknownProp incluido en Delpi 10 Seattle .
Saludos.

Código Delphi [-]
function TOleControl.GetIUnknownProp(Index: Integer): IUnknown;
var
  Temp: TVarData;
begin
  GetProperty(Index, Temp);
  Result := IUnknown(Temp.VUnknown);
  IUnknown(Temp.VUnknown) := nil;
end;
Responder Con Cita
  #11  
Antiguo 24-11-2015
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
A partir de aquí, de mi parte son solo ideas, pero te invito a intentarlo y ojalá lo consigamos.

Comienza por crear un ayudante de clase (class helper) para TOleControl llamado TOleControlHelper, a fin de acceder de manera formal y segura a su campo privado FControlDispatch. El ayudante debe permitir sobrescribir el valor de ese campo. Y crea una clase nueva llamada TOleControlDispatchFixer que implemente la interfaz IDispatch y contenga un campo protegido llamado InternalDispatch de tipo IDispatch, aunque de momento los métodos de la clase estén vacíos. Usaremos una instancia de esta clase para sustituir y envolver (wrap) a la interfaz que TOleControl guarda en FControlDispatch.

Si algo no compila hazlo saber, para contar con la ayuda de los compañeros. Yo regreso luego.
Responder Con Cita
  #12  
Antiguo 24-11-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola a todos,

Tratando de comenzar con lo que dices, Al, he querido preparar un programa que sirva a modo de ejemplo, y, me he encontrado con alguna cosa "rara" que paso a comentar:

1º Si en un Timer creo un botón (TButton) y lo destruyo a continuación, repetidamente, noto que el programa no consume ni un ápice de memoria más, quedándose en la memoria que ocupaba al principio de su ejecución. (1)

2º Si en un Timer creo un navegador (TWebBrowser) y lo destruyo a continuación, repetidamente, noto que el programa aumenta el consumo de memoria, incluso con el parche efectuado en "Vcl.OleCtrls.pas". ¡De hecho el método parcheado "GetIDispatchProp" no se ejecuta! (2)

3º Si en un Timer creo un navegador (TEmbeddedWB) y lo destruyo a continuación, repetidamente, noto que el programa automenta el consumo de memoria, incluso con el parche efectuado en "Vcl.OleCtrls.pas". ¡Pero esta vez sí que se ejecuta el método parcheado "GetIDispatchProp"!

Esto me hace pararme a pensar qué demonios puede estar pasando, habida cuenta de que, en efecto, en mi programa sí que he notado mejoría en el consumo de memoria RAM, si bien es cierto que no se pueden comparar mi programa con el ejemplo que he hecho para hacer estas pruebas: probablemente mi programa consuma mucha más memoria, de modo que tal vez mucha de ella se libere, pero otra más o menos pequeña parte no lo haga, es decir, que parece que el problema sigue estando ahí, hasta cierto punto, como parecen demostrar las pruebas que estoy haciendo.

Notas:

1. Sólo si no destruyo los botones creados la memoria aumenta muy poco a poco pero de forma apreciable.

2. Esto me llama la atención doblemente, porque, el compañero que propuso la solución del artículo enlazado, al menos quien escribió el artículo... estaba usando un componente "TEmbeddedWB" y no directamente un "TWebBrowser".
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #13  
Antiguo 24-11-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola de nuevo,

Más sorpresas... me encuentro en la unidad "SHDocVw_EWB" del componente "EmbeddedWB" con lo siguiente:

Código Delphi [-]
uses
  EwbAcc, Windows, ActiveX, Classes 
  {$IFDEF USE_OleCtrlsFix}, OleCtrlsFix{$ENDIF}, OleCtrls, 
   OleServer, StdVCL{$IFDEF DELPHI6_UP}, Variants{$ENDIF};

Y aquí la unidad en cuestión:

Código Delphi [-]
unit OleCtrlsFix;

interface

uses
  OleCtrls, Windows, Messages;

type
  TOleControlFix = class(TOleControl)
  protected
  //  procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
    function GetIDispatchProp(Index: Integer): IDispatch;
    function GetIUnknownProp(Index: Integer): IUnknown;
  end;

implementation

{ TOleControlFix }

{procedure TOleControlFix.WMPaint(var Message: TWMPaint);
var
  PS: TPaintStruct;
begin
  if Message.DC = 0 then
  begin
    BeginPaint(Handle, PS);
    EndPaint(Handle, PS);
  end;
end; }

function TOleControlFix.GetIDispatchProp(Index: Integer): IDispatch;
var
  Temp: TVarData;
begin
  GetProperty(Index, Temp);
// Result := IDispatch(Temp.VDispatch); ***** Change to:
  Pointer(Result) := Temp.VDispatch; //this avoids the extra AddRef
end;

function TOleControlFix.GetIUnknownProp(Index: Integer): IUnknown;
var
  Temp: TVarData;
begin
  GetProperty(Index, Temp);
// Result := IDispatch(Temp.VUnknown); ***** Change to:
  Pointer(Result) := Temp.VUnknown; //this avoids the extra AddRef
end;
end.

Voy a ver qué pasa con "USE_OleCtrlsFix"... pero, ¿no es esto algo parecido a lo que pretendemos hacer? Ay madre...

Actualizo: No; definitivamente no es lo que se pretende hacer, empero, tal vez sea suficiente y una forma de no tocar la VCL... desde luego acabo de encontrar dicha opción desactivada en el archivo "EWB.inc": voy a probar a activarla a ver qué ocurre...
__________________
David Esperalta
www.decsoftutils.com

Última edición por dec fecha: 24-11-2015 a las 19:45:30.
Responder Con Cita
  #14  
Antiguo 24-11-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Aquí el resultado de algunas pruebas. La opción "USE_OleCtrlsFix" que viene con el componente "EmbeddedWB" está desactivada por defecto y marcada como "experimental". Si la activamos, he comprobado en mi programa que no se soluciona el problema. Resulta que aunque el método "GetIDispatchProp" de la clase interpuesta se ejecuta, también lo hace el de la unidad "Vcl.OleCtrls.pas" (?) de modo que el problema persiste.

Lo único que parece solucionar el problema es el parche en la unidad "Vcl.OleCtrls.pas", quiero decir, que, si pensábamos usar una clase interpuesta, tal vez esto no funcione. Pero creo que tú, Al, ibas un poco más allá...

Me gustaría saber porqué el ejemplo que he preparado incrementa el consumo de memoria (mucha o poca) incluso con el parche en "Vcl.OleCtrls.pas", pero, al menos, si es que el problema se sigue produciendo (por algún otro lado) lo cierto es que parece menor que sin el parche, al menos por las pruebas realizadas en mi programa.
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
  #15  
Antiguo 24-11-2015
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
¡Harás que me desvele de nuevo, David!

Aun cuando un buen samaritano tenga disponibles estas horas de normal vigilia para aclararnos esas dudas, yo en la noche (del 24 de noviembre de este año ) estaré leyendo con mucho interés lo que has encontrado y lo que derive de ello.

Off topic: Espero encontrar pronto un programador que me ayude con varias cosas que tengo acá.
Responder Con Cita
  #16  
Antiguo 24-11-2015
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
Hola,

Tranquilo majo... en realidad no corre prisa alguna, puesto que, de momento el problema se ha mitigado mucho o puede decirse que ha desaparecido, quiero decir, en mi programa. Estaría bien aclararse un poco más, pero, como digo, no corre ninguna prisa, ¡así que nada de desvelos!
__________________
David Esperalta
www.decsoftutils.com
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Actualizar a Delphi XE desde cualquier versión de Delphi (hasta fin de mes) rrf Varios 0 11-03-2011 17:12:05
que tan cierto es que el 25 salio delphi 2009 gloriamab30 Noticias 1 05-09-2008 23:55:31
(Corregido) Introduccion a InstantObjects Ezecool OOP 0 05-07-2007 22:37:16
Problema con Versión 10 de Indys AGAG4 Internet 4 01-02-2006 16:50:27
Ejecutar aplicacion delphi cada cierto tiempo mgaray API de Windows 9 28-01-2005 19:16:20


La franja horaria es GMT +2. Ahora son las 17:22:28.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi