AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

Ein Thema von daniel775 · begonnen am 17. Mär 2013 · letzter Beitrag vom 20. Mär 2013
Antwort Antwort
daniel775

Registriert seit: 27. Nov 2010
46 Beiträge
 
#1

Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

  Alt 17. Mär 2013, 15:31
Hallo Leute,

ich steige gerade in das Thema Komponenten entwickeln ein. Ist es machbar bzw. sinnvoll eine Komponente zu entwickeln, die per eigens entwickelten PropertyEditor eine Form, ein Frame oder ein Panel annehmen kann?

Ich plane so eine Authorisationkomponente zu entwickeln die verschlüsselte Passwörter beispielsweise aus einer Datenbank oder einen FileStream holt, mit dem UserInput abgleicht und die dann entweder gewährt oder eben nicht gewährt.

Dazu hab ich mir gedacht das es zwei Komponenten gibt. Eine eben mit den Verschlüsselungs -und Auswärtungs Methoden und eine Komponente die nur eine Form, ein Frame, oder ein Panel darstellt zur Gestaltungsmöglichkeit eines eigenen Abfragedialogs. Diesen Abfragedialog bindet man dann nach der Gestaltung mit der ersten Komponente. Der Abfragedialog sollte natürlich zur Designzeit editierbar sein.

So brauche ich an geeigneter Stelle nur diese beiden Komponenten auf die Form ziehen, den Dialog editieren und die Properties der Komponenten einstellen und fertig. Dann muss ich mir bei der nächsten Implementierung keine Gedanken mehr zu Verschlüsselung, Entschlüsselung, Datenbankabfragen etc. machen.

Ich habe mir schon Diverse Tuts und HowTo´s angesehen. Aber keins geht so richtig auf dieses spezielle Thema mit einer Formbindnung zur Designzeit ein.

Habt ihr da Ideen, links, Beispielsource oder andere Vorstellungen zur Realiserung. Ich hoffe ich hab mir nicht zu viel vorgenommen?!

Gruß

[Edit]
P.S.: Vielleicht kann MaBuSE ja mal was zu diesem Thema schreiben. Der hat schon bereits schöne Beispiele gepostet (TPerson Component)
[/Edit]

