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/)
-   -   VCL-Komponenten aufeinander aufbauen (https://www.delphipraxis.net/179762-vcl-komponenten-aufeinander-aufbauen.html)

Ookami 30. Mär 2014 19:29

VCL-Komponenten aufeinander aufbauen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Gemeinde,

ich wollte mal was Testen und das raubt mir gerade den Verstand.
Was jetzt folgt ist viel Stoff zum Lesen, aber ich wollte mal sicher gehen, dass ich mich nicht umständlich und falsch ausdrücke.
Mein Problem, ich wollte eine VCL-Komponente aufbauen. Der Bereich TBMBasic. Der Funktioniert auch soweit.
Der Code ist
a. noch nicht fertig und
b. der Übersicht halber beschnitten.

Delphi-Quellcode:
 Type TMBBasic                 = Class (TGraphicControl)
        private                        
         fMouseOver            : Boolean;
         fPushDown             : Boolean;

         fHasFrame             : Boolean;
         fFrameStyle           : TPenStyle;
         fFrameThickness       : Integer;
         fFrameColor           : TColor;
         fBackFilling          : tBrushStyle;
         fBackGroundColor      : TColor;
         Procedure SetHasFrame (Value : Boolean);
         Procedure SetFrameStyle (Value : TPenStyle);
         Procedure SetFrameThickness (Value : Integer);
         Procedure SetBackFilling (Value : TBrushStyle);
         Procedure SetFrameColor (Value : TColor);
         Procedure SetBackGroundColor (Value : TColor);
        protected
           procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); Override;
           procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); Override;
           procedure CMMouseLeave (var Message: TMessage); message CM_MouseLeave;
           procedure CMMouseEnter (var Message: TMessage); message CM_MouseEnter;
           procedure CMFontChanged (var Message: TMessage); message CM_FONTCHANGED;
           procedure CMTextChanged (var Message: TMessage); message CM_TEXTCHANGED;
        public
         procedure  Paint; override;
         constructor Create(AOwner:Tcomponent);override;
         destructor Destroy; override;
        published
         property HasFrame      : Boolean read fHasFrame write SetHasFrame;
         property FrameStyle    : TPenStyle read fFrameStyle write SetFrameStyle;
         property FrameThickness : Integer read fFrameThickness write SetFrameThickness;
         property FrameColor    : TColor read fFrameColor write SetFrameColor;
         property BackFilling   : tBrushStyle read fBackFilling write SetBackFilling;
         property BackGroundColor: TColor read fBackGroundColor write SetBackGroundColor;

Hier die Paint-Methode. Wie gesagt funktioniert.

Delphi-Quellcode:
procedure TMBBasic.Paint;
var      rgn                    : Hrgn;
          Area                   : TRect;
Procedure DrawFrame;
Begin
     canvas.pen.style:= fFrameStyle;
     canvas.Pen.Width := fFrameThickness;
     canvas.pen.color := fFrameColor;
     canvas.brush.Style := bsClear;
     canvas.Rectangle(0, 0, Width-fFrameThickness+1, Height-fFrameThickness+1);
End;
Begin
     Area := Rect(0, 0, Width, Height);
     canvas.pen.style:= fFrameStyle;
     canvas.brush.color := fBackGroundColor;
     canvas.brush.Style := fBackFilling;
     canvas.FillRect(Area);
     if fHasFrame then drawframe;
     
End;
Ich habe von hier eine Klasse abgeleitet, die wiederum auch funktioniert.

Delphi-Quellcode:

Type TMBTitleLine              = Class (TMBBasic)
        private
         fTitle                 : String;
         fDirection             : sdDirection;
         procedure SetTitle (Value : String);
         procedure SetDirection (Value : sdDirection);
        protected
        public
         procedure  Paint; override;
         constructor Create(AOwner:Tcomponent);override;
         destructor Destroy; override;
        published
         property Title         : String read fTitle write SetTitle;
         property Direction     : sdDirection read fDirection write SetDirection;
      End;
in der Paint-Methode

Delphi-Quellcode:
procedure TMBTitleLine.Paint;
var      rgn                    : Hrgn;
          Area                   : TRect;
procedure drawcaption;
begin
     canvas.brush.style := bsclear;
     canvas.font.color := Font.color;
     DrawText (canvas.handle, @Title[1], -1, Area, DT_SINGLELINE or DT_VCENTER or DT_CENTER or DT_END_ELLIPSIS);
end;
Procedure DrawFrame;
Begin
     canvas.pen.style:= fFrameStyle;
     canvas.Pen.Width := fFrameThickness;
     canvas.pen.color := fFrameColor;
     canvas.brush.Style := bsClear;
     canvas.Rectangle(0, 0, Width-fFrameThickness+1, Height-fFrameThickness+1);
End;
Begin
     canvas.font.Assign(Font);
     canvas.brush.style:=bssolid;
     Height := font.Size * 5;                          <== Das scheint nicht zu gehen
     
     Area := Rect(0, 0, Width, Height);
     canvas.pen.style:= fFrameStyle;
     canvas.brush.color := fBackGroundColor;
     canvas.brush.Style := fBackFilling;
     canvas.FillRect(Area);
     if fHasFrame then drawframe;
     if Title<>'' then DrawCaption;
     
End;

Soweit sogut: Nun wollte ich eine weitere Komponente, die dann später die Hauptkomponente sein wird aufbauen.
Nennen wir die mal TMBPaintBoard und schon gingen die Probleme los.



Delphi-Quellcode:
 Type TMBPaintBoard             = Class (TGraphicControl)
        private
         fMouseOver            : Boolean;
         fPushDown             : Boolean;

         fMBTitleLine           : TMBTitleLine;

         Procedure SetTitleLine (Value : TMBTitleLine);
        protected
        public
         procedure  Paint; override;
         constructor Create(AOwner:Tcomponent);override;
         destructor Destroy; override;
        published
          property Titleline  : TMBTitleLine read fMBTitleLine write SetTitleLine;
      End;
Das nächste dann, wenn ich versuche diese in der Paint-Methode zu zeichnen,

Delphi-Quellcode:
procedure TMBPaintBoard.Paint;
var      rgn                    : Hrgn;
          Area                   : TRect;
Procedure DrawFrame;
Begin
     canvas.pen.style:= fFrameStyle;
     canvas.Pen.Width := fFrameThickness;
     canvas.pen.color := fFrameColor;
     canvas.brush.Style := bsClear;
     canvas.Rectangle(0, 0, Width-fFrameThickness+1, Height-fFrameThickness+1);
End;
Begin
     Area := Rect(0, 0, Width, Height);
     canvas.pen.style:= fFrameStyle;
     canvas.brush.color := fBackGroundColor;
     canvas.brush.Style := fBackFilling;
     canvas.FillRect(Area);
     if fHasFrame then drawframe;

     fMBTitleLine.Left   := Left + 5;
     fMBTitleLine.Top    := Top + 5;
     fMBTitleLine.Width  := Width - 10;
     fMBTitleLine.fBackGroundColor := clSkyBlue;

     fMBTitleLine.Parent := self.Parent;
     fMBTitleLine.Paint;
Wenn ich das dann starten möchte dann wird das soweit auch gezeichnet.
Ich habe die Komponente registriert und eingebunden. Funktioniert auch. Taucht auf der TForm als MBPaintBoard1 auf, wird gezeichnet und eigentlich könnte ich zufrieden sein.

Nur die Properties, die ich dann im Objektinspektor bekomme schauen schon mal seltsam aus und Zuweisungen funktionieren garnicht, d.h. nicht so ganz.
Im Designmode zeigt es mir die Geschichte korrekt an, im Laufzeitmode nicht.

Ich habe mal ein Bild Ausschnitt vom Objektinspekor mit angehängt.

Wäre toll, wenn einer von euch ne Antwort weiß. Ich komm grad nicht wirklich weiter.

Thx

stahli 30. Mär 2014 19:48

AW: VCL-Komponenten aufeinander aufbauen
 
