Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Eigene Komponente von TCustomControl > Eigenschaftseditor! (https://www.delphipraxis.net/67231-eigene-komponente-von-tcustomcontrol-eigenschaftseditor.html)

cherry 11. Apr 2006 14:33


Eigene Komponente von TCustomControl > Eigenschaftseditor
 
Tach wohl...

Ich will mir mein eigener Button Programmieren, wie bereits im Titel erwähnt, leite ich meine
Komponente von TCustomControl ab...

Ich möchte jetzt, um die Farbe des Buttons verändern zu können, ein Eigenschaftseditor
einbinden (TColorProperty)

Nur habe ich mühe dabei..
Das Konkrete Fehlermeldung lautet:
[Fehler] EButton_API.pas(10): Undefinierter Bezeichner: 'TPropertyColor'

Hier meine zwei Dateien:
Zwei Dateien sind notwendig weil es nicht erlaubt ist die Editoren ausserhalb IDE
zu verwenden oder so.. Hier die Erklärung dazu

Datei1: EButton.pas:

Delphi-Quellcode:
unit EButton;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Graphics;

type
  TEButton = class(TCustomControl)
  private
    FFont : TFont;
    { Private-Deklarationen }
  protected
    procedure Paint; override;
    { Protected-Deklarationen }
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    { Public-Deklarationen }
  published
    property Font: TFont read FFont write FFont;
    { Published-Deklarationen }
   
  end;

procedure Register;

implementation

procedure Register; //Procedure wird bei der Komponenteninstallation verwendet!
begin
  RegisterComponents('RComponents', [TEButton]);
end;

{------------------------------------------------}
{                                                }
{                                                }
{                  TRButton                     }
{                                                }
{------------------------------------------------}

constructor TEButton.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 FFont:=TFont.Create;
end;

destructor TEButton.Destroy;
begin
 FFont.Free;
 inherited Destroy;
end;

procedure TEButton.Paint;
begin
 inherited;//Zeichen Procedure des Vorfahren aufrufen.
 if csDesigning in ComponentState then //Wenn sich die Komponente in Entwicklung befindet.
 begin
  {Zeichung eines Rahmens}
   Canvas.Brush.Style := bsSolid;
   Canvas.Brush.Color := clblue;
   Canvas.Pen.Color := clblack;
   Canvas.Rectangle(0,0,width,height);//Rechteck zeichnen

   {Namen der Komponente in die Mitte schreiben}
   canvas.Font := FFont;
   canvas.TextOut((width - Canvas.TextWidth(Name)) div 2,(height - Canvas.TextHeight(Name)) div 2,name);

   {Keine weitern Zeichnungen mehr ausführen}
   exit;//Verlässt die Procedure
 end;

 {Zeichung eines Rahmens}
 Canvas.Brush.Style := bsSolid;
 Canvas.Brush.Color := clblue;
 Canvas.Pen.Color := clblack;
 Canvas.Rectangle(0,0,width,height);//Rechteck zeichnen

 {Namen der Komponente in die Mitte schreiben}
 canvas.Font := FFont;
 canvas.TextOut((width - Canvas.TextWidth(Name)) div 2,(height - Canvas.TextHeight(Name)) div 2,name);

 {Keine weitern Zeichnungen mehr ausführen}
 exit;//Verlässt die Procedure
end;

{------------------------------------------------}
{                                                }
{                                                }
{                   TEColor                     }
{                                                }
{------------------------------------------------}


end.
Datei2: EButton_API.pas:

Delphi-Quellcode:
unit EButton_API;

interface

uses
   {$ifdef ver150} DesignIntf, DesignEditors,{$else} DsgnIntf,{$endif}
   EButton,SysUtils,Classes,Controls,QGraphics;

type
  TEColor = class(TColorProperty)
  public
   procedure Edit; override;
   function GetColor : TPropertyColor; override;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('RComponents', [TEButton]);
  RegisterPropertyEditor(TypeInfo(TColor), TEButton, 'Color', TRColor);
end;

{ TRColor }

procedure TColorProperty.Edit;
var
 ColorDialog: TColorDialog;
begin
  **ColorDialog := TColorDialog.Create(Application);**********{ Editor erzeugen}
  try
    ****ColorDialog.Color := GetOrdValue;*********************{ Vorhandenen Wert verwenden }
    ****if ColorDialog.Execute then************************** { Wenn der Anwender auf OK klickt ... }
      ******SetOrdValue(ColorDialog.Color);*******************{ ...das Ergebnis verwenden, um den Wert zu setzen}

  finally
    ****ColorDialog.Free;*************************************{ Editor freigeben }
  *end;
*end;

end.
Wäre echt cool wenn man da was machen könnte...

Freundliche Grüsse
und Danke zum Voraus

Cherry

uligerhardt 11. Apr 2006 15:28

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Ich hab's jetzt nicht nachgeprüft, aber hätte gedacht, dass Delphi für Eigenschaften vom Typ TColor automatisch den passenden Editor im OI anbietet. Hast du schon mal probiert, den RegisterPropertyEditor-Aufruf einfach wegzulassen?

Außerdem benutzt du einmal die Unit Graphics und einmal die QGraphics. Ich würde mich an deiner Stelle für eine Variante entscheiden. :-)

Und in der Unit EButton kannst du die Routine Register rausschmeißen - die muss nur im Designzeitpackage sein.

cherry 11. Apr 2006 15:36

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Danke für deine Antwort...

Danke für deine Tipps..
Ich habe in der Zwischenzeit noch ein bisschen herumgesurft und getestet.
Du hast vollkommen Recht was dies angeht:

Zitat:

Zitat von uligerhardt
Ich hab's jetzt nicht nachgeprüft, aber hätte gedacht, dass Delphi für Eigenschaften vom Typ TColor automatisch den passenden Editor im OI anbietet.

Ich habs jetzt ganz normal gemacht und es funktioniert bestens..
Allerdings habe ich da noch eine Frage:

Was hatt es eigentlich damit auf sich?

Ich Zitiere von MaBuSE -> Referenz
"In Delphi 5 Komponenten wird oft die Unit DsgnIntf verwendet.

Damit ist es möglich "Component-" und "Propertyeditoren" zu programmieren, die dann in der IDE ausgeführt werden. Diese Design-Editoren sind ausschließlich für die IDE lizenziert und dürfen nicht in die eigenen Programme, welche außerhalb der IDE laufen eingebunden werden. Da es einige Verstöße (meistens wohl aus Unwissenheit) gab, wurden die Units getrennt und durch "Compiler-Magic" können die Editoren jetzt nicht mehr in Programme außerhalb der IDE eingebunden werden.
"

Gruss

MaBuSE 11. Apr 2006 16:20

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von uligerhardt
Ich hab's jetzt nicht nachgeprüft, aber hätte gedacht, dass Delphi für Eigenschaften vom Typ TColor automatisch den passenden Editor im OI anbietet. Hast du schon mal probiert, den RegisterPropertyEditor-Aufruf einfach wegzulassen?

Stimmt. Ich habe mal ein Beispielprogramm geschrieben (TMyColorButton)

Zitat:

Zitat von uligerhardt
Außerdem benutzt du einmal die Unit Graphics und einmal die QGraphics. Ich würde mich an deiner Stelle für eine Variante entscheiden. :-)

Stimmt. Graphics ist die VCL Variante (meine Empfehlung) und QGraphics ist die CLX Variante (nur zu empfehlen, falls Projekte auch mit Kylix kompiliert werden sollen)

Zitat:

Zitat von uligerhardt
Und in der Unit EButton kannst du die Routine Register rausschmeißen - die muss nur im Designzeitpackage sein.

Stimmt, aber wenn er keine Designtimepackage braucht, dann kann er es drinn lassen.

@cherry: Ich habe mir Deine Komponente mal angeschaut und ein kleines Beispiel gemacht.
(Die Font und Caption Eingenschaften habe ich bewust weggelassen, damit das Beispiel kleiner bleibt.)

Delphi-Quellcode:
///////////////////////////////////////////////////////////////////////////////
// TMyColorButton
//
// Beispielprogramm zur Komponentenerstellung
//
// Folgende Dinge sind zu sehen:
//   - eine einfache Message wird behandelt ( CM_MOUSEENTER und CM_MOUSELEAVE )
//   - Propertys werden verwendet
//   - bei TColor und TBrushStyle werden automatisch
//     die Standard Property Editoren verwendet
//   - ein protected Event wird published (OnClick)
//
// Dieser Quelltext liegt auch auf [url]www.delphipraxis.net[/url]
// ( [url]http://www.delphipraxis.net/topic80394_eigene+komponente+von+tcustomcontrol+eigenschaftseditor.html[/url] )
//
///////////////////////////////////////////////////////////////////////////////
// Das Programm ist Freeware und darf beliebig benutzt und erweitert werden.
// Es wäre nett, wenn dann auch der geänderte Quelltext in obige URL-Adresse
// gesendet wird. Dann haben alle was davon.
// Es wäre auch nett wenn mein (unser) Name in den Dateien enthalten bleibt.
// Das Programm wird von Ihnen auf eigenes Risiko eingesetzt. Ich übernehme
// keine Haftung für Schäden die durch das Programm oder die Benutzung des
// Programms entstanden sind bzw. entstehen.
///////////////////////////////////////////////////////////////////////////////
// (C) 2005, MaBuSE, member of DelphiPraxis.net
///////////////////////////////////////////////////////////////////////////////
// ReleaseNotes:
// v1.0 - 11.04.2006 - MaBuSE:     Erste Version war in 10 min programmiert
///////////////////////////////////////////////////////////////////////////////

unit MyColorButton;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Graphics, Messages;

type
  TMyColorButton = class(TcustomControl)
  private
    { Private-Deklarationen }
    FmyActiveBrushColor: TColor;
    FmyBrushColor: TColor;
    FmyBrushStyle: TBrushStyle;
    FmyMouseOver: Boolean;
    FmyPenColor: TColor;
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure SetmyActiveBrushColor(const Value: TColor);
    procedure SetmyBrushColor(const Value: TColor);
    procedure SetmyBrushStyle(const Value: TBrushStyle);
    procedure SetmyPenColor(const Value: TColor);
  protected
    { Protected-Deklarationen }
    procedure Paint; override;
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
  published
    { Published-Deklarationen }
    property myActiveBrushColor: TColor read FmyActiveBrushColor write SetmyActiveBrushColor;
    property myBrushColor: TColor read FmyBrushColor write SetmyBrushColor;
    property myBrushStyle: TBrushStyle read FmyBrushStyle write SetmyBrushStyle;
    property myPenColor: TColor read FmyPenColor write SetmyPenColor;
    property OnClick;
  end;

procedure Register;

implementation

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

{ TMyColorButton }

procedure TMyColorButton.CMMouseEnter(var Message: TMessage);
begin
  // wird automatisch aufgerufen wenn der Mauszeiger über dem Control ist.
  inherited;
  FmyMouseOver := true;
  RePaint;
end;

procedure TMyColorButton.CMMouseLeave(var Message: TMessage);
begin
  // wird automatisch aufgerufen wenn der Mauszeiger nicht mehr über dem Control ist.
  inherited;
  FmyMouseOver := false;
  RePaint;
end;

constructor TMyColorButton.Create(AOwner: TComponent);
begin
  inherited;
  FmyActiveBrushColor:= clRed;
  FmyBrushColor := clGreen;
  FmyBrushStyle := bsDiagCross;
  FmyMouseOver := false;
  FmyPenColor := clBlue;
end;