Geändert von daniel775 (17. Mär 2013 um 15:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.222 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

  Alt 17. Mär 2013, 15:58
Ich hatte hier mal etwas zu dem Thema geschrieben.
Das Video (ist nicht wirklich gut, sollte aber den Weg durchaus zeigen) könnte ich nochmal bei Bedarf neu verlinken.

Im Wiki ist das aber auch ganz gut erklärt:
http://docwiki.embarcadero.com/RADSt...machen_-_Index

Man unterscheidet zwischen "Komponentenditor" (gestartet durch Doppelklick auf eine Komponente in der IDE) und Propertyeditor (Eintrag im Objektinspektor z.B. mit einem Elips-Button).

Zu letzerem wollte ich demnächst nochmal etwas im o.g. Thread schreiben (oder ein Video machen), da ich das gestern gerade umgesetzt habe (siehe Bild).
Miniaturansicht angehängter Grafiken
ce.jpg  
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
daniel775

Registriert seit: 27. Nov 2010
46 Beiträge
 
#3

AW: Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

  Alt 17. Mär 2013, 20:06
Irgendwie stehe ich auf dem Schlauch...

Ich habe jetzt in den Properties eine Form und kann dort auch die Eigenschaften bearbeiten. Aber wie könnte ich mir diese in den Designer holen? Ist das so überhaupt machbar?

Wenn ich mir die Kompo auf eine Form ziehe und nicht vor dem schließen des Projekts runter nehme, dann bekomme ich auch eine invalid Pointer Exception!?

@stahli:
Wäre gut wenn der Link zu dem Video erneuert würde.

Hier einwenig Code und im Anhang das Package (in D7 erstellt)

Code:

package MyFormCompo;

{$R *.res}
{$ALIGN 8}
{$ASSERTIONS ON}
{$BOOLEVAL OFF}
{$DEBUGINFO ON}
{$EXTENDEDSYNTAX ON}
{$IMPORTEDDATA ON}
{$IOCHECKS ON}
{$LOCALSYMBOLS ON}
{$LONGSTRINGS ON}
{$OPENSTRINGS ON}
{$OPTIMIZATION ON}
{$OVERFLOWCHECKS OFF}
{$RANGECHECKS OFF}
{$REFERENCEINFO ON}
{$SAFEDIVIDE OFF}
{$STACKFRAMES OFF}
{$TYPEDADDRESS OFF}
{$VARSTRINGCHECKS ON}
{$WRITEABLECONST OFF}
{$MINENUMSIZE 1}
{$IMAGEBASE $400000}
{$DESCRIPTION 'TmyFormComponent mit PropertyEditor'}
{$IMPLICITBUILD OFF}

requires
  designide,
  vcl,
  rtl,
  vclactnband,
  vclx;

contains
  myFormComponent_dsgn in 'myFormComponent_dsgn.pas',
  myFormComponent in 'myFormComponent.pas';

end.
Code:

unit myFormComponent_dsgn;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, DesignIntf, DesignEditors, myFormComponent;

type
  TmyFormPropEditor = class(TClassProperty)
  protected
    FForm: TMyForm;
    function GetForm: TMyForm;
    procedure SetForm(const Value: TMyForm);
  public
    procedure Edit; override;
    function GetAttributes: TPropertyAttributes; override;
  end;

procedure Register;

implementation


procedure Register;
begin
  RegisterPropertyEditor(TypeInfo(TMyForm), TmyFormComponent, 'Form', TmyFormPropEditor);
end;

{ TmyFormPropEditor }

procedure TmyFormPropEditor.Edit;
begin
  inherited;
  if GetForm = nil then
  begin
    FForm := TMyForm.create(nil);
    SetForm(FForm);
  end;

  with TmyFormPropEditor.Create(nil, 0) do
  try
  finally
    Free;
  end;

end;

function TmyFormPropEditor.GetAttributes: TPropertyAttributes;
begin
  Result := inherited GetAttributes + [paDialog];
end;

function TmyFormPropEditor.GetForm: TMyForm;
begin
  if GetOrdValue <> 0 then
  begin
    Result := TMyForm(GetOrdValue);
  end
  else
  begin
    Result := nil;
  end;
end;

procedure TmyFormPropEditor.SetForm(const Value: TMyForm);
begin
  SetOrdValue(Longint(Value));
end;

end.
Code:

unit myFormComponent;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, forms;

type

  TMyForm = class(TForm)
  public
    function getDisplayValue: string;
  end;

  TMdMyItem = class (TCollectionItem)
  private
    FCode: Integer;
    FForm: TCustomForm;
    procedure SetForm(const Value: TCustomForm);
  published
    property Form: TCustomForm read FForm write SetForm;
  end;

  TMdMyCollection = class (TCollection)
  private
    FComp: TComponent;
    FCollString: string;
  public
    constructor Create (CollOwner: TComponent);
    function GetOwner: TPersistent; override;
    procedure Update(Item: TCollectionItem); override;
  end;

  TmyFormComponent = class(TComponent)
  private
    FForm: TMyForm;
    FColl: TMdMyCollection;
    function GetCollString: string;
    procedure SetMoreData(const Value: TMdMyCollection);
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Form: TMyForm read FForm write FForm;
    property MoreData: TMdMyCollection read FColl write SetMoreData;
    property CollString: string read GetCollString;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Beispiele', [TmyFormComponent]);
end;


{ TMyForm }

function TMyForm.getDisplayValue: string;
begin
  result := TMyForm.ClassName;
end;


{ TMdMyCollection }

constructor TMdMyCollection.Create (CollOwner: TComponent);
begin
  inherited Create (TMdMyItem);
  FComp := CollOwner;
end;

function TMdMyCollection.GetOwner: TPersistent;
begin
  Result := FComp;
end;

procedure TMdMyCollection.Update(Item: TCollectionItem);
var
  str: string;
  i: Integer;
begin
  inherited;
  // update everything in any case...
  str := '';
  for i := 0 to Count - 1 do
  begin
    str := str + (Items [i] as TMdMyItem).ClassName;
    if i < Count - 1 then
      str := str + '-';
  end;
  FCollString := str;
end;


{ TMdMyItem }

procedure TMdMyItem.SetForm(const Value: TCustomForm);
begin
end;


{ TmyFormComponent }

constructor TmyFormComponent.Create(AOwner: TComponent);
begin
  inherited;
  FForm := TMyForm.Create(AOwner);
  FColl := TMdMyCollection.Create(Self);
end;

destructor TmyFormComponent.Destroy;
begin
  FForm.Free;
  FForm := nil;
  FColl.Free;
  inherited;
end;

procedure TmyFormComponent.SetMoreData(const Value: TMdMyCollection);
begin
  FColl.Assign(Value);
end;

function TmyFormComponent.GetCollString: string;
begin
  Result := FColl.FCollString;
end;

end.
Angehängte Dateien
Dateityp: zip MyFormComponent.zip (36,1 KB, 5x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.222 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

  Alt 17. Mär 2013, 20:35
Du haust Da noch zu viel durcheinander.

Erst mal erstellst Du ein normales Laufzeitpackage und erstellt darin Deine Komponente, so dass die korrekt funktioniert.
Falls Du auch während der Laufzeit ein Formular brauchst, das dem User eine Bearbeitung ermöglicht, sollte das mit in das Package.
Damit kannst Du die Komponente wie gewünscht nutzen.

Jetzt brauchst Du ein Designtimepackage.
Darin kannst Du "Erweiterungen" für die IDE regestrieren, damit die IDE auch mit Deiner Komponente umgehen kann.
Das ist etwas komplizierter als ein normales Package.

Darin definiert man einen Komponenteneditor bzw. Propertyeditor und dazu passende Formulare, die dann von der IDE geöffnet werden.

Ich habe immer noch nicht verstanden, ob Du nun einen Komponenteneditor oder einen Propertyeditor brauchst.

Zeig mal Deine eigentliche Komponente und deren Eigenschaften und was Du davon in der IDE bearbeiten willst.
Das Video kann ich mal raussuchen oder neu machen, aber sag erst mal genauer, was Du machen willst.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
daniel775

Registriert seit: 27. Nov 2010
46 Beiträge
 
#5

AW: Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

  Alt 17. Mär 2013, 23:31
Zitat:
Erst mal erstellst Du ein normales Laufzeitpackage....
Jetzt brauchst Du ein Designtimepackage
Soll heissen? Ich habe 2 getrennte Packages. Runtime und Designtime. Bedeutet das, dass ich im Designtime Package den Registerkram für die IDE und die eingentliche Komponente habe und im Runtime Package nur die Komponente?

Zitat:
Falls Du auch während der Laufzeit ein Formular brauchst, das dem User eine Bearbeitung ermöglicht, sollte das mit in das Package.
Die Bearbeitung sollte zur Designtime gehen. Zur Runtime hab ich jetzt noch keine Idee was dort per Formular erledigt werden soll.


Zitat:
Zeig mal Deine eigentliche Komponente und deren Eigenschaften und was Du davon in der IDE bearbeiten willst.
Hab ich ja noch nicht. Fange gerade erst damit an. Ich habe das mal in einem kleinen Projekt gebastelt.
- Login mit Benutzer, Passwort und Datenbankabfrage
- Benutzer anlegen und das Passwort verschlüsselt in der Datenbank speichern.
- Benutzer Passwort ändern
- Angemeldet bleiben etc.
Das wollte ich jetzt in eine Komponente packen


Zitat:
...aber sag erst mal genauer, was Du machen willst.
Hab ich ja Eingangs schon erwähnt.
Schön wäre es wenn ich im Object Inspector z.B. auf eine Eigenschaft wie Anmeldedialog [TForm] ... klicke und mir zur Designzeit ein Formular angezeigt wird das ich dann bearbeiten kann. Das Formular muss dann z.B. ein Interface einbinden oder gewisse Textfelder und Buttons enthalten auf die ich dann in der Komponente reagieren kann. Formulargröße, Labels, Groupboxen oder ein Logo sind dann frei wähl oder platzierbar. In der eigentlichen Komponente läuft das ab, was ich in meinem Projekt gemacht habe.

Zur Runtime wird dieser Dialog dann zur Authorisation angezeigt.

Ist das machbar? Oder sollte ich mir lieber eine Klasse schreiben, die ich jedes mal in ein Projekt einbinde.
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.222 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

  Alt 17. Mär 2013, 23:52
Also ich komme noch nicht ganz hinterher...

Ich würde folgendes empfehlen:
Erstelle Dir eine normale Komponente, die Du für Deine IDE registrierst und somit auf Dein Formular ziehen kannst.
In der Komponente kannst Du Eigenschaften veröffentlichen, die Du im Objektinspektor setzen kannst oder auch dynamisch zur Laufzeit.

Da brauchst Du noch keinerlei Komponenten- oder Propertyeditor und auch kein Designtimepackage (einfach Komponente für eine Registerseite registrieren).
Diese Editoren kannst Du bei Bedarf später in einem anderen Package erzeugen, das dann Dein "Komponentenpackage" benutzt. Diese Editoren würden Dir dann ja "nur" eine komfortablere Einstellung der Komponente zur Designtime ermöglichen.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#7

AW: Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

  Alt 18. Mär 2013, 00:02
@daniel775 vielleich habe ich etwas missverstanden aber die Anforderung liest sich für mich etwas überspitzt wie:
Eine Komponente die ich auf was auch immer ziehen in der ich alle Forms meiner Anwendung designen kann?
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
daniel775

Registriert seit: 27. Nov 2010
46 Beiträge
 
#8

AW: Komponente entwickeln mit TCollection, TCollectionItem PropertyEditor

  Alt 20. Mär 2013, 22:32
Warum versteht mich denn keiner?

Vielleicht bin ich zu Detailverliebt.
Ok, vergessen wir es. Mir ist heute etwas eingefallen, wie ich es vielleicht einfacher angehen könnte.

Jetzt mal rein hypothetisch:

- Datei > Neu > Anwendung = Form1
- Form1 + MyComponent
- Datei > Neu > Form = Form2
- Form2 + btnOK + btnCancel + txtUser + txtPass
- Im OI unter Events von MyComponent ein doppelklick auf onInit

Unit MyComponent
Code:

...
type
  TFormClass = class of TForm;
  TInitEvent = procedure(Sender: TObject; DlgFormClass: TFormClass) of Object;
  TMyComponent1 = class
  private
    FDlgFormClass: TFormClass;
    FDialog: TForm;
    FOnInit: TInitEvent;
    procedure setAnmeldeDlg(value: TFormClass);
    function getAnmeldeDlg: TFormClass;
  public
    constructor create;
    destructor destroy;
    procedure Init(Sender: TObject; DlgFormClass: TFormClass);
    procedure Test;
  published
    property AnmeldeDlg: TFormClass read FDlgFormClass write FDlgFormClass;
    property OnInit: TInitEvent read FOnInit write FOnInit;
  end;

...

constructor TMyComponent1.create;
begin
  inherited;
  OnInit := self.Init;
end;

destructor TMyComponent1.destroy;
begin
  if assigned(FDialog) then
    FreeAndNil(FDialog);
  inherited;
end;

procedure TMyComponent1.setAnmeldeDlg(value: TFormClass);
begin
  FDlgFormClass := value;
end;

function TMyComponent1.getAnmeldeDlg: TFormClass;
begin
  result := FDlgFormClass;
end;
procedure TMyComponent1.Init(Sender: TObject; DlgFormClass: TFormClass);
begin
  ...
  self.setAnmeldeDlg(DlgFormClass);
  ...
end;

procedure TMyComponent1.Test;
begin

  freeAndNil(FDialog);

  try

    if not Assigned(FDialog) then
    begin
      FDialog := FDlgFormClass.Create(application);
      if assigned(FDialog) then
      begin
        FDialog.ShowModal;
      end;
    end;

  Except
    showMessage('error');
  end;

end;
Unit Clientform
Code:
procedure TForm1.FormShow(Sender: TObject);
var
  obj: TMyComponent1;
begin

  obj := nil;
  if not assigned(obj) then
    obj := TMyComponent1.create;

  if assigned(obj) then
  begin
    // Aufruf der Objekt Methode Init und übergabe der Parameter Sender und TForm3 als Klassenreferenz an die Komponente.
    // Die anschliessende Instanzierung von TForm3 geschieht in der Komponente durch die Methode Test.
    obj.Init(self, Tform3);
    obj.Test;
    obj.destroy;
  end;

end;
Ich übergebe hier an die Komponente eine Klassenreferenz einer Form, damit der Nutzer dieser Komponente Gestaltungsfreiheit für den
Dialog zur Benutzerauthentifizerung hat.
Innerhalb der Komponente kann dann durch gekapselte Methoden auf die Form zugegriffen bzw. angezeigt werden. Das wollte ich eigentlich erreichen.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +2. Es ist jetzt 22:29 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf