delphi tframe

delphi - Mostrando las propiedades adicionales del descendiente TFrame en el inspector de objetos



(4)

El inspector de objetos Delphi no muestra las propiedades adicionales de TFrame por diseño. La gente tiende a sugerir el uso de un truco conocido que se usa comúnmente para mostrar las propiedades del descendiente de TForm en el inspector de objetos. El truco es: registrar el módulo personalizado para los descendientes de TForm en Delphi IDE a través de un paquete de tiempo de diseño como:

RegisterCustomModule(TMyFrame, TCustomModule);

El inspector de objetos puede mostrar propiedades adicionales de la instancia de TFrame Descendant de esta manera, pero pierde sus comportamientos de marco mientras está incrustado en un formulario. No es redisponible, no es posible implementar eventos para sus subcomponentes y acepta controles secundarios (lo que no debería ser). Pero se comporta normalmente en su propia área de diseño.

Parece, esos comportamientos provistos por Delphi IDE especialmente solo para TFrame. Problaly no son tipo de instalaciones genéricas.

¿Hay alguna otra manera de lograr esto sin perder comportamientos marco?

Estoy usando Delphi 2007

@Tondrej,

Lea los comentarios sobre el problema, gracias de antemano.

frameunit.dfm:

object MyFrame: TMyFrame Left = 0 Top = 0 Width = 303 Height = 172 TabOrder = 0 object Edit1: TEdit Left = 66 Top = 60 Width = 151 Height = 21 TabOrder = 0 Text = ''Edit1'' end end

unit frameunit; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TBaseFrame = Class(TFrame) protected Fstr: string; procedure Setstr(const Value: string);virtual; published Property str:string read Fstr write Setstr; End; TMyFrame = class(TBaseFrame) Edit1: TEdit; private // This won''t be called in designtime. But i need this to be called in designtime Procedure Setstr(const Value: string);override; end; implementation {$R *.dfm} { TBaseFrame } procedure TBaseFrame.Setstr(const Value: string); begin Fstr := Value; end; { TMyFrame } procedure TMyFrame.Setstr(const Value: string); begin inherited; Edit1.Text := Fstr; // Sadly this code won''t work and Edit1 won''t be updated in designtime. end; end.

unit RegisterUnit; interface procedure Register; implementation uses Windows, DesignIntf, frameunit; procedure Register; var delphivclide: THandle; TFrameModule: TCustomModuleClass; begin delphivclide := GetModuleHandle(''delphivclide100.bpl''); if delphivclide <> 0 then begin TFrameModule := GetProcAddress(delphivclide, ''@Vclformcontainer@TFrameModule@''); if Assigned(TFrameModule) then begin RegisterCustomModule(frameunit.TBaseFrame, TFrameModule); // Just registering that won''t cause Tmyframe to loose its frame behaviours // but additional properties won''t work well. //RegisterCustomModule(frameunit.TMyFrame, TFrameModule); // That would cause Tmyframe to lose its frame behaviours // But additional properties would work well. end; end; end; end.


No, no creo que esto sea completamente posible.

Lo que suelo hacer cuando tengo necesidades similares es simplemente instalar el descendiente de cuadros como un componente por derecho propio. Pero sí, de esa manera pierde mucho del comportamiento de fotograma típico (especialmente en designtime), por ejemplo, ya no puede manipular subcomponentes directamente y los cambios en el fotograma ya no se propagan automáticamente a los formularios que lo utilizan en el tiempo de diseño. para recompilar primero el paquete de tiempo de ejecución que contiene el marco.

Por otra parte, desde una perspectiva de OOP esto no es tan malo. De hecho, impone el concepto de ocultación de la implementación. Aún puede exponer las propiedades individuales y la funcionalidad de los subcomponentes mediante nuevas propiedades y métodos en el propio marco.


¿Qué clase de módulo personalizado estás registrando para tu marco? ¿Qué versión de Delphi estás usando?