procedure TMyColorButton.Paint;
begin
  inherited;

  if (csDesigning in ComponentState) or (not FmyMouseOver) then
  begin
    Canvas.Brush.Color := FmyBrushColor;
  end
  else
  begin
    Canvas.Brush.Color := FmyActiveBrushColor;
  end;

  Canvas.Brush.Style := FmyBrushStyle;
  Canvas.Pen.Color := FmyPenColor;
  Canvas.Rectangle(0,0,width,height);
end;

// Die folgenden proceduren werden beim Ändern einer Property aufgerufen
// hier steht überall ein RePaint damit die geänderten Einstellungen
// auch sichtbar werden.

procedure TMyColorButton.SetmyActiveBrushColor(const Value: TColor);
begin
  FmyActiveBrushColor := Value;
  RePaint;
end;

procedure TMyColorButton.SetmyBrushColor(const Value: TColor);
begin
  FmyBrushColor := Value;
  RePaint;
end;

procedure TMyColorButton.SetmyBrushStyle(const Value: TBrushStyle);
begin
  FmyBrushStyle := Value;
  RePaint;
end;

procedure TMyColorButton.SetmyPenColor(const Value: TColor);
begin
  FmyPenColor := Value;
  RePaint;
end;

end.
Ich hoffe das hilft Dir.
Viel Spaß

[edit] url oben in Quelltext eingefügt [/edit]

MaBuSE 11. Apr 2006 16:22

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von cherry
Was hatt es eigentlich damit auf sich?

Ich Zitiere von MaBuSE -> Referenz
"In Delphi 5 Komponenten wird oft die Unit DsgnIntf verwendet.

Damit ist es möglich "Component-" und "Propertyeditoren" zu programmieren, die dann in der IDE ausgeführt werden. Diese Design-Editoren sind ausschließlich für die IDE lizenziert und dürfen nicht in die eigenen Programme, welche außerhalb der IDE laufen eingebunden werden. Da es einige Verstöße (meistens wohl aus Unwissenheit) gab, wurden die Units getrennt und durch "Compiler-Magic" können die Editoren jetzt nicht mehr in Programme außerhalb der IDE eingebunden werden.
"

Man kann auch eigene Property- und Component Editoren schreiben.
Dazu verwendet man Objekte von Borland, die nicht zur Weitergabe freigegeben sind.
Das ist alles.

Mal schauen, vieleicht schreib ich Dir Morgen mal ein kleines Beispiel.

cherry 11. Apr 2006 16:28

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Vielen Dank MaBuSE

Ist echt net von dir!! :thumb:
Ich werde entweder noch an meiner Version versuchen weiter zu basteln,
oder vielleicht werde ich auch an deinem Beispiel weitermachen.
Auf jedenfall stelle ich den Quellcode dann wieder unter diesem Thread zur Verfügung!

Namen bleiben ;)

Nochmals recht herzlichen Dank!

Freundliche Grüsse

Cherry

MaBuSE 12. Apr 2006 06:51

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von cherry
Vielen Dank MaBuSE

Keine Ursache, gern geschehen.

Zitat:

Zitat von cherry
Namen bleiben ;)

In diesem Fall lege ich auf den Namen keinen großen Wert, da ich ja nicht viel Zeit investiert habe :-)
Das ist nur mein Standard Header für Pascal Dateien, die ich in die DP stelle.
Damit muß ich nicht jedesmal einen neuen erfinden ;-)

cherry 12. Apr 2006 10:33

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von MaBuSE
// Es wäre nett, wenn dann auch der geänderte Quelltext in obiges URL-Adresse
// gesendet wird. Dann haben alle was davon.

Also ich bin ja kein Deutscher und die Sprache liegt mir auch nicht besonders,
aber irgendwie passt hier (nach meinem Gefühl) "obiges" nicht. Oder!?

URL = Uniform Resource Locator !
obiges Uniform Resource Locator ??

Eben wie gesagt, vielleicht liege ich falsch aber ich wurde einfach schreiben " ... in die obige URL-Adresse ... "

Zitat:

Zitat von MaBuSE
Das ist nur mein Standard Header für Pascal Dateien, die ich in die DP stelle.
Damit muß ich nicht jedesmal einen neuen erfinden

Und da du diesen Header standardmässig verwendest, dachte ich, mache ich dich darauf aufmerksam. :cyclops:

MaBuSE 12. Apr 2006 13:06

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von cherry
Also ich bin ja kein Deutscher und die Sprache liegt mir auch nicht besonders, aber irgendwie passt hier (nach meinem Gefühl) "obiges" nicht. Oder!?
Zitat:

Zitat von MaBuSE
Das ist nur mein Standard Header für Pascal Dateien, die ich in die DP stelle.
Damit muß ich nicht jedesmal einen neuen erfinden

Und da du diesen Header standardmässig verwendest, dachte ich, mache ich dich darauf aufmerksam. :cyclops:

:oops: Danke.
(Ich habe den Header zum Glück erst zwei, drei mal verwendet :-)

Hier mal ein Beispiel zu einem "echtem" PropertyEditor:

Die Komponente TmyPersonComponent hat eine Eigenschaft Person die vom Typ TPerson ist.
Ich habe es mir einfasch gemacht und TPerson vom Typ TPersistent abgeleitet. Im Prinzip geht auch TObject oder ein Record. Dann muß man aber die GetProperties Methode selbst implementieren, damit sich beim Drücken auf das [+] auch weitere Untereigenschaften öffnen.


Hier ist der Objektinspektor zu sehen.


Wenn man auf den [...] Button klickt öffnet sich der PropertyEditor.


Analog dazu kann man auch die Untereigenschaften von TPerson ändern :-)


Also hier die Komponente:
Delphi-Quellcode:
///////////////////////////////////////////////////////////////////////////////
// TmyPersonComponent
//
// Beispielprogramm zur Komponentenerstellung
//
// Folgende Dinge sind zu sehen:
//   - komplexe Properties werden verwendet (Objekt TPerson)
//   - Einfacher Propertyeditor wird verwendet (s. myPersonComponent_dsgn.pas)
//
// Dieser Quelltext liegt auch auf [url]www.delphipraxis.net[/url]
// ( [url]http://www.delphipraxis.net/topic80394_eigene+komponente+von+tcustomcontrol+eigenschaftseditor.html[/url] )
// 
/////////////////////////////////////////////////////////////////////////////// 
// Das Programm ist Freeware und darf beliebig benutzt und erweitert werden.
// Es wäre nett, wenn dann auch der geänderte Quelltext in obige URL-Adresse
// gesendet wird. Dann haben alle was davon.
// Es wäre auch nett wenn mein (unser) Name in den Dateien enthalten bleibt.
// Das Programm wird von Ihnen auf eigenes Risiko eingesetzt. Ich übernehme
// keine Haftung für Schäden die durch das Programm oder die Benutzung des
// Programms entstanden sind bzw. entstehen.
/////////////////////////////////////////////////////////////////////////////// 
// (C) 2005, MaBuSE, member of DelphiPraxis.net
/////////////////////////////////////////////////////////////////////////////// 
// ReleaseNotes:
// v1.0 - 12.04.2006 - MaBuSE:     Erste Version war in 25 min programmiert
//                                  (inkl. PropertyEditor)
/////////////////////////////////////////////////////////////////////////////// 
unit myPersonComponent;

interface

uses
  SysUtils, Classes, Controls, StdCtrls;

type
  // Das ist ein Objekt, das die Daten einer Person speichert.
  // im Beispiel nur Vor- und Nachname :-)
  TPerson = class(TPersistent)
  private
    FVorname: string;
    FNachname: string;
  public
    function getDisplayValue: string;
  published
    property Nachname: string read FNachname write FNachname;
    property Vorname: string read FVorname write FVorname;
  end;

  // Das ist die Komponente die als Property eine Person beinhaltet
  // Die Person kann über die Untereigenschaften [+] oder über
  // den Propertyeditor Dialog [...] bearbeitet werden.
  TmyPersonComponent = class(TComponent)
  private
    FPerson: TPerson;
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published-Deklarationen }
    property Person : TPerson read FPerson write FPerson;
  end;

procedure Register;

implementation

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

{ TmyPersonComponent }

constructor TmyPersonComponent.Create(AOwner: TComponent);
begin
  inherited;
  FPerson := TPerson.Create;
end;

destructor TmyPersonComponent.Destroy;
begin
  FPerson.Free;
  FPerson := nil;
  inherited;
end;

{ TPerson }

// getdisplayText wird im PropertyEditor verwendet um im Objektinspektor
// Den Namen anzuzeigen. '(Nachname, Vorname)'
function TPerson.getDisplayValue: string;
var
  s: string;
begin
  if (FNachname = '') or (FVorname = '') then
  begin
    s := FNachname + FVorname;
    if s = '' then
    begin
      s := 'leer'
    end;
  end
  else
  begin
    s := FNachname + ', ' + FVorname;
  end;
  Result := '('+s+')';
end;

end.
Und hier der PropertyEditor:

Delphi-Quellcode:
///////////////////////////////////////////////////////////////////////////////
// PropertyEditor zu TmyPersonComponent
//
// Beispielprogramm zur Komponentenerstellung
//
// Folgende Dinge sind zu sehen:
//   - komplexe Properties werden verwendet (Objekt TPerson)
//   - Einfacher Propertyeditor wird verwendet (s. myPersonComponent_dsgn.pas)
//
// Dieser Quelltext liegt auch auf [url]www.delphipraxis.net[/url]
// ( [url]http://www.delphipraxis.net/topic80394_eigene+komponente+von+tcustomcontrol+eigenschaftseditor.html[/url] )
//
///////////////////////////////////////////////////////////////////////////////
// Das Programm ist Freeware und darf beliebig benutzt und erweitert werden.
// Es wäre nett, wenn dann auch der geänderte Quelltext in obige URL-Adresse
// gesendet wird. Dann haben alle was davon.
// Es wäre auch nett wenn mein (unser) Name in den Dateien enthalten bleibt.
// Das Programm wird von Ihnen auf eigenes Risiko eingesetzt. Ich übernehme
// keine Haftung für Schäden die durch das Programm oder die Benutzung des
// Programms entstanden sind bzw. entstehen.
///////////////////////////////////////////////////////////////////////////////
// (C) 2005, MaBuSE, member of DelphiPraxis.net
///////////////////////////////////////////////////////////////////////////////
// ReleaseNotes:
// v1.0 - 12.04.2006 - MaBuSE:     Erste Version war in 25 min programmiert
//                                  (inkl. PropertyEditor)
///////////////////////////////////////////////////////////////////////////////
unit myPersonComponent_dsgn;

interface

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

type
  // Formular des PropertyEditors
  TfrmPersonPropertyEditor = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

type
  // Der eigentliche PropertyEditor
  TmyPersonPropEditor = class(TClassProperty)
  protected
    // zwei Hilfsfunktionen um auf TPerson zuzugreifen
    function GetPerson: TPerson;
    procedure SetPerson(const Value: TPerson);
  public
    // hier wird das Formular aufgerufen
    procedure Edit; override;
    // hier wird bestimmt, die das Property im Objektinspektor angezeigt wird
    function GetAttributes: TPropertyAttributes; override;
    // das wird im Objektinspektor angezeigt
    function GetValue: string; override;
  end;

procedure Register;

implementation

{$R *.dfm}