Du musst wahrscheinlich noch SetSubComponent verwenden: http://www.delphipraxis.net/79726-un...der-gruen.html

Ookami 30. Mär 2014 20:04

AW: VCL-Komponenten aufeinander aufbauen
 
Hallo Stahli,

ich hab das mal so gemacht. Hat aber nichts bewirkt.

Trotzdem Danke

Der schöne Günther 31. Mär 2014 09:24

AW: VCL-Komponenten aufeinander aufbauen
 
Dumme Frage, aber müsste man für die Properties die auch in die DFM nicht noch eine
Delphi-Quellcode:
stored
-Direktive anhängen oder ist das irgendwie schon automatisch?

Ookami 31. Mär 2014 10:12

AW: VCL-Komponenten aufeinander aufbauen
 
Hallo Günther,

ich steh noch auf dem Schlauch. Umstellung Sommerzeit und so weiter...
aber Scherz beiseite, ich versteh dich gerade wirklich nicht.

Könntest du da bitte ein bisschen genauer werden?

Danke mal

Der schöne Günther 31. Mär 2014 10:29

AW: VCL-Komponenten aufeinander aufbauen
 
Delphi-Quellcode:
type TMyComponent = class(...)
   protected
      procedure setMyProperty(const Value: String);
      function getMyProperty(): String;
   
   published
      property name: String
         read getMyProperty
         write setMyProperty
         stored True;

end;
Ich dachte "Stored" gibt bei einer Property noch an, ob die Werte in der DFM gespeichert werden oder nicht. Allerdings merke ich grade, dass ja garkeine eigene DFM für die Komponente im Spiel ist. Deshalb Quatsch :oops:

stahli 31. Mär 2014 11:17

AW: VCL-Komponenten aufeinander aufbauen
 
Ich habe das schon so verstanden, dass es um die Speicherung im Formular geht.

Stored ist schon wichtig, aber standardmäßig True.
Aus dem Wiki:
Zitat:

Speicherbezeichner

Die optionalen Direktiven stored, default und nodefault sind Speicherbezeichner. Sie haben keinerlei Auswirkungen auf die Funktionsweise des Programms, sondern bestimmen, ob die Werte der published-Eigenschaften in Formulardateien gespeichert werden.

Nach der Angabe stored muss der Wert True oder False, der Name eines booleschen Feldes oder der Name einer parameterlosen Methode folgen, die einen booleschen Wert zurückgibt. Beispiel:
property Name : TComponentName read FName write SetName stored False;

Wird eine Eigenschaft ohne die Angabe von stored deklariert, entspricht dies der Definition stored True.
@Ookami
Dein Quelltext ist vielleicht etwas komplex um das trocken nachzuvollziehen.
Mach doch mal einen kleinen Test mit einer Unterkomponente, in der Du nur einen Text oder so speicherst.
Es geht doch darum, dass Du zur Designtime die Untereigenschaften deklarierst und nach dem Projektstart oder nach dem Delphi-Neustart sind Deine Einstellungen weg - oder?
Dann musst Du dafür sorgen, dass die Unterkomponenteneigenschaften mit in der DFM gespeichert werden.
Dazu muss eigentlich Deine Komponente Owner der Unterkomponente sein und SetSubComponent(True) sein.

Mein Tipp: Versuche mal einen kleinen, übersichtlich Test mit sehr einfachen Komponenten.

Ookami 31. Mär 2014 11:43

AW: VCL-Komponenten aufeinander aufbauen
 
Hallo Stahli,

Danke noch für die Antwort.

Zitat:

@Ookami
Dein Quelltext ist vielleicht etwas komplex um das trocken nachzuvollziehen.
Mach doch mal einen kleinen Test mit einer Unterkomponente, in der Du nur einen Text oder so speicherst.
Es geht doch darum, dass Du zur Designtime die Untereigenschaften deklarierst und nach dem Projektstart oder nach dem Delphi-Neustart sind Deine Einstellungen weg - oder?
Dann musst Du dafür sorgen, dass die Unterkomponenteneigenschaften mit in der DFM gespeichert werden.
Dazu muss eigentlich Deine Komponente Owner der Unterkomponente sein und SetSubComponent(True) sein.

