2008-11-14 3 views
9

Der Delphi-Objekt-Inspektor zeigt die zusätzlichen Eigenschaften von TFrame-Nachkommen nicht von Entwurf an. Die Benutzer neigen dazu, einen bekannten Trick vorzuschlagen, der häufig verwendet wird, um die Eigenschaften von TForm-Nachkommen im Objektinspektor anzuzeigen. Der Trick ist: Registrieren von benutzerdefinierten Modul für TForm Nachkommen zu Delphi IDE über Design-Zeit-Paket wie:Anzeigen der zusätzlichen Eigenschaften von TFrame-Nachkommen im Objektinspektor

RegisterCustomModule(TMyFrame, TCustomModule); 

Objektinspektor zusätzliche Eigenschaften des TFrame Nachkommen der Instanz mit dieser Art und Weise zeigen kann, aber es verliert seinen Rahmen Verhalten während es eingebettet in eine Form. Nicht redesignable, nicht möglich, Ereignisse für seine Unterkomponenten zu implementieren, und es akzeptiert untergeordnete Steuerelemente (was nicht möglich ist). Aber es verhält sich normalerweise in seinem eigenen Entwurfsbereich.

Sieht aus wie diese Verhaltensweisen von Delphi IDE speziell für TFrame bereitgestellt. Sie sind wahrscheinlich keine generischen Einrichtungen.

Gibt es eine andere Möglichkeit, dies zu erreichen, ohne das Rahmenverhalten zu verlieren?

Ich verwende Delphi 2007


@Tondrej,

Lesen Sie Kommentare für das Problem, Dank im Voraus.

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. 

Antwort

0

Nein, ich glaube nicht, das in vollem Umfang möglich ist.

Was ich normalerweise mache, wenn ich ähnliche Bedürfnisse habe, ist einfach den Frame-Nachkommen als eine eigenständige Komponente zu installieren. Aber ja, auf diese Weise verlieren Sie eine Menge des typischen Rahmenverhaltens (insbesondere zur Designzeit), z. Sie können Unterkomponenten nicht mehr direkt bearbeiten, und Änderungen am Rahmen werden nicht mehr automatisch an Formulare weitergegeben, die sie zur Entwurfszeit verwenden. Sie müssen das Laufzeitpaket, das den Rahmen enthält, zuerst neu kompilieren.

Andererseits ist das aus einer OOP-Perspektive nicht so schlimm. Es erzwingt tatsächlich das Konzept des Implementierungsverbergens. Sie können einzelne Eigenschaften und Funktionen von Unterkomponenten weiterhin über neue Eigenschaften und Methoden für den Rahmen selbst verfügbar machen.

4

Welche benutzerdefinierte Modulklasse registrieren Sie für Ihren Rahmen? Welche Version von Delphi verwenden Sie?

Aus meinen Experimenten mit Delphi 2007 scheint die benutzerdefinierte Modulklasse TFrameModule zu funktionieren. Diese Klasse ist in delphivclide100.bpl enthalten. Da es keine entsprechenden delphivclide.dcp ist, müssen Sie es manuell laden:

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. 

Meine FrameTest Einheit ist sehr einfach, man braucht nicht FrameTest.dfm hat, nur die Erklärung des neuen TFrame Nachkomme:

unit FrameTest; 

interface 

uses 
    Forms; 

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

implementation 

end. 

Mit der TFrameModule-Klasse scheint bisher alles in Ordnung zu sein.Ich kann einen neuen Nachkomme von TTestFrame erstellen, um in das Projekt aufzunehmen und seine veröffentlichten Eigenschaften im Objektinspektor zu bearbeiten, Instanzen dieses neuen Nachfahrens auf ein Formular in der IDE zu setzen, ihre neuen veröffentlichten Eigenschaften im Objektinspektor zu bearbeiten, Ereignishandler für zu schreiben ihre untergeordneten Komponenten usw. In der .dfm-Ressource kann ich die erwartete Inline-Direktive für die Instanzen sehen. Ich habe bis jetzt kein Problem damit gefunden, vielleicht ist dies die Lösung.

+0

Nizza, havn't ich gebrauchte Frames für einige Zeit, weil ich denke, sie sind nicht der Mühe wert. Aber ich werde es versuchen. –

0
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; 

Ich denke, es ist, weil es nicht zur Entwurfszeit arbeiten sollte. Sie haben TBaseFrame als ein benutzerdefiniertes Modul registriert, daher sind es die Eigenschaften des TBaseFrames (nicht deren Nachkommen !!!), die zur Entwurfszeit editierbar sein sollten. Delphi IDE kennt nur die veröffentlichten Eigenschaften der von Ihnen registrierten Klasse. Sie wissen nichts über Nachkommen und Außerkraftsetzungen, die Sie in Ihrem Projekt vorgenommen haben. Um den Code zu arbeiten zur Entwurfszeit zu machen, sollten Sie es entweder in der TBaseFrame Definition sind:

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

oder (zusätzlich zu TBaseFrame) registrieren die TMyFrame Definition als benutzerdefinierten Modul.

Versuchen Sie zu verstehen: Delphi IDE zur Entwurfszeit weiß nur über Dinge, die darin registriert wurden. Es ist kein Handicap; Es ist ein logisches Verhalten.

+1

Es war lange Zeit .. Soweit ich mich erinnere, wenn ich TMyFrame registriere, haben seine Instanzen nicht mehr die Fähigkeit redisegnablity und es zeigt nur seine Nachkommen Eigenschaften. – Serguzest

0

Es gibt keine Notwendigkeit, in "Hack way"

uses 
... 
    DMForm, 
    VCLFormContainer, 
... 

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

Es gibt eine andere Art und Weise zu tun, um Rahmen zu

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

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

+

RegisterCustomModule(TYourFrameClass, TNestableWinControlCustomModule); 

Namen der Einheiten hinzufügen (getestet in XE7):

TCustomModule =>DesignEditors

TDataModuleCustomModule =>DMForm (designide.dcp)

TWinControlCustomModule =>WCtlForm (designide.dcp)

TFrameModule =>VCLFormContainer (vcldesigner.dcp)

Ich nehme an, dass für Firemonkey es in ähnlicher Weise möglich sein soll (fmxdesigner.dcp & Check finden, was in Notepad ist innerhalb ++)

PS. Bei älteren Delphi-Versionen gab es TDataModuleDesignerCustomModule metaclass statt TDataModuleCustomModule in Einheit DMDesigner

PPS. Andere bestehende Metaklasse Namen:

TCustomFormCustomModule

TIDESourceModuleCustomModule

Verwandte Themen