procedure Register;
begin
  // Der PropertyEditor TmyPersonPropEditor (4. Parameter)
  // wird für alle Properties:
  // - vom Typ TPerson (1. Parameter)
  // - in der Komponente TmyPersonComponent inkl. Nachfahren (2. Parameter)
  // - mit dem Namen 'Person'
  // in der Delphi IDE verwendet.
  // Wenn als 2. Parameter nil übergeben wird, dann wird der PropertyEditor von
  // allen Komponenten verwendet.
  // Wenn als 3. Parameter '' übergeben wird, dann wird der PropertyEditor von
  // allen Eigenschaften des Typs TPerson verwendet.
  RegisterPropertyEditor(TypeInfo(TPerson), TmyPersonComponent, 'Person', TmyPersonPropEditor);
end;

{ TmyPersonPropEditor }

procedure TmyPersonPropEditor.Edit;
begin
  inherited;
  // Get Person sollte immer <> nil sein, da es im Constructor der Komponente
  // erzeugt wird.
  if GetPerson = nil then
  begin
    SetPerson(TPerson.Create);
  end;

  // Form erzeugen, füllen und aufrufen.
  // Wenn OK gedrückt wurde Werte übernehmen.
  // Zuletzt Form wieder aus Speicher entfernen.
  with TfrmPersonPropertyEditor.Create(nil) do
  try
    Edit1.Text := GetPerson.Nachname;
    Edit2.Text := GetPerson.Vorname;
    if ShowModal = idOk then
    begin
      getPerson.Nachname := Edit1.Text;
      getPerson.Vorname := Edit2.Text;
    end;
  finally
    Free;
  end;
end;

function TmyPersonPropEditor.GetAttributes: TPropertyAttributes;
begin
  // inherited GetAtributes liefert [paSubProperties] zurück,
  // das ist schon in TClassProperty implementiert.

  // paSubProperties:
  // Die Eigenschaft verfügt über Untereigenschaften, die unterhalb der
  // aktuellen Eigenschaft stehen und mit einer Einrückung versehen werden.
  // Wenn paSubProperties gewählt wird, muss die Eigenschaft GetProperties
  // so überschrieben werden, dass Sie Untereigenschaften übergibt.
  // In der TClassProperty ist glücklicherweise schon GetProperties
  // implementiert, so das wir uns das sparen können.

  // paDialog:
  // Die Methode Edit öffnet ein Dialogfeld. Außerdem wird im Objektinspektor
  // neben der Eigenschaft eine Ellipsen-Schaltfläche [...] platziert.

  // Es sind noch weitere Werte möglich. Einfach die Onlinehilfe zu
  // TPropertyAttributes aufrufen.

  Result := inherited GetAttributes + [paDialog];
end;

function TmyPersonPropEditor.GetPerson: TPerson;
begin
  // Das ist ein kleiner Trick. Das Objekt TPerson wird einfach mit
  // Longint(TPerson) einer Integer Variablen zugewiesen.
  // Mit TPerson(Integerwert) kann dann wieder auf das Objekt zugegriffen werden.
  // Es wird also quasi der "Pointer" auf das Objekt weitergegeben.

  // Folgende Zeile würde eigentlich reichen, da TPerson im Constuctor der
  // Komponente erzeugt wird:
  //   Result := TPerson(GetOrdValue);
  // Die Überprüfung auf nil ist nur zusätzliche Sicherheit
  if GetOrdValue <> 0 then
  begin
    Result := TPerson(GetOrdValue);
  end
  else
  begin
    Result := nil;
  end;
end;

function TmyPersonPropEditor.GetValue: string;
begin
  // Hier wird der Wert zurückgegeben, der im Objektinspektor angezeigt wird.

  // Folgende Zeile würde eigentlich reichen, da TPerson im Constuctor der
  // Komponente erzeugt wird:
  //   Result := GetPerson.getDisplayValue;
  // Die Überprüfung auf nil ist nur zusätzliche Sicherheit
  if GetPerson <> nil then
  begin
    Result := GetPerson.getDisplayValue;
  end
  else
  begin
    Result := '(nil)';
  end;
end;

procedure TmyPersonPropEditor.SetPerson(const Value: TPerson);
begin
  // Das ist ein kleiner Trick. Das Objekt TPerson wird einfach mit
  // Longint(TPerson) einer Integer Variablen zugewiesen.
  // Mit TPerson(Integerwert) kann dann wieder auf das Objekt zugegriffen werden.
  // Es wird also quasi der "Pointer" auf das Objekt weitergegeben.
  SetOrdValue(Longint(Value));
end;

end.
Die Dfm Datei des PropertyEditors sieht wie folgt aus:
Delphi-Quellcode:
object frmPersonPropertyEditor: TfrmPersonPropertyEditor
  Left = 588
  Top = 336
  Width = 354
  Height = 133
  Caption = 'Propertyeditor'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label1: TLabel
    Left = 8
    Top = 12
    Width = 31
    Height = 13
    Caption = 'Name:'
  end
  object Label2: TLabel
    Left = 8
    Top = 36
    Width = 45
    Height = 13
    Caption = 'Vorname:'
  end
  object Edit1: TEdit
    Left = 72
    Top = 8
    Width = 265
    Height = 21
    TabOrder = 0
    Text = 'Edit1'
  end
  object Edit2: TEdit
    Left = 72
    Top = 32
    Width = 265
    Height = 21
    TabOrder = 1
    Text = 'Edit2'
  end
  object BitBtn1: TBitBtn
    Left = 152
    Top = 64
    Width = 89
    Height = 25
    TabOrder = 2
    Kind = bkOK
  end
  object BitBtn2: TBitBtn
    Left = 248
    Top = 64
    Width = 89
    Height = 25
    TabOrder = 3
    Kind = bkCancel
  end
end
Ich hoffe das bringt Dich weiter.
Viel Spaß

ps: Ich werde mal bei Gelegenheit um die Beispielkomponenten ein kleines Tutorial zur Komponentenentwicklung schreiben...

MaBuSE 12. Apr 2006 13:20

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von MaBuSE
Hier mal ein Beispiel zu einem "echtem" PropertyEditor:...

Der Beitrag ist wegen des Quellcodes ziemlich lang geworden.

Da im Quelltext durch die Kommentare (die grüne Schrift :-)) meinen Beitrag sehr kurz werden lies, habe ich das in Kauf genommen.

Für alle die es nun auch zuhause ausprobieren wollen:

Hier ist der komplette Quelltext:
  • myPersonComponent.pas
  • myPersonComponent_dsgn.dfm
  • myPersonComponent_dsgn.pas
  • Package1.dpk
  • Package1.res
  • PropertyEditor1.jpg
  • PropertyEditor2.jpg
  • PropertyEditor3.jpg

cherry 13. Apr 2006 06:54

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Das ist ja einfach wiedermal genial... :drunken:

Ich werde dies bei gelegenheit ausprobieren, momentan
bin ich aber immer noch mit dem Button beschäftigt! :stupid:

Bis irgendwann..

PeteSky 13. Apr 2006 16:06

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Wirklich tolles Beispiel. :thumb:

Aber wie kann ich in meiner eigenen Komponente den StandardPropertyEditor benutzen?
So das neben meinen Strings im OI dei drei Punkte erscheinen [...] ?

cherry 15. Apr 2006 12:40

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Hey.. schon wieder habe ich ein Problem...
und zwar liegt es diesmal irgendwie an der schrift!

Ich kann den Code zwar Kompilieren, wenn ich die Komponente jedoch auf die Form
ziehe, so gibts einen Fehler. Zugriffsverletzung...

führe ich FEFont.Create; nicht aus funktionierts.

Delphi-Quellcode:
unit EButton;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Graphics, Messages, Dialogs;

type
  TEnemyleftKind = (Button, ArrowRight, ArrowLeft, Ellipse, PNG);

  TEButton = class(TCustomControl)
  private
    { Private-Deklarationen }
    { Deklarationen der Variablen für die Propertys! }
    FEFont : TFont;
    FEColor : TColor;
    FEColorOver : TColor;
    FEColorDown : TColor;
    FEBrushStyle : TBrushStyle;
    FEBrushStyleOver : TBrushStyle;
    FEBrushStyleDown : TBrushStyle;
    FEPenColor : TColor;
    FEPenColorOver : TColor;
    FEPenColorDown : TColor;
    FEnemyleftKind : TEnemyleftKind;
    FEnemyleftKindOver : TEnemyleftKind;
    FEnemyleftKindDown : TEnemyleftKind;

    EMouseOver : Boolean;

    FEOnMouseDown : TNotifyEvent;
    FEOnMouseUp : TNotifyEvent;
    EMouseDown : Boolean;

    { Deklarationen der Procedures der Propertys
      Die folgenden Procedures verarbeiten erhaltene Propertywerte }

    { Die Zwei folgenden Prozeduren }
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure SetEFont(const Value: TFont);
    procedure SetEColor(const Value: TColor);
    procedure SetEColorOver(const Value: TColor);
    procedure SetEColorDown(const Value: TColor);
    procedure SetEBrushStyle(const Value: TBrushStyle);
    procedure SetEBrushStyleOver(const Value: TBrushStyle);
    procedure SetEBrushStyleDown(const Value: TBrushStyle);
    procedure SetEPenColor(const Value: TColor);
    procedure SetEPenColorOver(const Value: TColor);
    procedure SetEPenColorDown(const Value: TColor);

    procedure SetEOnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure SetEOnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  protected
    { Protected-Deklarationen }
    procedure Paint; override;
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published-Deklarationen }

    { Propertys, Einstellungen die zur entwicklungszeit vorgenommen werden können.
      z.B. bei EFont und EColor [E für Enemyleft^^], werden standardmässige Eigenschafts-
      editoren angezeigt. Sprich Schrift / Farbeditor usw.
      write: geschrieben wird nicht einfach der "Wert" als solches, sonder über eine Prozedur.}

    property EFont: TFont read FEFont write SetEFont;
    property EColor: TColor read FEColor write SetEColor;
    property EColorOver: TColor read FEColorOver write SetEColorOver;
    property EColorDown: TColor read FEColorDown write SetEColorDown;
    property EBrushStyle : TBrushStyle read FEBrushStyle write SetEBrushStyle;
    property EBrushStyleOver : TBrushStyle read FEBrushStyleOver write SetEBrushStyleOver;
    property EBrushStyleDown : TBrushStyle read FEBrushStyleDown write SetEBrushStyleDown;
    property EPenColor : TColor read FEPenColor write SetEPenColor;
    property EPenColorOver : TColor read FEPenColorOver write SetEPenColorOver;
    property EPenColorDown : TColor read FEPenColorDown write SetEPenColorDown;
    property EnemyleftKind: TEnemyleftKind read FEnemyleftKind write FEnemyleftKind;
    property OnMouseDown: TNotifyEvent read FEOnMouseDown write FEOnMouseDown;
    property OnMouseUp: TNotifyEvent read FEOnMouseUp write FEOnMouseUp;

    { Diese Ereignisse wurden geerbt von TCustomControl und können
      deshald so simpel deklariert werden }
     
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnMouseMove;
  end;

procedure Register;

implementation

procedure Register;
begin
  { Procedure wird bei der Komponenteninstallation verwendet! }
  RegisterComponents('enemyleft', [TEButton]);
end;

constructor TEButton.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 { Hier im Konstruktor wird das OnMouseDown/Up-Ereigniss der
   "oberen Klasse (inherited)" überschrieben }
 inherited OnMouseDown := SetEOnMouseDown;
 inherited OnMouseUp := SetEOnMouseUp;
 Width:=75;
 Height:=25;
 FEFont.Create;
 FEColor:=clWhite;
 FEColorOver:=clAqua;
 FEColorDown:=clBlack;
 FEBrushStyle:=bsSolid;
 FEBrushStyleOver:=bsSolid;
 FEBrushStyleDown:=bsSolid;
 FEPenColor:=clRed;
 FEPenColorOver:=clBlue;
 FEPenColorDown:=clYellow;
 EMouseOver:=false;
 EMouseDown:=false;