De mis experimentos con Delphi 2007, la clase de módulo personalizado que parece funcionar es TFrameModule. Esta clase está contenida en delphivclide100.bpl. Como no hay un delphivclide.dcp correspondiente, debe cargarlo manualmente:

unit FrameTestReg; interface procedure Register; implementation uses Windows, DesignIntf, FrameTest; procedure Register; var delphivclide: THandle; TFrameModule: TCustomModuleClass; begin delphivclide := GetModuleHandle(''delphivclide100.bpl''); if delphivclide <> 0 then begin TFrameModule := GetProcAddress(delphivclide, ''@Vclformcontainer@TFrameModule@''); if Assigned(TFrameModule) then RegisterCustomModule(TTestFrame, TFrameModule); end; end; end.

Mi unidad FrameTest es muy simple, no tiene FrameTest.dfm, solo la declaración del nuevo descendiente TFrame:

unit FrameTest; interface uses Forms; type TTestFrame = class(TFrame) private FHello: string; published property Hello: string read FHello write FHello; end; implementation end.

Usando la clase TFrameModule, todo parece funcionar bien hasta ahora. Puedo crear un nuevo descendiente de TTestFrame para incluirlo en el proyecto y editar sus propiedades publicadas en el Inspector de Objetos, poner instancias de este nuevo descendiente en un formulario en el IDE, editar sus nuevas propiedades publicadas en el Inspector de Objetos, escribir controladores de eventos para sus componentes secundarios, etc. En el recurso .dfm, puedo ver la directiva esperada "en línea" para las instancias. No he encontrado ningún problema hasta ahora, así que tal vez esta es la solución.


procedure TMyFrame.Setstr(const Value: string); begin inherited; Edit1.Text := Fstr; // Sadly this code won''t work and Edit1 won''t be updated in designtime. end;

Creo que es porque no debería funcionar en el momento del diseño. Usted ha registrado TBaseFrame como un módulo personalizado, por lo que las propiedades de TBaseFrame (¡no los descendientes!) Deberían ser editables en el momento del diseño. Delphi IDE solo conoce las propiedades publicadas de la clase que ha registrado; no sabe nada sobre los descendientes y anulaciones que haya realizado en su proyecto. Para que el código funcione en tiempo de diseño, debe incluirlo en la definición de TBaseFrame:

procedure TBASEFrame.Setstr(const Value: string); begin inherited; Edit1.Text := Fstr; end;

o (además de TBaseFrame) registre la definición de TMyFrame como un módulo personalizado.

Trate de entender: Delphi IDE en el momento del diseño solo conoce las cosas que se han registrado en él. No es una desventaja; es un comportamiento lógico.


No hay necesidad de hacerlo en "hackear"

uses ... DMForm, VCLFormContainer, ... procedure Register; begin ... RegisterCustomModule(TYourFrameClass, TFrameModule); // for frames RegisterCustomModule(TYourModuleClass, TDataModuleCustomModule); // for data modules ... end;

Hay otra forma de agregar cuadros también

type TNestableWinControlCustomModule = class (TWinControlCustomModule) public function Nestable: Boolean; override; end; function TNestableWinControlCustomModule.Nestable: Boolean; begin Result := True; end;

+

RegisterCustomModule(TYourFrameClass, TNestableWinControlCustomModule);

Nombres de unidades (probado en XE7):

TCustomModule => DesignEditors

TDataModuleCustomModule => DMForm (designide.dcp)

TWinControlCustomModule => WCtlForm (designide.dcp)

TFrameModule => VCLFormContainer (vcldesigner.dcp)

Supongo que para FireMonkey debería ser posible de manera similar (encuentre fmxdesigner.dcp y compruebe qué hay dentro en Notepad ++)

PD. En versiones anteriores de Delphi existía la metaclase TDataModuleDesignerCustomModule en lugar de TDataModuleCustomModule en la unidad DMDesigner

PPS. Otros nombres de metaclase existentes:

TCustomFormCustomModule

TIDESourceModuleCustomModule