Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Acceder a las propiedades protegidas de un DBGrid (https://www.clubdelphi.com/foros/showthread.php?t=26993)

gluglu 09-11-2005 15:39:39

Acceder a las propiedades protegidas de un DBGrid
 
Hola Amigos !

Intento lo siguiente con Delphi 2005 para poder acceder a la propiedad protegida DBGrid.Row
Código Delphi [-]
type
  THackGrid = class(TDBGrid);
...
procedure TMain.Panel1Enter(Sender: TObject);
var
  N_Row: Integer;
begin
  N_Row := THackGrid(DBGrid1).Row;
  Panel1.Top := 106 + (18*N_Row);
end;
pero al compilar me dá el siguiente error:
"[Error]: E2363 Only methods of descendent types may access protected symbol [Borland.VclDbCtrls]TCustomDBGrid.Row across assembly boundaries"

Alguna recomendación ? Gracias por vuestra ayuda.

Thales 09-11-2005 18:32:15

El error te está diciendo que sólo puedes acceder a la propiedad Row desde algún método definido en la clase THackGrid y no desde la clase TMain

¿Qué es lo que quieres hacer?

gluglu 10-11-2005 15:26:31

Lo que intento precisamente es lo que se indica arriba en el código, al activar un panel ('Panel1'), posicionarlo en la pantalla según la línea del DBGrid1 que tenga selecccionado, concretamente en la posicion Top := 106 + (18*N_Row), siendo N_Row la línea del DBGrid1 que en ese momento se encuentre activa.

El código que tengo es:
Código Delphi [-]
unit Principal;
 
interface
 
uses
  ...
type
  THackGrid = class(TDBGrid);
  TMain = class(TForm)
    ...
    Frame1: TFrameA;
    ...
var
  Principal1: TMain;
 
implementation
...
procedure TMain.Panel1Enter(Sender: TObject);
var
  N_Row: Integer;
begin
  N_Row := THackGrid(Frame1.DBGrid1).Row;
  Panel1.Top := 106 + (18*N_Row);
end;
Nota: El FrameA está definido adicionalmente y el DBGrid1 es parte de ese FrameA, al igual que Panel1.
Gracias de nuevo por la ayuda.

andres1569 10-11-2005 18:49:02

Hola.

Como te dice el mensaje de error, no puedes acceder a dicha propiedad desde otra clase, sólo desde una clase descendiente. Por lo cual, la clase THackGrid debería publicar dicha propiedad (hacerla o bien public o bien published), y luego el mismo código que ya tienes te servirá:

Código Delphi [-]
THackGrid = class(TDBGrid)
public
  property Row;
end;

Por cierto, podrías también dejar la propiedad como protected (pero redeclarándola), y podrías accederla sólo desde la misma unit, pero no desde otras.

Código Delphi [-]
THackGrid = class(TDBGrid)
protected
  property Row;
end;

Saludos

gluglu 10-11-2005 19:11:24

Gracias Andres1569,

He probado de las tres maneras, tanto public, published como protected. Ahora sí me deja compilar correctamente. Pero en todos los casos, al intentar acceder en el código del procedimiento a la función
Código Delphi [-]
N_Row := THackGrid(DBGrid1).Row;
me da un error en tiempo de ejecución "Object Reference not set to an instance of an Object" y no se ejecuta correctamente.

Que puedo estar haciendo mal ?

Nota : Una vez más indicar que utilizo Delphi 2005

andres1569 10-11-2005 19:29:09

Hola de nuevo:

Así a botepronto no sé el motivo, pero ése es el peligro de redeclarar una propiedad protegida, seguramente se dejó así por algo, habría que mirar en la VCL si el método (¿GetRow?) que devuelve dicha propiedad accede a algún objeto o puntero inexistente. O vete tú a saber, ese mensaje parece indicar que el objeto (¿el DBGrid1?) no apunta a una instancia válida. :rolleyes:

Delfino 10-11-2005 19:39:48

Este puede ayudarte..

gluglu 10-11-2005 19:55:52

Gracias Delphino,

Precísamente de la página de delphi.about saqué la idea de acceder a la propiedad protegida.

Lo que no sé es por qué causa concreta no me funciona en el Delphi 2005. La verdad es que no he probado con versiones anteriores.

jachguate 10-11-2005 21:50:40

¿Has checado que el offset en la declaración de la clase sea el mismo en THackGrid y TDBGrid?

gluglu 11-11-2005 14:47:11

Gracias Jachguate,

Me podrías por favor especificar un poco más el concepto de offset de ambas clases, o donde poder especificarlo ?

He probado el mismo código con Delphi 7 y funciona correctamente. La pregunta clave es por qué ...(!) no funciona en Delphi 2005 ? :mad:

Un saludo a todos.

Añado lo siguiente : Acabo de probar otra cosa cuanto menos sospechosa y curiosa. He intentado de la misma manera acceder a una función "no protegida" de THackGrid (por ejemplo, FieldCount) y me da el mismo error.
Código Delphi [-]
  N_Row := THackGrid(DBGrid1).FieldCount;
El error de nuevo es : "Object reference not set to an instance of an Object".

gluglu 11-11-2005 16:47:07

Sigo comiéndome el coco con este tema !

Por lo que sigo consultando en todos los sitios que puedo encontrar, me hago una pregunta a mí mismo y a todos vosotros:

Sería necesario definir correctamente (en Delphi 2005) la propiedad 'Row', dentro de la definición de la clase THackGrid, de esta manera ?
Código Delphi [-]
protected property Row: Integer write SetRow;
Si fuera así, por desconocimiento mío, como se haría de manera correcta y completa?

Un saludo.

andres1569 11-11-2005 19:59:50

Hola, sólo puedo decirte que he probado ese código en Delphi 6.0 y funciona correctamente (haciendo uso de un Frame, como en tu ejemplo)

No creo que tenga que ver con la definición de la propiedad (no hace falta que le asignes ningún método write pues la propiedad ya existe en la clase base). Por el mensaje de error es como si accedieras a una propiedad de un Objeto inexistente, puede que el error esté en otra parte ...

maeyanes 11-11-2005 20:48:31

Solo una pregunta, la aplicación que estás haciendo en Delphi 2005, es Win32 o .NET?

Por que el error que mencionas al principio del hilo me suena mucho a .NET (por aquello de los assembly), y puede ser que no sea posible hacer en .NET eso que quieres. Claro, solo estoy suponiendo, por que se tendría que investigar bien.


Saludos...

gluglu 12-11-2005 00:30:45

La aplicación está hecha en .NET

Durante el transcurso del día, he estado investigando algunos artículos que he encontrado, y parece ser que sí, que con .NET las propiedades que son protegidas, lo son de verdad.

No he probado hacer lo mismo en Delphi 2005 con WIN32.

Uno de los artículos que encontré (en inglés) es :
http://blogs.teamb.com/RudyVelthuis

Cita:

Strict private and strict protected
The private and protected sections of Delphi classes were, according to purists, severely flawed, because they did not prevent access to private or protected fields or methods from code in the same unit. The Delphi RTL and VCL actually use this "friend" concept, so it was not so easy to simply remove it.

But in .NET, private and protected really had to be just that, i.e. no other code should have access to these items (except of course descendant classes to protected items). So we got strict private and strict protected sections. Although this is not documented, it seems that these are also available in the Win32 compiler (thanks to Rob Kennedy for finding out). I'm sure that those who have been asking for this for a long time will be pleased to hear this.
Pero precisamente aquí se hace referencia a : "(except of course descendant classes to protected items)" ... por lo que entiendo que las clases descendientes SI permiten el acceso a dichas propiedades protegidas. ... y es lo que venimos discutiendo todo el tiempo.

Si utilizo la definición como "strict protected" o "strict private", directamente me dá un error de compilación.

De cualquier manera, me sigue pareciendo extraño que el mismo error me dé también cuando accedo a las propiedades públicas ("no protegidas") de la misma clase THackGrid, por lo que me dá la impresión de que algo se me está escapando.

Saludos

roman 12-11-2005 02:19:59

Pues entonces, según lo que entiendo de lo que dice Rudy Velthuis, ahí está la explicación.

Las clases descendientes siempre van a tener acceso a a las propiedades protegidas de sus ancestros, tanto en NET como en Win32. Aquí no hay diferencia. El punto es que en Win32, Delphi permitía acceso a propiedades protegidas incluso desde otras clases, siempre y cuando estuvieran en la misma unidad. Es esta segunda parte la que parece ya no funcionar con NET (o, como dice Rudy que dicen los puristas, ahora sí funciona).

Cuando haces THackGrid(DBGrid1).Row, es justo lo que la segunda parte dice. THackGrid ciertamente es un descendiente de TDBGrid, pero el acceso es desde otra clase (la del formulario), y el acceso es desde la misma unidad que la clase descendiente.

Si te fijas, este truco del moldeo, realmente sigue todas las reglas del juego que marca Delphi 7-, no hay trampa. Es sólo que tales reglas ya no son las mismas para Delphi 2005.

// Saludos

gluglu 12-11-2005 13:25:49

... no exactamente Delphi 2005 ! ... mas concretamente .NET

He probado con Win32 para Delphi 2005 y funciona correctamente. Ahora bien, con las aplicaciones en .NET no funciona.

Rizando el rizo : No sería posible llamar desde el Form (Frame en mi caso particular y ejemplo que venimos discutiendo en este hilo), a una procedure definida en la clase THackGrid, que a su vez accediera a las funciones protegidas del DBGrid definido en el Form ??!!

Lo he probado y supongo que ha sido pedirle demasiado porque evidentemente me vuelvo a encontrar de narices con la imposibilidad de acceder desde precisamente la clase THackGrid a elementos del DBGrid del Form.

Algo así como esto:
Código Delphi [-]
type
THackGrid = class(TDBGrid)
procedure Prueba(Sender: TObject);
public property Row;
end;
 
type
TFrame1 = class(TForm)
DBGrid1: TDBGrid;
Panel1: TPanel;
...
procedure TForm.Panel1Enter(Sender: TObject);
begin
  THackGrid.Prueba(nil);
end;
 
procedure THackGrid.Prueba(Sender: TObject);
var
  n_Row: Integer;
begin
  n_Row := THackGrid(TForm.DBGrid1).Row;
end;
Conclusión : Supongo que en .NET ya no es posible lo que venimos discutiendo, no es verdad ?! :(

Saludos a todos !

roman 12-11-2005 16:35:25

Cita:

Empezado por gluglu
Conclusión : Supongo que en .NET ya no es posible lo que venimos discutiendo, no es verdad ?! :(

Así es. No porque yo lo sepa sino que me baso en lo dicho por Rudy Velthuis, persona muy repetable.

Toma en cuenta que el moldeo con una clase descendiente no es más que una forma rápida para evitar tener que crear una componente descendiente con "todas las de la ley". Lo indicado es que desciendas una componente de TDBGrid y sea ésa la que coloques en tu frame en lugar del DBGrid original.

// Saludos


La franja horaria es GMT +2. Ahora son las 14:38:14.

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