end;

destructor TEButton.Destroy;
begin
 FEFont.Free;
 inherited Destroy;
end;

procedure TEButton.Paint;

 { Methode Paint wird überschrieben, die diversen if abfragen sind nötig um
   Den Button korrekt zu Zeichen, trifft das Ereignis MouseDown, oder RollOver
   zu, wird der Button anders gezeichnet als in ComponentState(Entwicklungsumgebung)
   oder wenn kein Ereignis zutrifft. }

begin
 inherited;//Zeichen Procedure des Vorfahren aufrufen.
 if (csDesigning in ComponentState) or (not EMouseOver) then
 begin
  {Zeichung eines Rahmens}
  Canvas.Brush.Color := FEColor;
  Canvas.Brush.Style := FEBrushStyle;
  Canvas.Pen.Color := FEPenColor;
  Canvas.Rectangle(0,0,width,height);//Rechteck zeichnen

  {Namen der Komponente in die Mitte schreiben}
  canvas.Font := FEFont;
  canvas.TextOut((width - Canvas.TextWidth(Name)) div 2,(height - Canvas.TextHeight(Name)) div 2,name);

  {Keine weitern Zeichnungen mehr ausführen}
  exit;//Verlässt die Procedure
 end
 else if (EMouseOver) then
 begin
  if (EMouseDown) then
  begin
   Canvas.Brush.Color := FEColorDown;
   Canvas.Brush.Style := FEBrushStyleDown;
   Canvas.Pen.Color := FEPenColorDown;
   Canvas.Rectangle(0,0,width,height);

   canvas.Font := FEFont;
   canvas.TextOut((width - Canvas.TextWidth(Name)) div 2,(height - Canvas.TextHeight(Name)) div 2,name);

   exit;
  end
  else
  begin
   Canvas.Brush.Color := FEColorOver;
   Canvas.Brush.Style := FEBrushStyleOver;
   Canvas.Pen.Color := FEPenColorOver;
   Canvas.Rectangle(0,0,width,height);

   canvas.Font := FEFont;
   canvas.TextOut((width - Canvas.TextWidth(Name)) div 2,(height - Canvas.TextHeight(Name)) div 2,name);

   exit;
  end;
 end;
end;

{ Proceduren (Selbsterklärens) }

procedure TEButton.CMMouseEnter(var Message: TMessage);
begin
 inherited;
 EMouseOver := true;
 RePaint;
end;

procedure TEButton.CMMouseLeave(var Message: TMessage);
begin
 inherited;
 EMouseOver := false;
 RePaint;
end;

procedure TEButton.SetEFont(const Value: TFont);
begin
 FEFont := Value;
 RePaint;
end;

procedure TEButton.SetEColor(const Value: TColor);
begin
 FEColor := Value;
 RePaint;
end;

procedure TEButton.SetEColorOver(const Value: TColor);
begin
 FEColorOver := Value;
 RePaint;
end;

procedure TEButton.SetEColorDown(const Value: TColor);
begin
 FEColorDown := Value;
 RePaint;
end;

procedure TEButton.SetEBrushStyle(const Value: TBrushStyle);
begin
 FEBrushStyle := Value;
 RePaint;
end;

procedure TEButton.SetEBrushStyleOver(const Value: TBrushStyle);
begin
 FEBrushStyleOver := Value;
 RePaint;
end;

procedure TEButton.SetEBrushStyleDown(const Value: TBrushStyle);
begin
 FEBrushStyleDown := Value;
 RePaint;
end;

procedure TEButton.SetEPenColor(const Value: TColor);
begin
 FEPenColor := Value;
 RePaint;
end;

procedure TEButton.SetEPenColorOver(const Value: TColor);
begin
 FEPenColorOver := Value;
 RePaint;
end;

procedure TEButton.SetEPenColorDown(const Value: TColor);
begin
 FEPenColorDown := Value;
 RePaint;
end;

{ Vor das Ereignis wird die Variable MouseDown, weleche einfluss auf
  auf die Procedure Paint hat auf true gesetzt. /
  Im Konstruktor wird mit "inherited OnMouseDown / UP := Proc" auf die jeweilige
  Procedure hingewiesen, die das Ereignis "steuert" }

procedure TEButton.SetEOnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 EMouseDown := true;
 RePaint;
 if Assigned(FEOnMouseDown) then FEOnMouseDown(Sender);
end;

procedure TEButton.SetEOnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 EMouseDown := false;
 RePaint;
 if Assigned(FEOnMouseUp) then FEOnMouseUp(Sender);
end;

end.

Hawkeye219 15. Apr 2006 12:50

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Du mußt dem Feld EFont das Ergebnis des Konstruktor-Aufrufs zuweisen:

Delphi-Quellcode:
FEFont := TFont.Create;
Gruß Hawkeye

cherry 15. Apr 2006 14:54

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zu Peinlich man... Vielen Dank.. :oops:

MaBuSE 18. Apr 2006 09:05

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von cherry
Das ist ja einfach wiedermal genial...

Danke
Zitat:

Zitat von PeteSky
Wirklich tolles Beispiel. :thumb:

Danke

Zitat:

Zitat von PeteSky
Aber wie kann ich in meiner eigenen Komponente den StandardPropertyEditor benutzen?
So das neben meinen Strings im OI dei drei Punkte erscheinen [...] ?

Ich verstehe diese Frage nicht ganz.

Die StandardPropertyEditoren werden automatisch verwendet.
Ein Eigenschaft vom Typ TColor bekommt automatisch die [...] um den Farbdialog aufzurufen.
Es gibt auch PropertyEditoren die z.B. an allen eigenschaften vom Typ string hängen und den Namen Caption tragen. Diese sind aber keine StandardPropertyEditoren, sondern einzeln installiert (und vorher programmiert .-)) werden.

Die Drei Punkte bekommt man wenn man in dem Property Editor die GetAttributes Methode implementiert und im ResultSet paDialog zurückgibt. (siehe obiges Beispiel von mir)

Wird der [...] Button gedrückt, so wird die (hoffentlich implementierte) Edit Methode aufgerufen.

Das wars eigentlich.

Hier ein kleines Beispiel, das der Tag Eigenschaft aller Komponenten einen PropertyEditor zuweist. Zusätzlich habe ich noch gezeigt, wie einfach man auch auf mehrere markierte Komponenten reagieren kann.
Also einfach mal instrallieren und ein TLabel, TEdit und TButton aufs Form alle 3 Markieren und dann in der Tag Eigenschaft auf den [...] Button klicken.
In der EditBox erscheint dann der Text:
Zitat:

Folgende Eigenschaften setzen:
Label1.Tag
Edit1.Tag
Button1.Tag
Da auch die Anzeige des Eigenschaftsnamens zur Laufzeit ermittelt wird, kann der PropertyEditor auch anderen Integer Eigenschaften zugewiesen werden.
Delphi-Quellcode:
procedure Register;
begin
  // damit ist der PropertyEditor allen Eingenschaften vom Typ Integer zugewiesen
  RegisterPropertyEditor(TypeInfo(Integer), nil, '', TmyIntegerPropEditor);
end;
Delphi-Quellcode:
///////////////////////////////////////////////////////////////////////////////
// PropertyEditor für Integer
//
// Beispielprogramm zur Komponentenerstellung
//
// Folgende Dinge sind zu sehen:
//   - PropertyEditor für Tag Eigenschaft aller Komponenten
//   - auf mehrere gleichzeitig markierte Komponenten reagieren :-)
//
// Dieser Quelltext liegt auch auf [url]www.delphipraxis.net[/url]
// ( [url]http://www.delphipraxis.net/topic80394_eigene+komponente+von+tcustomcontrol+eigenschaftseditor.html[/url] )
//
///////////////////////////////////////////////////////////////////////////////
// Das Programm ist Freeware und darf beliebig benutzt und erweitert werden.
// Es wäre nett, wenn dann auch der geänderte Quelltext in obige URL-Adresse
// gesendet wird. Dann haben alle was davon.
// Es wäre auch nett wenn mein (unser) Name in den Dateien enthalten bleibt.
// Das Programm wird von Ihnen auf eigenes Risiko eingesetzt. Ich übernehme
// keine Haftung für Schäden die durch das Programm oder die Benutzung des
// Programms entstanden sind bzw. entstehen.
///////////////////////////////////////////////////////////////////////////////
// (C) 2005, MaBuSE, member of DelphiPraxis.net
///////////////////////////////////////////////////////////////////////////////
// ReleaseNotes:
// v1.0 - 18.04.2006 - MaBuSE:     Erste Version war in 5 min programmiert
///////////////////////////////////////////////////////////////////////////////
unit integer_dsgn;

interface

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

type
  TmyIntegerPropEditor = class(TIntegerProperty)
  public
    // hier wird das Formular aufgerufen
    procedure Edit; override;
    // hier wird bestimmt, die das Property im Objektinspektor angezeigt wird
    function GetAttributes: TPropertyAttributes; override;
  end;

procedure Register;

implementation

procedure Register;
begin
  // Der PropertyEditor TmyIntegerPropEditor (4. Parameter)
  // wird für alle Properties:
  // - vom Typ Integer (1. Parameter)
  // - für alle Komponenten (2. Parameter)
  // - mit dem Namen 'Tag'
  // in der Delphi IDE verwendet.
  // Wenn als 2. Parameter nil übergeben wird, dann wird der PropertyEditor von
  // allen Komponenten verwendet.
  // Wenn als 3. Parameter '' übergeben wird, dann wird der PropertyEditor von
  // allen Eigenschaften des Typs Integer verwendet.
  RegisterPropertyEditor(TypeInfo(Integer), nil, 'Tag', TmyIntegerPropEditor);
end;

{ TmyIntegerPropEditor }

procedure TmyIntegerPropEditor.Edit;
var
  i: Integer;
  s: string;
  cc: string;
begin
  inherited;
  // Wenn gleichzeitig mehrere Komponenten markiert sind,
  // alle Komponenten im Prompt Text des Eingabedialogs anzeigen
  if PropCount > 1 then
  begin
    cc := 'Folgende Eigenschaften setzen:'+#13;
  end
  else
  begin
    cc := 'Folgende Eigenschaft setzen: ';
  end;
 
  for i := 0 to PropCount - 1 do
  begin
    // Für jede markierte Komponente
    cc := cc + GetComponent(i).GetNamePath + '.' + GetName + #13;
  end;

  // aktuellen Wert in String s übernehmen
  s := IntToStr(GetOrdValue);

  // den EingabeDialog mit s aufrufen
  if InputQuery('myIntegerPropertyEditor', cc, s) then
  begin
    // s in Integer umwandeln und Eigenschaft setzen
    SetOrdValue(StrToInt(s));
  end;
end;

function TmyIntegerPropEditor.GetAttributes: TPropertyAttributes;
begin
  // [...] Button anzeigen
  Result := inherited GetAttributes + [paDialog];
end;

end.

cherry 18. Apr 2006 10:58

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
So, ich gebs auf.. Kann mir jmd helfen?
Das mit Font funzt immer noch nicht und ich werd nicht Schlau dabei... ich habs sicher schon auf 100 verschiedene
arten versucht..
Wenn mann diese Version so wie sie her Steht Compiliert kann man, wenn man den Eigenschaftseditor nicht aufruft
die Schrift teils verändern, eg. Style usw.
Ändert man sie jedoch durch den EigenschaftsEditor wird die Font zwär geändert, gibt aber trotzdem eine Zugriffsverletzung aus!
Ich kriegs nicht hingebogen..
Bitte um hilfe...

