tframe absichern

Rund um die LCL und andere Komponenten
Antworten
arturx
Beiträge: 140
Registriert: Fr 21. Nov 2008, 11:29
OS, Lazarus, FPC: Winux (L 1.0.6.xy FPC 2.6.z)
CPU-Target: 32/64Bit

tframe absichern

Beitrag von arturx »

Lazarus 9.29
Kann man dafür sorgen, dass die Komponenten ( + deren events) eines Frames
nur auf dem Frame selbst veränderbar sind und nicht auf den Formularen,
auf denen der Frame genutzt wird ?

Beispiel :
verschiebt man ein Control im Zielformular (kann ja auch ungewollt passieren),
dann passiert ein entsprechender Eintrag in der lfm Datei des Zielformulars und
damit ist die Position dieses Controls ein für allemal von allen entsprechenden Änderungen
auf dem tframe selbst abgekoppelt ....
- Es sei denn, man entfernt die entsprechenden Einträge wieder per Hand -

Außerdem : wenn ein Control im Nachhinein im Original Frame verschoben wird,
spiegelt sich diese Veränderung nicht in schon auf Formularen abgelegten frames wieder

MAC
Beiträge: 770
Registriert: Sa 21. Feb 2009, 13:46
OS, Lazarus, FPC: Windows 7 (L 1.3 Built 43666 FPC 2.6.2)
CPU-Target: 32Bit

Re: tframe absichern

Beitrag von MAC »

Ich kann leider nicht genau verstehen was du meinst.
Zwar kenne ich mich generell schlecht mit Frames aus, aber wenn es möglich wäre das problem genauer zu erläutern könnten andere dir bestimmt leichter helfen.

Code: Alles auswählen

Signatur := nil;

arturx
Beiträge: 140
Registriert: Fr 21. Nov 2008, 11:29
OS, Lazarus, FPC: Winux (L 1.0.6.xy FPC 2.6.z)
CPU-Target: 32/64Bit

Re: tframe absichern

Beitrag von arturx »

MAC hat geschrieben:Ich kann leider nicht genau verstehen was du meinst.
Danke für die Anregung :
Ich würde gern ein frame wie eine Komponente nutzen :
der Code ist gekapselt und die Erscheinung immer wieder identisch (auch im Nachhinein) .
Mein Problem ist Folgendes :
Wenn ich ein Frame auf ein Formular lege, erscheint das Frame im 1.Augenblick so wie es erstellt wurde.
Unglücklicherweise kann ich in einem auf ein Formular gelegten Frame z.B. die Lage der Komponenten ändern.
so dass es nicht mehr so aussieht wie zu Beginn.
Des Weiteren : wenn ich im ursprünglichen tframe die Lage dieser Komponente verändere,
so spiegelt sich das nicht mehr in den schon abgelegten Frames wieder.
Die Frames verhalten sich nur wie eine Schreib-HIlfe und drücken nicht im Nachhinein alle Änderungen durch.
Ich hoffe, dass es eine Art Schalter gibt, mit dessen Hilfe man den "Vererbungsgrad" des Frames bestimmen kann :
Vererbung : immer wie Original - beliebig änderbar
Ich hoffe, dass mein Anliegen nun etwas leichter verständlich ist.

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: tframe absichern

Beitrag von Socke »

Das von dir gewünschte Verhalten ist mehr oder weniger schon vorhanden. Dazu darf die Eigenschaft TControl.ControlStyle den Wert csOwnedChildrenNotSelectable nicht enthalten. Das Problem ist, dass diese Eigenschaft als public deklariert ist und kann daher nicht im Objektinspektor bearbeitet werden. Du müsstest dies also im Constructor setzen und das Frame als eigne Komponente in Lazarus hineinkompilieren (->Package).

Aus meiner Sicht ist es erheblich einfacher, die Frames erst zur Laufzeit zu erzeugen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

arturx
Beiträge: 140
Registriert: Fr 21. Nov 2008, 11:29
OS, Lazarus, FPC: Winux (L 1.0.6.xy FPC 2.6.z)
CPU-Target: 32/64Bit

Re: tframe absichern

Beitrag von arturx »

Socke hat geschrieben: Dazu darf die Eigenschaft TControl.ControlStyle den Wert csOwnedChildrenNotSelectable nicht enthalten. Das Problem ist, dass diese Eigenschaft als public deklariert ist und kann daher nicht im Objektinspektor bearbeitet werden..
Eine Veränderung von Controlstyle scheint keinerlei Veränderung des Verhaltens auszumachen.

Ein kleiner Wermutstropfen ist in jedem Fall, dass nach Veränderungen des Frames jedesmal Lazarus neu kompiliert werden muss.
Gegenüber dem möglichen Sicherheitsgewinn wäre das allerdings i.m.0. zu verschmerzen.
(--> Müsste in meinem Fall controlstyle nicht sogar unbedingt den Wert csOwnedChildrenNotSelectable enthalten ?)
Socke hat geschrieben: Frame als eigne Komponente in Lazarus hineinkompilieren (->Package).
Das habe ich probiert : 1. Package : Hinzufügen-neu-frame 2. Registercomponents('XYZ',[tframecomp]); 3.Package neu kompilieren
Nun erscheint zwar das Frame brav auf der Komponentenleiste, die platzierten Komponenten (testweise ein Button und ein Edit) sieht man erst zur runtime.
Auch über den OI eingestellte Eigenschaften wie z.B. Color sind erst zur runtime sichtbar. Wieso ist das Frame nicht zur designtime komplett sichtbar ?
Sollte das die Lösung sein ?? : Dadurch, dass man die Einträge des Frames zur Designtime nicht sieht, sind sie natürlich nicht änderbar :shock:
Socke hat geschrieben:... die Frames erst zur Laufzeit zu erzeugen.
Leider geht dann das bequeme/anschauliche visuelle Erstellen verloren.
Außerdem sind die Instanzen des Frames nicht zur Designtime zu sehen...

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: tframe absichern

Beitrag von Socke »

arturx hat geschrieben:(--> Müsste in meinem Fall controlstyle nicht sogar unbedingt den Wert csOwnedChildrenNotSelectable enthalten ?)
Wahrscheinlich hab ich nur einen Dreher in meinen Gedanken gehabt und du hast Recht.
arturx hat geschrieben:Das habe ich probiert : 1. Package : Hinzufügen-neu-frame 2. Registercomponents('XYZ',[tframecomp]); 3.Package neu kompilieren
Nun erscheint zwar das Frame brav auf der Komponentenleiste, die platzierten Komponenten (testweise ein Button und ein Edit) sieht man erst zur runtime.
Auch über den OI eingestellte Eigenschaften wie z.B. Color sind erst zur runtime sichtbar. Wieso ist das Frame nicht zur designtime komplett sichtbar ?
Sollte das die Lösung sein ?? : Dadurch, dass man die Einträge des Frames zur Designtime nicht sieht, sind sie natürlich nicht änderbar :shock:
Vielleicht lässt sich auch hier etwas über CVontrolStyle (oder vielleicht ach ComponentStyle) einstellen. Vielleicht ist es aber auch ein Bug (aber da stecke ich zu wenig drinn, um das beurteilen zu können).
arturx hat geschrieben:
Socke hat geschrieben:... die Frames erst zur Laufzeit zu erzeugen.
Leider geht dann das bequeme/anschauliche visuelle Erstellen verloren.
Außerdem sind die Instanzen des Frames nicht zur Designtime zu sehen...
Meine Frames schaue ich mir zur Designtime nicht im Eltern-Formular an. Dazu gibt es sie schließlich. Meine Frage war: Welche Eigenschaften der Frames muss ich im Eltern-Formular ändern/setzen? Für mich waren das nur die grundlegenden grafischen Eigenschaften: Position, Anker, Parent usw. Den Rest will ich gar nicht verändern (und du doch auch nicht), weshalb das für mich keinen großer Nachteil darstellt.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

arturx
Beiträge: 140
Registriert: Fr 21. Nov 2008, 11:29
OS, Lazarus, FPC: Winux (L 1.0.6.xy FPC 2.6.z)
CPU-Target: 32/64Bit

Re: tframe absichern

Beitrag von arturx »

Socke hat geschrieben: Meine Frames schaue ich mir zur Designtime nicht im Eltern-Formular an. Dazu gibt es sie schließlich. Meine Frage war: Welche Eigenschaften der Frames muss ich im Eltern-Formular ändern/setzen? Für mich waren das nur die grundlegenden grafischen Eigenschaften: Position, Anker, Parent usw. Den Rest will ich gar nicht verändern (und du doch auch nicht), weshalb das für mich keinen großer Nachteil darstellt.
Das war ja gerade mein Aufhänger : wie kann ich verhindern, dass innerhalb des Parentformulars die frames unabsichtlich verändert werden.
Du hast natürlich recht, das Sicherste ist, wenn sie garnicht erscheinen.....
Nun habe ich diesen Weg weiterverfolgt und eine kleine (von tlabel abgeleitete) Komponente geschrieben, die
1.das Laden des Frames organisiert
2.anzeigen (caption) kann, für welchen frame sie steht :