Mein Tipp: Versuche mal einen kleinen, übersichtlich Test mit sehr einfachen Komponenten
.
Den Test werd ich so mal machen, wie du es vorschlägst. Bleibt mir wohl auch nichts anderes übrig.

Um ehrlich zu sein, hab ich das mit den DFM so noch nie händisch gemacht.
Ist das so zu verstehen, wie das Günther vorgeschlagen hat?

siehe
Delphi-Quellcode:
type TMyComponent = class(...)
   protected
      procedure setMyProperty(const Value: String);
      function getMyProperty(): String;
   
   published
      property name: String
         read getMyProperty
         write setMyProperty
         stored True;

end;
Falls ja, dann versuch ich das so. Falls nein, wäre ich auf ein kleines Snippet angewiesen, gesucht hab ich schon, bin aber nicht besonders fündig geworden. Hab zumindest nichts gefunden, was mich weiterbringt.
Und –
Zitat:

Es geht doch darum, dass Du zur Designtime die Untereigenschaften deklarierst und nach dem Projektstart oder nach dem Delphi-Neustart sind Deine Einstellungen weg - oder?
Die Frage ist mit JA zu beantworten. Das ist alles weg.

stahli 31. Mär 2014 11:58

AW: VCL-Komponenten aufeinander aufbauen
 
Hier mal ein Auszug aus einem alten Projekt:

Delphi-Quellcode:
unit odEdit;

interface

uses
  StdCtrls,
{$INCLUDE 'inc\uses.inc'};

type

  TodEdit = class(TEdit)
  private
{$INCLUDE 'inc\privat_var.inc'}
{$INCLUDE 'inc\privat_meth.inc'}
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
{$INCLUDE 'inc\public_prop.inc'}
    procedure WndProc(var Message: TMessage); override;
  published
{$INCLUDE 'inc\published_prop.inc'}
//  Die inc sieht so aus: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//    property DataSet: TodDataSet read FDataSet;
//    property OnAfterGetData: TNotifyEvent read FOnAfterGetData write FOnAfterGetData;
//    property OnBeforeGetData: TNotifyEvent read FOnBeforeGetData write FOnBeforeGetData;

  end;

procedure Register;

implementation

uses
  Graphics, Controls, Themes, Windows, SysUtils;

procedure Register;
begin
  RegisterComponents('odControls', [TodEdit]);
end;

{ TodEdit }

function TodEdit{$INCLUDE 'inc\get_od.inc'}
procedure TodEdit{$INCLUDE 'inc\set_od.inc'}
function TodEdit{$INCLUDE 'inc\get_PropName.inc'}
procedure TodEdit{$INCLUDE 'inc\set_PropName.inc'}
function TodEdit{$INCLUDE 'inc\get_PropText.inc'}
procedure TodEdit{$INCLUDE 'inc\set_PropText.inc'}

constructor TodEdit.Create(AOwner: TComponent);
begin
  inherited;
{$INCLUDE 'inc\create.inc'}
//  Die inc sieht so aus: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//  FDataSet := TodDataSet.Create(Self);
//  DataSet.SetSubComponent(True);

end;

destructor TodEdit.Destroy;
begin
  inherited;
end;

procedure TodEdit.WndProc(var Message: TMessage);
begin
...
  inherited;
end;

end.
TodDataSet war von TComponent abgeleitet:

Delphi-Quellcode:
  TodDataSet = class(TComponent)
  private
...
  protected
...
  public
...
  published
    property PropName: String read get_PropName write set_PropName;
  end;
Das hat so wunderbar funktioniert.

Ookami 31. Mär 2014 12:04

AW: VCL-Komponenten aufeinander aufbauen
 
Ok Stahli,

Danke erst mal. Das Muss ich mir heute Abend mal in Ruhe durch die Birne ziehen.
So ganz bin ich da in der Schnelle noch nicht durchgestiegen, aber ich denke ich hab den entscheidenden Hinweis erhalten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:17 Uhr.

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