Delphi-Quellcode:
unit EButton;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Graphics, Messages, Dialogs;

type
  TEnemyleftKind = (Button, ArrowRight, ArrowLeft, Ellipse, PNG);

  TEButton = class(TCustomControl)
  private
    { Private-Deklarationen }
    { Deklarationen der Variablen für die Propertys! }
    FEFont : TFont;
   // FEFontOver : TFont;
   // FEFontDown : TFont;
    FEColor : TColor;
    FEColorOver : TColor;
    FEColorDown : TColor;
    FEBrushStyle : TBrushStyle;
    FEBrushStyleOver : TBrushStyle;
    FEBrushStyleDown : TBrushStyle;
    FEPenColor : TColor;
    FEPenColorOver : TColor;
    FEPenColorDown : TColor;
    FEnemyleftKind : TEnemyleftKind;
    FEnemyleftKindOver : TEnemyleftKind;
    FEnemyleftKindDown : TEnemyleftKind;

    EMouseOver : Boolean;

    FEOnMouseDown : TNotifyEvent;
    FEOnMouseUp : TNotifyEvent;
    EMouseDown : Boolean;

    { Deklarationen der Procedures der Propertys
      Die folgenden Procedures verarbeiten erhaltene Propertywerte }

    { Die Zwei folgenden Prozeduren }
    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    //procedure SetEFont(const Value: TFont);
    //procedure SetEFontOver(const Value: TFont);
    //procedure SetEFontDown(const Value: TFont);
    procedure SetEColor(const Value: TColor);
    procedure SetEColorOver(const Value: TColor);
    procedure SetEColorDown(const Value: TColor);
    procedure SetEBrushStyle(const Value: TBrushStyle);
    procedure SetEBrushStyleOver(const Value: TBrushStyle);
    procedure SetEBrushStyleDown(const Value: TBrushStyle);
    procedure SetEPenColor(const Value: TColor);
    procedure SetEPenColorOver(const Value: TColor);
    procedure SetEPenColorDown(const Value: TColor);

    procedure SetEOnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure SetEOnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  protected
    { Protected-Deklarationen }
    procedure Paint; override;
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published-Deklarationen }

    { Propertys, Einstellungen die zur entwicklungszeit vorgenommen werden können.
      z.B. bei EFont und EColor [E für Enemyleft^^], werden standardmässige Eigenschafts-
      editoren angezeigt. Sprich Schrift / Farbeditor usw.
      write: geschrieben wird nicht einfach der "Wert" als solches, sonder über eine Prozedur.}

    property EFont: TFont read FEFont write FEFont;
    //property EFontOver: TFont read FEFontOver write SetEFontOver;
    //property EFontDown: TFont read FEFontDown write SetEFontDown;
    property EColor: TColor read FEColor write SetEColor;
    property EColorOver: TColor read FEColorOver write SetEColorOver;
    property EColorDown: TColor read FEColorDown write SetEColorDown;
    property EBrushStyle : TBrushStyle read FEBrushStyle write SetEBrushStyle;
    property EBrushStyleOver : TBrushStyle read FEBrushStyleOver write SetEBrushStyleOver;
    property EBrushStyleDown : TBrushStyle read FEBrushStyleDown write SetEBrushStyleDown;
    property EPenColor : TColor read FEPenColor write SetEPenColor;
    property EPenColorOver : TColor read FEPenColorOver write SetEPenColorOver;
    property EPenColorDown : TColor read FEPenColorDown write SetEPenColorDown;
    property EnemyleftKind: TEnemyleftKind read FEnemyleftKind write FEnemyleftKind;
    property OnMouseDown: TNotifyEvent read FEOnMouseDown write FEOnMouseDown;
    property OnMouseUp: TNotifyEvent read FEOnMouseUp write FEOnMouseUp;

    { Diese Ereignisse wurden geerbt von TCustomControl und können
      deshald so simpel deklariert werden }
     
    property OnClick;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnMouseMove;
  end;

procedure Register;

implementation

procedure Register;
begin
  { Procedure wird bei der Komponenteninstallation verwendet! }
  RegisterComponents('enemyleft', [TEButton]);
end;

constructor TEButton.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 { Hier im Konstruktor wird das OnMouseDown/Up-Ereigniss der
   "oberen Klasse (inherited)" überschrieben }
 //DoubleBuffered := True; {Zeichen Prozesse werden sonst vielleicht in Zwischenstufen angezeigt - Flackern}
 FEFont := TFont.Create;
 inherited OnMouseDown := SetEOnMouseDown;
 inherited OnMouseUp := SetEOnMouseUp;
 //FEFont.Create;
 //FEFontOver := TFont.Create;
 //FEFontDown := TFont.Create;
 FEColor:=clWhite;
 FEColorOver:=clAqua;
 FEColorDown:=clBlack;
 FEBrushStyle:=bsSolid;
 FEBrushStyleOver:=bsDiagCross;
 FEBrushStyleDown:=bsDiagCross;
 FEPenColor:=clRed;
 FEPenColorOver:=clBlue;
 FEPenColorDown:=clYellow;
 EMouseOver:=false;
 EMouseDown:=false;
 Width:=75;
 Height:=25;
end;

destructor TEButton.Destroy;
begin
 FEFont.Free;
 inherited Destroy;
end;

procedure TEButton.Paint;

 { Methode Paint wird überschrieben, die diversen if abfragen sind nötig um
   Den Button korrekt zu Zeichen, trifft das Ereignis MouseDown, oder RollOver
   zu, wird der Button anders gezeichnet als in ComponentState(Entwicklungsumgebung)
   oder wenn kein Ereignis zutrifft. }

begin
 inherited;//Zeichen Procedure des Vorfahren aufrufen.
 if (csDesigning in ComponentState) or (not EMouseOver) then
 begin
  {Zeichung eines Rahmens}
  Canvas.Brush.Color := FEColor;
  Canvas.Brush.Style := FEBrushStyle;
  Canvas.Pen.Color := FEPenColor;
  Canvas.Rectangle(0,0,width,height);//Rechteck zeichnen

  {Namen der Komponente in die Mitte schreiben}
  canvas.Font := FEFont;
  canvas.TextOut((width - Canvas.TextWidth(Name)) div 2,(height - Canvas.TextHeight(Name)) div 2,name);

  {Keine weitern Zeichnungen mehr ausführen}
  //exit;//Verlässt die Procedure
 end
 else if (EMouseOver) then
 begin
  if (EMouseDown) then
  begin
   Canvas.Brush.Color := FEColorDown;
   Canvas.Brush.Style := FEBrushStyleDown;
   Canvas.Pen.Color := FEPenColorDown;
   Canvas.Rectangle(0,0,width,height);

   canvas.Font := FEFont;
   canvas.TextOut((width - Canvas.TextWidth(Name)) div 2,(height - Canvas.TextHeight(Name)) div 2,name);

   exit;
  end
  else
  begin
   Canvas.Brush.Color := FEColorOver;
   Canvas.Brush.Style := FEBrushStyleOver;
   Canvas.Pen.Color := FEPenColorOver;
   Canvas.Rectangle(0,0,width,height);

   canvas.Font := FEFont;
   canvas.TextOut((width - Canvas.TextWidth(Name)) div 2,(height - Canvas.TextHeight(Name)) div 2,name);

   exit;
  end;
 end;
end;

{ Proceduren (Selbsterklärens) }

procedure TEButton.CMMouseEnter(var Message: TMessage);
begin
 inherited;
 EMouseOver := true;
 RePaint;
end;

procedure TEButton.CMMouseLeave(var Message: TMessage);
begin
 inherited;
 EMouseOver := false;
 RePaint;
end;

{procedure TEButton.SetEFont(const Value: TFont);
begin
 FEFont := Value;
 RePaint;
end;  }

{procedure TEButton.SetEFontOver(const Value: TFont);
begin
 FEFontOver := Value;
 RePaint;
end;

procedure TEButton.SetEFontDown(const Value: TFont);
begin
 FEFontDown := Value;
 RePaint;
end;      }

procedure TEButton.SetEColor(const Value: TColor);
begin
 FEColor := Value;
 RePaint;
end;

procedure TEButton.SetEColorOver(const Value: TColor);
begin
 FEColorOver := Value;
 RePaint;
end;

procedure TEButton.SetEColorDown(const Value: TColor);
begin
 FEColorDown := Value;
 RePaint;
end;

procedure TEButton.SetEBrushStyle(const Value: TBrushStyle);
begin
 FEBrushStyle := Value;
 RePaint;
end;

procedure TEButton.SetEBrushStyleOver(const Value: TBrushStyle);
begin
 FEBrushStyleOver := Value;
 RePaint;
end;

procedure TEButton.SetEBrushStyleDown(const Value: TBrushStyle);
begin
 FEBrushStyleDown := Value;
 RePaint;
end;

procedure TEButton.SetEPenColor(const Value: TColor);
begin
 FEPenColor := Value;
 RePaint;
end;

procedure TEButton.SetEPenColorOver(const Value: TColor);
begin
 FEPenColorOver := Value;
 RePaint;
end;

procedure TEButton.SetEPenColorDown(const Value: TColor);
begin
 FEPenColorDown := Value;
 RePaint;
end;

{ Vor das Ereignis wird die Variable MouseDown, weleche einfluss auf
  auf die Procedure Paint hat auf true gesetzt. /
  Im Konstruktor wird mit "inherited OnMouseDown / UP := Proc" auf die jeweilige
  Procedure hingewiesen, die das Ereignis "steuert" }

procedure TEButton.SetEOnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 EMouseDown := true;
 RePaint;
 if Assigned(FEOnMouseDown) then FEOnMouseDown(Sender);
end;

procedure TEButton.SetEOnMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 EMouseDown := false;
 RePaint;
 if Assigned(FEOnMouseUp) then FEOnMouseUp(Sender);
end;

end.

Sidorion 18. Apr 2006 12:14

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zu den Zugriffsverletzungen hab ich erstmal keine Idee, aber Du solltest nicht den Event des Vorgängers überschreiben(OnMouseDown usw.), sondern die Methode MouseDown. Wenn nämlich jemand einen Zeiger auf den Vorgänger hat, dann killt er damir Deine ganze Behandlung mit dem EMouseDown. MouseDown und MouseUp sind Methoden von TControl und rufen dort nur FOnMouse... Wenn Du diese Methoden überschreibst, dann kannst Du Deinen Merker Setzten, Inherited rufen und dann den Repaint ausführen.

MaBuSE 18. Apr 2006 16:08

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von Sidorion
...aber Du solltest nicht den Event des Vorgängers überschreiben(OnMouseDown usw.), sondern die Methode MouseDown.

Stimmt.

Zu den Schutzverletzungen:

Das scheint ein Bug im Delphi zu sein oder wir machen was grundlegend falsch.
Bei einer einfachen Komponente (siehe Quelltext) tritt das Problem bei mir auch auf, wenn ich z.B. Arial auswähle.
Ich werde morgen mal schauen woran das liegt. Ach ja ich verwende im Moment Delphi 7. (Ich schau mal was D2006 dazu sagt.)

Delphi-Quellcode:
unit myFontDemoComponent;

interface

uses
  SysUtils, Classes, Graphics;

type
  TmyFontDemoComponent = class(TComponent)
  private
    FFont: TFont;
    procedure SetFont(const Value: TFont);
    { Private-Deklarationen }
  protected
    { Protected-Deklarationen }
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published-Deklarationen }
    property Font: TFont read FFont write SetFont;
  end;

