2008-11-14 6 views
9

L'inspecteur d'objets Delphi n'affiche pas les propriétés supplémentaires de TFrame descendants par conception. Les gens ont tendance à suggérer d'utiliser une astuce connue qui est couramment utilisée pour afficher les propriétés du descendant de TForm dans l'inspecteur d'objets. L'astuce est: l'enregistrement module personnalisé pour les descendants TForm à Delphi IDE par paquet de temps de conception comme:Affichage des propriétés supplémentaires du descendant de TFrame sur l'inspecteur d'objets

RegisterCustomModule(TMyFrame, TCustomModule); 

L'inspecteur d'objets peut présenter des propriétés supplémentaires de l'instance de l'TFrame Descendant de cette façon, mais il perd ses comportements de cadre alors qu'il est intégré dans un formulaire. Non redessinable, impossible d'implémenter des événements pour ses sous-composants et il accepte les contrôles enfants (ce qu'il ne doit pas être). Mais il se comporte normalement dans sa propre zone de conception.

Apparemment, ces comportements fournis par Delphi IDE spécialement pour TFrame. Ils ne sont pas des installations génériques.

Existe-t-il un autre moyen d'y parvenir sans perdre les comportements de trame?

J'utilise Delphi 2007


@Tondrej,

Lire les commentaires pour le problème, merci d'avance.

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, '@[email protected]@'); 
    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. 

Répondre

0

Non, je ne pense pas que ce soit tout à fait possible.

Ce que je fais habituellement quand j'ai des besoins similaires est d'installer simplement le descendant de cadre comme un composant à part entière. Mais oui, de cette façon, vous perdez beaucoup du comportement typique des cadres (en particulier au moment de la conception), par ex. vous ne pouvez plus manipuler directement les sous-composants et les modifications apportées au cadre ne se propagent plus automatiquement aux formulaires qui l'utilisent au moment de la conception. Vous devez d'abord recompiler le package d'exécution qui contient le cadre.

Ensuite, d'un point de vue POO, ce n'est pas trop mal. Il applique réellement le concept de dissimulation de l'implémentation. Vous pouvez toujours exposer les propriétés individuelles et les fonctionnalités des sous-composants via de nouvelles propriétés et méthodes sur le cadre lui-même.

4

Quelle classe de module personnalisé inscrivez-vous pour votre cadre? Quelle version de Delphi utilisez-vous? De mes expériences avec Delphi 2007, la classe de module personnalisé qui semble fonctionner est TFrameModule. Cette classe est contenue dans delphivclide100.bpl. Comme il n'y a pas delphivclide.dcp correspondant vous devez le charger manuellement:

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, '@[email protected]@'); 
    if Assigned(TFrameModule) then 
     RegisterCustomModule(TTestFrame, TFrameModule); 
    end; 
end; 

end. 

Mon unité de FrameTest est très simple, il n'a pas FrameTest.dfm, seule la déclaration du nouveau descendant TFrame:

unit FrameTest; 

interface 

uses 
    Forms; 

type 
    TTestFrame = class(TFrame) 
    private 
    FHello: string; 
    published 
    property Hello: string read FHello write FHello; 
    end; 

implementation 

end. 

En utilisant la classe TFrameModule, tout semble fonctionner correctement jusqu'à présent.Je peux créer un nouveau descendant de TTestFrame à inclure dans le projet et éditer ses propriétés publiées dans l'inspecteur d'objets, placer les instances de ce nouveau descendant sur un formulaire dans l'EDI, éditer leurs nouvelles propriétés publiées dans l'inspecteur d'objets, écrire des gestionnaires d'événements pour leurs composants enfants etc. Dans la ressource .dfm, je peux voir la directive "inline" attendue pour les instances. Je n'ai rencontré aucun problème jusqu'à présent, alors c'est peut-être la solution.

+0

Nice, je havn't cadres utilisés depuis un certain temps, parce que je pense qu'ils ne valent pas la peine. Mais je vais essayer celui-ci. –

0

Je pense que c'est parce que cela ne devrait pas fonctionner au moment du design. Vous avez enregistré TBaseFrame en tant que module personnalisé, donc ce sont les propriétés de TBaseFrame (pas ses descendants !!!) qui devraient être modifiables au moment du design. Delphi IDE ne connaît que les propriétés publiées de la classe que vous avez enregistrée; il ne sait rien des descendants et des remplacements que vous avez faits dans votre projet. Pour faire fonctionner le code au moment de la conception, vous devez soit l'inclure dans la définition de TBaseFrame:

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

ou (en plus de TBaseFrame) enregistrer la définition TMyFrame comme module personnalisé. Essayez de comprendre: L'IDE Delphi au moment du design ne connaît que les choses qui y ont été enregistrées. Ce n'est pas un handicap. c'est un comportement logique.

+1

Cela fait longtemps ... Pour autant que je m'en souvienne, Si j'inscris TMyFrame, ses instances n'ont plus la capacité de redisegnablity et ne montrent que les propriétés de ses descendants. – Serguzest

0

Il n'y a pas besoin de faire de "façon hack"

uses 
... 
    DMForm, 
    VCLFormContainer, 
... 

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

Il y a une autre façon autour d'ajouter des cadres trop

type 
    TNestableWinControlCustomModule = class (TWinControlCustomModule) 
    public 
    function Nestable: Boolean; override; 
    end; 

function TNestableWinControlCustomModule.Nestable: Boolean; 
begin 
    Result := True; 
end; 

+

RegisterCustomModule(TYourFrameClass, TNestableWinControlCustomModule); 

Les noms des unités (testé en XE7):

TCustomModule =>DesignEditors

TDataModuleCustomModule =>DMForm (designide.dcp)

TWinControlCustomModule =>WCtlForm (designide.dcp)

TFrameModule =>VCLFormContainer (vcldesigner.dcp)

Je suppose que pour FireMonkey il devrait être possible de manière similaire (trouver fmxdesigner.dcp & vérifier ce qui est à l'intérieur dans Notepad ++)

PS. Dans les anciennes versions de Delphi il y avait TDataModuleDesignerCustomModule métaclasse au lieu de TDataModuleCustomModule dans l'unité DMDesigner

PPS. Autres noms de métaclasse existants:

TCustomFormCustomModule

TIDESourceModuleCustomModule

Questions connexes