Code: Alles auswählen

type tframeinterface = class(tlabel)
   private
     vframe    : tframe;
   published
      property    frame  : tframe   read  vframe  write setframe;
 end;
Die property zeigt zur Designzeit auch brav das frame an, zur Laufzeit ist ihr jedoch keine Information zu entlocken.
Auf dem 1.Blick ist das schon klar, weil der Frame ja nicht instanziiert ist.
Aber irgendwo muss die Info doch stecken, sonst wäre sie im O.I. nicht sichtbar.
Meine Frage : Wie kommt man zur Laufzeit von innerhalb der Komponente an die Klasse des Frames,
damit man ihn instanziieren kann ? Hilfe !!
Falls Interesse besteht kann ich zum Abschluss gern die komponente ins Forum stellen.

arturx
Beiträge: 140
Registriert: Fr 21. Nov 2008, 11:29
OS, Lazarus, FPC: Winux (L 1.0.6.xy FPC 2.6.z)
CPU-Target: 32/64Bit

Re: tframe absichern

Beitrag von arturx »

arturx hat geschrieben: Aber irgendwo muss die Info doch stecken, sonst wäre sie im O.I. nicht sichtbar.
Meine Frage : Wie kommt man zur Laufzeit von innerhalb der Komponente an die Klasse des Frames,
damit man ihn instanziieren kann ? Hilfe !!
1.Der Klassenname ist mittlerweile erreichbar zur runtime via frametypname (siehe Beispiel):

Code: Alles auswählen

type 
tccl = string;
 tfraneinterface = class(tlabel)
   private
     vframe       : tframe;
     vfrtypname :  string;
   protected
     procedure setframe(const AValue: tframe);
   published
      property  frame  : tframe   read  vframe  write setframe;
      property  frametypname  : string read vfrtypname;
 end;
 
procedure tfointfaceStatic.setframe(const AValue: tframe);
   begin
               vframe      := AValue;
               If assigned(vframe) // designtime !
                  then frametypename := vframe.classname
                  else frametypename := '';
   end;
Gibt es einen Mechanismus, mit dessen Hilfe man den Klassentyp anhand seines Namens bekommen kann ???:
So etwas Ähnliches wie ....function findcomponenttype(Classname) : tcomponentclass.....
Denn den brauche ich für den constructor

arturx
Beiträge: 140
Registriert: Fr 21. Nov 2008, 11:29
OS, Lazarus, FPC: Winux (L 1.0.6.xy FPC 2.6.z)
CPU-Target: 32/64Bit

Re: tframe absichern

Beitrag von arturx »

das Problem ist gelöst, die "Frame Plaztierungskomponente" läuft :
Sie 1.repräsentiert das Frame (label.caption), ist 2.im O.I. zuzuweisen und 3.bewahrt das Frame vor zufälliger Änderung.

1.Voraussetzung : der Frame registriert seine Klasse im Implementierungsteil

Code: Alles auswählen

initialization
       registerclass(tframe1);         
   end;
2.

Code: Alles auswählen

type tframecomp = class(tlabel)
         private
           vframe    : tframe; // nur zur designtime assigned (es gibt ja keine Instanz!)
           vfrclnam  : string; // frameclassname : auch noch zur runtime assigned
      protected
           procedure setframe(const AValue: tframe);
           procedure loaded; override;
     published
         property   frame          : tframe   read vframe   write setframe;
         property   frameclassname : string   read vfrclnam write vfrclnam;//<-- wird gestreamt !!
    end;
//......................
procedure tfointfaceStatic.setframe(const AValue: tframe);
    begin
              If vframe = AValue
                 then exit;
              vframe      := AValue;
              If assigned(vframe) then
                 then begin caption  := objname(vframe);//+owner.name+ frame.caption+.. <-- nach Geschmack
                            vfrclnam := vframe.classname;
                        end
                 else begin  caption := '??';
                             vfrclnam := '';
                       end;
   end;
// .......
procedure tfointfaceStatic.loaded;
        type tframeclass = class of tframe; // <------- !!
         var fra  : tframe;
            pers : tpersistentclass;
    begin 
          inherited loaded;
          visible := (csdesigning in componentstate);
          If (csdesigning in componentstate) then
               begin .....--> caption setzen wie in setframe
                        exit;
              end;
           If trim(frameclassname)='' 
                then exit;
           try
               pers := findclass(frameclassname);//Voraussetzung :  registerclass(tframe2);// <--- !!!
           except
               showmessage('frame "'+frameclassname+'"does not exist or is not registered via registerclass..');
                pers := nil;
            end;
            If assigned(pers) and pers.inheritsfrom(tframe) then
                begin 
                         fra := tframeclass(pers.ClassType).Create(self.owner);// <--- !!!
                    // fra.parent := ...... etc.
               end;
    end;
Natürlich müssen noch notification und create angepasst werden...
Das ist die gekürzte Version einer Komponente, die noch einige weitere Features hat, die für die meisten uninteressant sein dürften.
Ich hoffe, dass das Wesentliche klar wird und der ein oder andere diese Zeilen nützlich findet....

Vieleicht hat hat noch jemand eine Idee, wie man frameclassname per Code streamen kann,
damit diese Published readwrite Property verschwinden kann.

.
Zuletzt geändert von arturx am Fr 17. Dez 2010, 13:42, insgesamt 1-mal geändert.

arturx
Beiträge: 140
Registriert: Fr 21. Nov 2008, 11:29
OS, Lazarus, FPC: Winux (L 1.0.6.xy FPC 2.6.z)
CPU-Target: 32/64Bit

Re: tframe absichern

Beitrag von arturx »

arturx hat geschrieben: Vieleicht hat hat noch jemand eine Idee, wie man frameclassname per Code streamen kann,
damit diese Published readwrite Property verschwinden kann.
Durch den Artikel "streaming_components in der Freepascal wiki http://wiki.freepascal.org/Streaming_components/de" onclick="window.open(this.href);return false;
ist das letzte Problem der Komponente gelöst.
Auch auf die Gefahr hin, dass es für etliche nicht lohnen würde, den Code zu schreiben, mag es für den ein oder anderen doch aufschlussreich sein :

Code: Alles auswählen

type tframecomp = class(tlabel)
             private
               vframe    : tframe; // nur zur designtime assigned (es gibt ja keine Instanz!)
               vfrclnam  : string; // frameclassname : auch noch zur runtime assigned
          protected
               procedure setframe(const AValue: tframe);
               procedure loaded; override;
         published
             property   frame  : tframe   read vframe   write setframe;
        end;
    //......................
    procedure tfointfaceStatic.setframe(const AValue: tframe);
       begin
                  If vframe = AValue
                     then exit;
                  vframe      := AValue;
                  If assigned(vframe) then
                     then begin caption  := objname(vframe);//+owner.name+ frame.caption+.. <-- nach Geschmack
                                vfrclnam := vframe.classname;
                            end
                     else begin  caption := '??';
                                 vfrclnam := '';
                           end;
       end;
  // .......
    procedure tfointfaceStatic.loaded;
            type tframeclass = class of tframe; // <--- natürlich nicht tframe  !!
             var fra  : tframe;
                pers : tpersistentclass;
        begin 
              inherited loaded;
              visible := (csdesigning in componentstate);
              If (csdesigning in componentstate) then
                   begin // .....--> caption setzen wie in setframe
                            exit;
                  end;
               If trim(vfrclnam)='' 
                    then exit;
               try
                   pers := findclass(vfrclnam); // Voraussetzung :  registerclass(tframe2);// <--- !!!
               except
                   showmessage('frame "'+vfrclnam+'"does not exist or is not registered via registerclass..');
                    pers := nil;
                end;
                If assigned(pers) and pers.inheritsfrom(tframe) then
                    begin 
                             fra := tframeclass(pers.ClassType).Create(self.owner);// <--- !!!
                            // fra.parent := ...... etc.
                   end;
        end;
//=========================
procedure tfointfaceStatic.DefineProperties(Filer: TFiler);
    begin inherited DefineProperties(Filer);
             Filer.DefineProperty('XYfrclname' {Name ist egal....},
                               @Readfrclassname,@Writefrclassname,(vfrclnam<>''));
    end;
//=====================
procedure tfointfaceStatic.ReadfrclassName(Reader: TReader);
      begin  vfrclnam := reader.readstring; 
      end;
//========================
procedure tfointfaceStatic.WriteFrclassName(Writer: TWriter);
     begin  writer.Writestring(vfrclnam);  
     end;

Antworten