procedure Register;

implementation

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

{ TmyFontDemoComponent }

constructor TmyFontDemoComponent.Create(AOwner: TComponent);
begin
  inherited;
  FFont := TFont.Create;
end;

destructor TmyFontDemoComponent.Destroy;
begin
  FFont.Free;
  FFont := nil;
  inherited;
end;

procedure TmyFontDemoComponent.SetFont(const Value: TFont);
begin
  FFont := Value;
end;

end.

Sidorion 18. Apr 2006 16:16

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Ich nehm mal schwer an, das liegt an der Zuweisung:
Delphi-Quellcode:
FFont:=Value
Ich geh mal davon aus, dass Value das Fontobjekt des Eigenschafteditors ist. Wenn ja, dann wirds nach dem Aufruf der Property plattgeschlafen und in FFont stehr ien Zeiger in die Pampa.
Besser ist wohl:
Delphi-Quellcode:
FFont.Assign(Value)

cherry 18. Apr 2006 17:07

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von Sidorion
Ich nehm mal schwer an, das liegt an der Zuweisung:
Besser ist wohl:
Delphi-Quellcode:
FFont.Assign(Value)

Cool. Das Problem wäre nun geklärt, nur tritt jetzt ein neues auf!!!
Jetzt gibts keine Fehlermeldung mehr, alles funktioniert so weit.

Führt man das Programm aber nun aus, Wird einfach die standardschrift übernommen,..
:freak: :gruebel: :lol: ??? halloo...

Hast du da auch gleich so n prima Vorschlag parat? Wäre toll...

Gruss

MeineFastFunktionierendeTestKomponente:

Delphi-Quellcode:
unit EChecker;

interface

uses
  SysUtils, Classes, Controls, Graphics;

type
  TEChecker = class(TCustomControl)
  private
    { Private-Deklarationen }
    FFont: TFont;
  protected
    { Protected-Deklarationen }
    procedure Paint; override;
    procedure SetFFont(const Value: TFont);
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published-Deklarationen }
    property Font read FFont write SetFFont;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('enemyleft', [TEChecker]);
end;

constructor TEChecker.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 FFont:=TFont.Create;
end;

destructor TEChecker.Destroy;
begin
 FFont.Free;
 inherited Destroy;
end;

procedure TEChecker.Paint;
begin
 Canvas.Rectangle(0,0,width,height);
 Canvas.Font := FFont;
 Canvas.TextOut((width - Canvas.TextWidth(Name)) div 2,(height - Canvas.TextHeight(Name)) div 2,name);
 exit;
end;

procedure TEChecker.SetFFont(const Value: TFont);
begin
  FFont.Assign(Value);
  RePaint;
end;

end.
// Auch Canvas.Font.Assign(Self.FFont); oder solche sachen gehen net. Hab ich schon ausprobiert.

Hawkeye219 18. Apr 2006 17:54

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Hallo cherry,

die Komponente TCustomControl, von der Du Deine eigene Komponente ableitest, verfügt bereits über eine Font-Eigenschaft. Es ist also gar nicht sinnvoll, eine weitere zu definieren. Du mußt lediglich die vorhandene veröffentlichen.

Versuche es einmal mit dem folgenden Quelltext:

Delphi-Quellcode:
unit EChecker;

interface

uses
  SysUtils, Classes, Controls, Graphics;

type
  TEChecker = class(TCustomControl)
  protected
    procedure Paint; override;
  published
    property Font;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('enemyleft', [TEChecker]);
end;

procedure TEChecker.Paint;
begin
  Canvas.Rectangle(0,0,width,height);
  Canvas.Font.Assign(Font);
  Canvas.TextOut((width - Canvas.TextWidth(Name)) div 2, (height - Canvas.TextHeight(Name)) div 2,name);
end;

end.
Gruß Hawkeye

cherry 19. Apr 2006 06:22

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von Hawkeye219
Hallo cherry,

die Komponente TCustomControl, von der Du Deine eigene Komponente ableitest, verfügt bereits über eine Font-Eigenschaft. Es ist also gar nicht sinnvoll, eine weitere zu definieren. Du mußt lediglich die vorhandene veröffentlichen.

Ich weiss, nur bin ich dran einen Button zu kreieren. In seinen 3 verschiedenen Zuständen soll es auch möglich sein
die Schrift anzupassen. Also benötige ich zwei weitere Font eigenschaften! :cat:

Tja, also immer noch daselbe Problem...

Danke trotzdem

cherry 19. Apr 2006 06:35

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Ok, ich habs raus... :dancer:

Ich schrieb:

Delphi-Quellcode:
property Font read FFont write SetFFont;
statt:

Delphi-Quellcode:
property Font: TFont read FFont write SetFFont;
So, jetzt kann ich so viele Font Eigenschaften ersellen wie ich möchte
und das beste, es funktioniert einwandfrei!

MaBuSE 19. Apr 2006 06:57

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von MaBuSE
Zu den Schutzverletzungen:
Das scheint ein Bug im Delphi zu sein oder wir machen was grundlegend falsch.

Ich ahnte schon, das wir etwas falsch machen, deshalb habe ich es fett gemacht :mrgreen:

Zitat:

Zitat von Sidorion
Ich nehm mal schwer an, das liegt an der Zuweisung:
Delphi-Quellcode:
FFont:=Value
Ich geh mal davon aus, dass Value das Fontobjekt des Eigenschafteditors ist. Wenn ja, dann wirds nach dem Aufruf der Property plattgeschlafen und in FFont stehr ien Zeiger in die Pampa.
Besser ist wohl:
Delphi-Quellcode:
FFont.Assign(Value)

Sidorion, Du hast Recht. Borland macht es ja genau so.
Delphi-Quellcode:
{*******************************************************}
{       Borland Delphi Visual Component Library        }
{  Copyright (c) 1995-2002 Borland Software Corporation }
{*******************************************************}
unit Controls;
...
procedure TControl.SetFont(Value: TFont);
begin
  FFont.Assign(Value);
end;
...
Das heißt bei Objekten sollte nie folgendes verwenden:
Delphi-Quellcode:
...
property Eigenschaft: TEigenschaft read FEigenschaft write FEigenschaft;
...
Da dort ja das selbe gemacht wird.
Besser ist dann
Delphi-Quellcode:
...
private
  FEigenschaft: TEigenschaft;
  procedure SetEigenschaft(Value: TEigenschaft);
published
  property Eigenschaft: TEigenschaft read Feigenschaft write SetEigenschaft;
...
In SetEigenschaft muß dann das Objekt "richtig" übergeben werden.

Sidorion 19. Apr 2006 08:57

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Bei Objektmember kann man auch eine nur Lesen Property machen, dann kann man allerdings immernoch schreibend auf die Member der Instanz zugreifen und man keine neue Instanz mehr zuweisen.
z.B.:
Delphi-Quellcode:
Property MyFont: TFont Read FMyFont;
dann geht das nichtmehr:
Delphi-Quellcode:
MyObject.MyFont:=oNewFont
aber das geht immer
Delphi-Quellcode:
MyObject.MyFont.Color:=clMaroon
und kann auch nicht verhindert werden, es sei denn man gibt nicht MyFont, sondern die änderbaren Eigenschaften des MyFont als eigene Propertys aus. Dafür braucht man dann allerdings grundsätzlich Methoden zum Lesen und Schreiben.

Zu dem
Delphi-Quellcode:
FFOnt:=Value;
noch folgendes: Bei Objektvariablen weist der := Operator grundsätzlich nur den Zeiger zu (Wir erinnern uns: Objektvariablen sind in Delphi gleichzeitig immer Pointer). Um die Eigenschaften zuzuweisen ist grundsätzlich die Assign-Methode oder ein Copy Constructor(Falls vorhanden) zu nehmen.
Man sollte diese zwei Methoden auch bei eigenen Objekttypen implementieren, falls auch nur die geringste Wahrscheinlichkeit besteht, dass so eine Instanz irgendwann einmal kopiert werden muss.

cherry 19. Apr 2006 13:06

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Ich will, das man sieht ob der Button Fokusiert ist oder nicht.

Wie mach ich das am besten?

mit:

SetFocus (Komponente wird Fokusiert, entsprechendes Repaint..)
OnExit

oder mit

OnEnter
OnExit

Sidorion 19. Apr 2006 14:22

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Am besten durch Überschreiben von
Delphi-Quellcode:
    procedure DoEnter; dynamic;
    procedure DoExit; dynamic;
Da kannst Du dann erst Inherited rufen und danach deinen Focusmerker setzten und Repaint/Invalidate rufen.
NIE die Events selber verwursten, sondern immer die Prozeduren, die diese Events aufrufen überschreiben, dann kann man nämlich die Events immernoch für anderes Zeug von aussen setzen.

cherry 21. Apr 2006 08:58

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Hello..
Dem Wochenend näher kommend, poste ich hier mal mein aktueller Code:

Delphi-Quellcode:
///////////////////////////////////////////////////////////////////////////////
// TEButton.pas - EnemyleftButton
//
// Ein Button abgeleitet von TCustomControl.
// TEButton bietet alle Eigenschaften und Ereignisse die
// wir bereits vom herkömmlichen TButton kennen. Darüber hinaus
// hat man grafisch mehr Mäglichkeiten. Farbe, Form...
//
// Diese OpenSource Komponente ist noch nicht fertig entwickelt!
//
///////////////////////////////////////////////////////////////////////////////
// (C) 2006, Enemyleft
/////////////////////////////////////////////////////////////////////////////// 
// ReleaseNotes:
// v1.0 beta - 21.04.06 - Enemyleft
/////////////////////////////////////////////////////////////////////////////// 

unit EButton;

interface

uses
  SysUtils, Classes, Controls, StdCtrls, Graphics, Messages, Dialogs, Types;

type
  TEnemyleftKind = (Button, Rounded, ArrowRight, ArrowLeft, Ellipse, PNG);

  TEButton = class(TCustomControl)
  private
    { Private-Deklarationen }
    FEFont : TFont;
    FEFontOver : TFont;
    FEFontDown : TFont;
    FEColor : TColor;
    FEColorOver : TColor;
    FEColorDown : TColor;
    FEBrushStyle : TBrushStyle;
    FEBrushStyleOver : TBrushStyle;
    FEBrushStyleDown : TBrushStyle;
    FEPenColor : TColor;
    FEPenColorOver : TColor;
    FEPenColorDown : TColor;
    FEOnFocusedShow : Boolean;
    FEOnFocusedColor : TColor;
    FEnemyleftKind : TEnemyleftKind;
    FEnemyRoundedW : Integer;
    FEnemyRoundedH : Integer;

    FCaption: String;

    FOnMouseDown : TNotifyEvent;
    FOnMouseUp : TNotifyEvent;

    EMouseOver : Boolean;
    EMouseDown : Boolean;

    isCaption : Boolean;

    procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
    procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
    procedure SetEFont(const Value: TFont);
    procedure SetEFontOver(const Value: TFont);
    procedure SetEFontDown(const Value: TFont);
    procedure SetEColor(const Value: TColor);
    procedure SetEColorOver(const Value: TColor);
    procedure SetEColorDown(const Value: TColor);
    procedure SetEBrushStyle(const Value: TBrushStyle);
    procedure SetEBrushStyleOver(const Value: TBrushStyle);
    procedure SetEBrushStyleDown(const Value: TBrushStyle);
    procedure SetEPenColor(const Value: TColor);
    procedure SetEPenColorOver(const Value: TColor);
    procedure SetEPenColorDown(const Value: TColor);
    procedure SetEOnFocusedShow(const Value: Boolean);
    procedure SetEOnFocusedColor(const Value: TColor);
    procedure SetEnemyRoundedW(const Value: Integer);
    procedure SetEnemyRoundedH(const Value: Integer);
    procedure SetCaption(const Value: String);
  protected
    { Protected-Deklarationen }
    procedure Paint; override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
    procedure DoEnter; override;
    procedure DoExit; override;
    procedure KeyPress(var Key: Char); override;

    procedure PaintButton;
    procedure PaintRounded;
    procedure PaintArrowRight;
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

  published
    { Published-Deklarationen }
    property EFont: TFont read FEFont write SetEFont;
    property EFontOver: TFont read FEFontOver write SetEFontOver;
    property EFontDown: TFont read FEFontDown write SetEFontDown;
    property EColor: TColor read FEColor write SetEColor;
    property EColorOver: TColor read FEColorOver write SetEColorOver;
    property EColorDown: TColor read FEColorDown write SetEColorDown;
    property EBrushStyle: TBrushStyle read FEBrushStyle write SetEBrushStyle;
    property EBrushStyleOver: TBrushStyle read FEBrushStyleOver write SetEBrushStyleOver;
    property EBrushStyleDown: TBrushStyle read FEBrushStyleDown write SetEBrushStyleDown;
    property EPenColor: TColor read FEPenColor write SetEPenColor;
    property EPenColorOver: TColor read FEPenColorOver write SetEPenColorOver;
    property EPenColorDown: TColor read FEPenColorDown write SetEPenColorDown;
    property EnemyleftKind: TEnemyleftKind read FEnemyleftKind write FEnemyleftKind;
    property EOnFocusedShow: Boolean read FEOnFocusedShow write SetEOnFocusedShow;
    property EOnFocusedColor: TColor read FEOnFocusedColor write SetEOnFocusedColor;
    property EnemyRoundedWidth: Integer read FEnemyRoundedW write SetEnemyRoundedW;
    property EnemyRoundedHeight: Integer read FEnemyRoundedH write SetEnemyRoundedH;

    property Caption: String read FCaption write SetCaption;

    property Anchors;
    property Action;
    property BiDiMode;
    //property Cancel;
    //property Constrains;
    //property Default;
    property DragCursor;
    property DragKind;
    property DragMode;
    property Enabled;
    //property ModalResult;
    property ParentBiDiMode;
    //***property ParentFont;
    property ParentShowHint;
    property PopupMenu;
    property ShowHint;
    property TabOrder;
    property TabStop;
    property Visible;

    property OnClick;
    property OnContextPopup;
    property OnDblClick;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDock;
    property OnEndDrag;
    property OnEnter;
    property OnExit;
    property OnKeyDown;
    property OnKeyPress;
    property OnKeyUp;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnStartDock;
    property OnStartDrag;

  end;

procedure Register;

implementation

procedure Register;
begin
 RegisterComponents('enemyleft', [TEButton]);
end;

constructor TEButton.Create(AOwner: TComponent);
begin
 inherited Create(AOwner);
 DoubleBuffered := True;
 FEFont := TFont.Create;
 FEFontOver := TFont.Create;
 FEFontDown := TFont.Create;
 FEColor:=clWhite;
 FEColorOver:=clSilver;
 FEColorDown:=clGray;
 FEBrushStyle:=bsSolid;
 FEBrushStyleOver:=bsSolid;
 FEBrushStyleDown:=bsSolid;
 FEPenColor:=clSilver;
 FEPenColorOver:=clGray;
 FEPenColorDown:=clSilver;
 Width:=75;
 Height:=25;
 EMouseOver:=false;
 EMouseDown:=false;
 FEOnFocusedShow:=true;
 FEOnFocusedColor:=clAqua;
 FEnemyRoundedW:=5;
 FEnemyRoundedH:=5;
 TabStop:=True;
 isCaption:=false;
end;


destructor TEButton.Destroy;
begin
 FEFont.Free;
 inherited Destroy;
end;

procedure TEButton.Paint;
begin
 inherited;
 if (not isCaption) then
  SetCaption(Name);
 isCaption:=true;

 if FEnemyleftKind = Button then
  PaintButton
 else if FEnemyleftKind = Rounded then
  PaintRounded
 else if FEnemyleftKind = ArrowRight then
  PaintArrowRight;
 exit;
end;

procedure TEButton.PaintButton;
begin
 if (csDesigning in ComponentState) or (not EMouseOver) then
 begin
  Canvas.Brush.Color := FEColor;
  Canvas.Brush.Style := FEBrushStyle;
  Canvas.Pen.Color := FEPenColor;
  Canvas.Rectangle(0,0,width,height);
  Canvas.Font.Assign(Self.FEFont);
  Canvas.TextOut((width - Canvas.TextWidth(Caption)) div 2,(height - Canvas.TextHeight(Caption)) div 2,Caption);
 end
 else if (EMouseOver) then
 begin
  if (EMouseDown) then
  begin
   Canvas.Brush.Color := FEColorDown;
   Canvas.Brush.Style := FEBrushStyleDown;
   Canvas.Pen.Color := FEPenColorDown;
   Canvas.Rectangle(0,0,width,height);
   Canvas.Font.Assign(Self.FEFontDown);
   Canvas.TextOut((width - Canvas.TextWidth(Caption)) div 2,(height - Canvas.TextHeight(Caption)) div 2,Caption);
  end
  else
  begin
   Canvas.Brush.Color := FEColorOver;
   Canvas.Brush.Style := FEBrushStyleOver;
   Canvas.Pen.Color := FEPenColorOver;
   Canvas.Rectangle(0,0,width,height);
   Canvas.Font.Assign(Self.FEFontOver);
   Canvas.TextOut((width - Canvas.TextWidth(Caption)) div 2,(height - Canvas.TextHeight(Caption)) div 2,Caption);
  end;
 end;
 if (Focused) then
 begin
  if (FEOnFocusedShow) then
  begin
   Canvas.Pen.Color := FEOnFocusedColor;
   Canvas.Brush.Style := bsClear;
   Canvas.Rectangle(1,1,width-1,height-1);
  end;
 end;
end;

procedure TEButton.PaintRounded;
begin
 if (csDesigning in ComponentState) or (not EMouseOver) then
 begin
  Canvas.Brush.Color := FEColor;
  Canvas.Brush.Style := FEBrushStyle;
  Canvas.Pen.Color := FEPenColor;
  Canvas.RoundRect(0,0,width,height,FEnemyRoundedW,FEnemyRoundedH);
  Canvas.Font.Assign(Self.FEFont);
  Canvas.TextOut((width - Canvas.TextWidth(Caption)) div 2,(height - Canvas.TextHeight(Caption)) div 2,Caption);
 end
 else if (EMouseOver) then
 begin
  if (EMouseDown) then
  begin
   Canvas.Brush.Color := FEColorDown;
   Canvas.Brush.Style := FEBrushStyleDown;
   Canvas.Pen.Color := FEPenColorDown;
   Canvas.RoundRect(0,0,width,height,FEnemyRoundedW,FEnemyRoundedH);
   Canvas.Font.Assign(Self.FEFontDown);
   Canvas.TextOut((width - Canvas.TextWidth(Caption)) div 2,(height - Canvas.TextHeight(Caption)) div 2,Caption);
  end
  else
  begin
   Canvas.Brush.Color := FEColorOver;
   Canvas.Brush.Style := FEBrushStyleOver;
   Canvas.Pen.Color := FEPenColorOver;
   Canvas.RoundRect(0,0,width,height,FEnemyRoundedW,FEnemyRoundedH);
   Canvas.Font.Assign(Self.FEFontOver);
   Canvas.TextOut((width - Canvas.TextWidth(Caption)) div 2,(height - Canvas.TextHeight(Caption)) div 2,Caption);
  end;
 end;
 if (Focused) then
 begin
  if (FEOnFocusedShow) then
  begin
   Canvas.Pen.Color := FEOnFocusedColor;
   Canvas.Brush.Style := bsClear;
   Canvas.RoundRect(1,1,width-1,height-1,FEnemyRoundedW,FEnemyRoundedH);
  end;
 end;
end;

procedure TEButton.PaintArrowRight;
var
 Points: array[1..4] of TPoint;
begin
 if (csDesigning in ComponentState) or (not EMouseOver) then
 begin
  Points[1]:=Point(0,height div 4);
  Points[2]:=Point(width,height div 4);
  Points[3]:=Point(width,height);
  Points[4]:=Point(width,height div 2);
  Canvas.Brush.Color := FEColor;
  Canvas.Brush.Style := FEBrushStyle;
  Canvas.Pen.Color := FEPenColor;
  Canvas.Polygon(Points);
  //Canvas.RoundRect(0,0,width,height,FEnemyRoundedW,FEnemyRoundedH);
  Canvas.Font.Assign(Self.FEFont);
  Canvas.TextOut((width - Canvas.TextWidth(Caption)) div 2,(height - Canvas.TextHeight(Caption)) div 2,Caption);
 end
 else if (EMouseOver) then
 begin
  if (EMouseDown) then
  begin
   Canvas.Brush.Color := FEColorDown;
   Canvas.Brush.Style := FEBrushStyleDown;
   Canvas.Pen.Color := FEPenColorDown;
   Canvas.RoundRect(0,0,width,height,FEnemyRoundedW,FEnemyRoundedH);
   Canvas.Font.Assign(Self.FEFontDown);
   Canvas.TextOut((width - Canvas.TextWidth(Caption)) div 2,(height - Canvas.TextHeight(Caption)) div 2,Caption);
  end
  else
  begin
   Canvas.Brush.Color := FEColorOver;
   Canvas.Brush.Style := FEBrushStyleOver;
   Canvas.Pen.Color := FEPenColorOver;
   Canvas.RoundRect(0,0,width,height,FEnemyRoundedW,FEnemyRoundedH);
   Canvas.Font.Assign(Self.FEFontOver);
   Canvas.TextOut((width - Canvas.TextWidth(Caption)) div 2,(height - Canvas.TextHeight(Caption)) div 2,Caption);
  end;
 end;
 if (Focused) then
 begin
  if (FEOnFocusedShow) then
  begin
   Canvas.Pen.Color := FEOnFocusedColor;
   Canvas.Brush.Style := bsClear;
   Canvas.RoundRect(1,1,width-1,height-1,FEnemyRoundedW,FEnemyRoundedH);
  end;
 end;
end;

procedure TEButton.DoEnter;
begin
 inherited;
 Invalidate;
end;

procedure TEButton.DoExit;
begin
 inherited;
 Invalidate;
end;

procedure TEButton.CMMouseEnter(var Message: TMessage);
begin
 inherited;
 EMouseOver := true;
 RePaint;
end;

procedure TEButton.CMMouseLeave(var Message: TMessage);
begin
 inherited;
 EMouseOver := false;
 RePaint;
end;

procedure TEButton.SetEFont(const Value: TFont);
begin
 FEFont.Assign(Value);
 RePaint;
end;

procedure TEButton.SetEFontOver(const Value: TFont);
begin
 FEFontOver.Assign(Value);
 RePaint;
end;

procedure TEButton.SetEFontDown(const Value: TFont);
begin
 FEFontDown.Assign(Value);
 RePaint;
end;

procedure TEButton.SetEColor(const Value: TColor);
begin
 FEColor := Value;
 RePaint;
end;

procedure TEButton.SetEColorOver(const Value: TColor);
begin
 FEColorOver := Value;
 RePaint;
end;

procedure TEButton.SetEColorDown(const Value: TColor);
begin
 FEColorDown := Value;
 RePaint;
end;

procedure TEButton.SetEBrushStyle(const Value: TBrushStyle);
begin
 FEBrushStyle := Value;
 RePaint;
end;

procedure TEButton.SetEBrushStyleOver(const Value: TBrushStyle);
begin
 FEBrushStyleOver := Value;
 RePaint;
end;

procedure TEButton.SetEBrushStyleDown(const Value: TBrushStyle);
begin
 FEBrushStyleDown := Value;
 RePaint;
end;

procedure TEButton.SetEPenColor(const Value: TColor);
begin
 FEPenColor := Value;
 RePaint;
end;

procedure TEButton.SetEPenColorOver(const Value: TColor);
begin
 FEPenColorOver := Value;
 RePaint;
end;

procedure TEButton.SetEPenColorDown(const Value: TColor);
begin
 FEPenColorDown := Value;
 RePaint;
end;

procedure TEButton.SetEOnFocusedShow(const Value: Boolean);
begin
 FEOnFocusedShow := Value;
 RePaint;
end;

procedure TEButton.SetEOnFocusedColor(const Value: TColor);
begin
 FEOnFocusedColor := Value;
 RePaint;
end;

procedure TEButton.SetEnemyRoundedW(const Value: Integer);
begin
 FEnemyRoundedW := Value;
 RePaint;
end;

procedure TEButton.SetEnemyRoundedH(const Value: Integer);
begin
 FEnemyRoundedH := Value;
 RePaint;
end;

procedure TEButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 if (Button=mbLeft) then
 begin
  EMouseDown := true;
  RePaint;
  if Assigned(FOnMouseDown) then FOnMouseDown(Self);
 end;
end;

procedure TEButton.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
 EMouseDown := false;
 RePaint;
 if Assigned(FOnMouseUp) then FOnMouseUp(Self);
end;

procedure TEButton.SetCaption(const Value: String);
begin
 FCaption := Value;
 RePaint;
end;

procedure TEButton.KeyPress(var Key: Char);
begin
 if (Key=#13) then
  Click;
end;

end.
:-D Natürlich mit einer Frage verbunden...

1f) Ich will die Eigenschaft Default zur verfügung stellen.
Da diese Eigenschaft in keinem Vorgänger vorkommt, muss ich diese
selber programmieren. (Ist der Button Default reagiert er auf den Tastendruck Enter,
egal welche Komponente Fokusiert ist).

Wie Fange ich alle Tastenereignisse ab?

2f) Wie man in meinem Beispiel sieht, versuche ich die standard Caption auf den Komponentennamen zu setzen,
so wie ich es jetzt habe funktionierts. Einzige Nebenwirkung: Setzt man den Button auf ein Formular/Frame, dann
ist die Caption im OBJEKTINSPEKTOR erst gesetzt wenn man eine andere einstellung fokusiert. Zudem ists in meinem
Beispiel schlecht/kompliziert gemacht.

Wie setzte ich nun die standard Caption korrekt?

3f) Ich bin auch dankbar für jeden sonstige Tipp!

Sachen die ich anders machen sollte?

Grüsse
Enamyleft

cherry 24. Apr 2006 12:07

TEButton - Eigener Button
 
Na?

MaBuSE 24. Apr 2006 16:36

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von cherry
Na?

Wer wird denn hier ungeduldig werden?

Zitat:

Zitat von cherry
1f) Ich will die Eigenschaft Default zur verfügung stellen.
Da diese Eigenschaft in keinem Vorgänger vorkommt, muss ich diese
selber programmieren. (Ist der Button Default reagiert er auf den Tastendruck Enter,
egal welche Komponente Fokusiert ist).

Schau doch mal in den Quelltext der VCL wie Borland das bei den Buttons gemacht hat.

Zitat:

Zitat von cherry
Wie Fange ich alle Tastenereignisse ab?

Du verwendest ja schon CM_MOUSEENTER und CM_MOUSELEAVE.
Es gibt noch eine Menge weiterer Messages, die man verwenden kann.

Du musst hier im wesentlichen zwischen drei Arten unterscheiden:
  • WM_XXX Nachichten (Das WM steht für Windows Messages.)
  • CN_XXX Nachichten (Das CN steht für Component Notifications.) und
  • CM_XXX Nachichten (Das CM steht für Component Messages.)
Die WM_XXX Nachichten werden direkt von Windows an die Applikation gesendet. Manchmal sind die Nachichten aber nicht für das Form, sondern für einzelne Komponenten auf dem Form. Aus diesem Grund werden dann von dem Form (bzw. allgemein Parent Objekt) CN_XXX Nachichten an die Controlls gesendet für die die WM_XXX Nachichten eigentlich gedacht waren. Component Notifications sind also refektierte Windows Messages. CM_XXX Nachichten dagegen sind Nachichten die ausschließlich von der VCL generiert werden.

In Komponenten (Objekten) kann demnach WM_, CN_ und CM_ Nachichten abfangen.

Es gibt ein Dokument in dem alle CN und CM Nachichten aufgelistet sind.
(s. Anhang)

Zitat:

Zitat von cherry
2f) Wie man in meinem Beispiel sieht, versuche ich die standard Caption auf den Komponentennamen zu setzen,
so wie ich es jetzt habe funktionierts. Einzige Nebenwirkung: Setzt man den Button auf ein Formular/Frame, dann
ist die Caption im OBJEKTINSPEKTOR erst gesetzt wenn man eine andere einstellung fokusiert. Zudem ists in meinem
Beispiel schlecht/kompliziert gemacht.
Wie setzte ich nun die standard Caption korrekt?

gleiche Antwort wie bei 1f) :-)

Zitat:

Zitat von cherry
3f) Ich bin auch dankbar für jeden sonstige Tipp!
Sachen die ich anders machen sollte?

Was mir damals bei der Komponentenentwicklung geholfen hat sind die Quelltexte der VCL.
Diese liegen ja dem Delphi (ich glaube ab Prof) bei.
(z.B. C:\Programme\Borland\Delphi7\Source\...)

Dort kann man sehen wie die Borländer das programmiert haben.
Sehr lehrreich.

cherry 25. Apr 2006 07:44

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von MaBuSE
Zitat:

Zitat von cherry
Na?

Wer wird denn hier ungeduldig werden?

Sorry, bin von natur aus ein wenig ungeduldug. Wollte ja nicht vergessen gehen :roll:

Zitat:

Zitat von MaBuSE
Was mir damals bei der Komponentenentwicklung geholfen hat sind die Quelltexte der VCL.
Diese liegen ja dem Delphi (ich glaube ab Prof) bei.
(z.B. C:\Programme\Borland\Delphi7\Source\...)

Vielen Dank für den Tipp. Das wird mir einige Fragen beantworten.
Dank auch für den Anhang, ich hab nämlich so ein Dokument gesucht leider keins gefunden.

Dank der schön...

Gruss

cherry 26. Apr 2006 10:40

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Ok, ich gebs zu.. Ich bin zu blöde:

Ich hab weder rausgefunden welche Message ALLE Tastendrücke abfängt (Auch die die gar nichts mit meiner Komponente am Hut haben),
geschweige denn wie ich die Property "Deault" (Siehe z.B. TButton) programmiere!

Und das alles trotz den guten Tipps von MaBuSe...

AM I TOO SEXY?

cherry 1. Mai 2006 08:06

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von MaBuSE
Was mir damals bei der Komponentenentwicklung geholfen hat sind die Quelltexte der VCL.
Diese liegen ja dem Delphi (ich glaube ab Prof) bei.
(z.B. C:\Programme\Borland\Delphi7\Source\...)

Dort kann man sehen wie die Borländer das programmiert haben.
Sehr lehrreich.

Dort habe ich die Datei "Buttons.pas" gefunden. Nur leider ist dort nicht ersichtlich wie die Property Default Programmiert
wird. Denn der gewöhnliche Button (TButton) finde ich nid dieser Datei nicht!
Ich finde aber z.B. den (TBitBtn) der von der Klasse TButton abgeleitet ist.. nur wo ist diese?
wo iser? help me!

himitsu 1. Mai 2006 08:09

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Zitat:

Zitat von cherry
...nur wo ist diese?
wo iser? help me!

die OH hilft doch fast immer :zwiner:

Zitat:

Zitat von OH
TButton kapselt ein Schaltflächen-Steuerelement von Windows.

Unit
StdCtrls


cherry 1. Mai 2006 08:12

Re: Eigene Komponente von TCustomControl > Eigenschaftsed
 
Uhh... Danke...

stahli 9. Aug 2011 11:48

AW: Eigene Komponente von TCustomControl > Eigenschaftseditor!
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hänge mich mal hier dran...

Erst einmal danke an MaBuSE. Ich habe hier einige interessante Hinweise gefunden :thumb:
(Die Bilder im Beitrag 9 sind übrigens hübsch. :wink:)

Nun zu meiner Frage:

Ich habe unter XE nun einen Propertyeditor für eine Komponete (TodDataSet) eingerichtet. Grundsätzlich funktioniert dies schon, aber es gibt ein paar unerwartete Details.
Anbei mal ein Screenshot, wie der Objektinspektor die Komponente standardmäßig anzeigt und wie mit registriertem Editor...

Ich kann jetzt mit Doppelklick mein Formular öffnen, hätte aber sonst gern die Originale Darstellung der SubPropertys. Insbesondere die Eigenschaft "Name" soll nicht dargestellt werden. Kann ich das auf Knopfdruck erreichen oder muss ich GetPropertys überschreiben?


aktueller Quelltext:
Delphi-Quellcode:
unit odPropNameEditor;
 
interface
 
uses
  DesignEditors, DesignIntf;
 
type
 
  TodPropNameEditor = class(TClassProperty)
  private
  protected
  public
    function GetAttributes: TPropertyAttributes; override;
    procedure Edit; override;
  published
  end;
 
implementation
 
uses
  odPropNameEditorDialog;
 
{ TodPropNameEditor }
 
procedure TodPropNameEditor.Edit;
begin
  ShowOdPropNameEditorDialog(nil);
end;
 
function TodPropNameEditor.GetAttributes: TPropertyAttributes;
begin
  Result := inherited GetAttributes + [paDialog];
end;
 
end.
 
*********************************************
 
unit odControlsEditorsRegister platform;
 
interface
 
procedure Register;
 
implementation
 
uses
  DesignIntf, odExpertEditor, odExpert, od_dataset, odPropNameEditor;
 
procedure Register;
begin
  RegisterComponentEditor(TodExpert, TodExpertEditor);
  RegisterPropertyEditor(TypeInfo(TodDataSet), nil, '', TodPropNameEditor);
end;
 
end.

MaBuSE 9. Aug 2011 13:39

AW: Eigene Komponente von TCustomControl > Eigenschaftseditor!
 
Zitat:

Zitat von stahli (Beitrag 1115752)
Die Bilder im Beitrag 9 sind übrigens hübsch. :wink:

Ich habe das Verhalten der DP als Bug gemeldet.
( http://www.delphipraxis.net/issue-400/ )

Bitte den Bug bestätigen, damit er auch geprüft/behoben wird.-
( Are you able to reproduce this bug? -> [yes] !!! )

Zu deiner Frage kann ich im Moment leider nicht viel sagen, da ich mich schon eine Weile nicht mehr mit Komponentenerstellung beschäftigt habe. Und zum Einarbeiten fehlt mir im Monent die Zeit. Sorry.
Ich hoffe das jemand anderes eine Lösung schreibt.
Grüße
MaBuSE


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz