|
Registriert seit: 10. Jun 2002 Ort: Unterhaching 11.421 Beiträge Delphi 12 Athens |
#4
Hi DP-ler,
jetzt geht es endlich richtig los, der erste echte Schritt in Richtung Komponentenerstellung. Ich habe mich entschieden, vor dem Debug Manager noch eine kleine Runde Komponenten-Basics einzuschieben. Sonst wäre es wahrscheinlich doch ein wenig schwer mitzukommen, wenn man noch nie Komponenten entwickelt hat. Und schließlich ist das ja auch das gewollte Publikum des Artikels. Estellen einer Komponente Fangen wir mal ganz vorne an und das auch praktisch. Delphi starten und/oder eventuell geöffnete Projekte schließen. Nochmal: ich nutze die englische Delphi Version, es sollte aber nicht schwer sein, entsprechende Schritte nachzuvollziehen. Im Menü Datei|Neu wählen wir jetzt das Item Komponente aus und klicken den OK Schalter. ![]() Anschließend präsentiert Delphi uns einen Dialog, der uns die Möglichkeit gibt, den "Rahmen" der Komponente zu erstellen. Dort füllen wir die Startdaten der Komponente ein. ![]() Delphi erstellt uns jetzt eine kleine Unit, welche wie folgt aussieht.
Code:
Damit ist der erste Schritt schon geschafft, wir haben eine Komponente, die, in ihrer jetzigen Form, völlig unnütz ist, aber bereits funktioniert. Aber den Test sparen wir uns noch ein paar Minuten. Etwas sinnvolles wäre doch ganz nett, oder?
unit SenselessSample;
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TSenselessSample = class(TComponent) private { Private declarations } protected { Protected declarations } public { Public declarations } published { Published declarations } end; procedure Register; implementation procedure Register; begin RegisterComponents('gate(n)etwork', [TSenselessSample]); end; end. Der Aufbau unserer Unit Was sehen wir jetzt eigentlich? Die Unit für unsere Komponente ist genau wie jede andere Unit aufgebaut.
Hinweis: Ein Hinweis sei mir noch gestattet. In den jeweiligen Abschnitten (private, protected, ...) müssen alle Variablen stets vor den Methoden (procedure, function) und Eigenschaften (property) deklariert werden. "Filling in the meat" Wollen wir dieser sinnlosen Komponente mal noch ein wenig Inhalt geben. Dazu deklarieren wir insgesamt sechs Eigenschaften. Zwei geben uns die Möglichkeit Fließkommazahlen entgegenzunehmen, vier weitere zeigen jeweils auf eine TLabel Komponente. Dazu füllen wir den Bereich zwischen private und end; wie folgt aus.
Code:
Der Bezeichner property teilt Delphi mit, das es sich um eine Eigenschaft der Klasse handelt. In diesem Fall habe ich die Eigenschaften X, Y, Result_Add, Result_Sub, Result_Mul und Result_Div deklariert. Noch sind wir aber nicht fertig. Jetzt positionieren wir den Cursor innerhalb des gerade eingefügten Bereiches und lassen Delphi ein bisschen für uns arbeiten. Einfach mal die Tasten [STRG]+[SHIFT]+[C] drücken und Delphi "completes" unsere Klasse und die ganze Unit.
published
{ Published declarations } property X: Double; property Y: Double; property Result_Add: TLabel; property Result_Sub: TLabel; property Result_Mul: TLabel; property Result_Div: TLabel; end;
Code:
Da wir uns entschieden haben, TLabel zu nutzen müssen wir die uses Klausel ein wenig erweitern.
unit SenselessSample;
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TSenselessSample = class(TComponent) private FX: Double; FY: Double; FResult_Add: TLabel; FResult_Sub: TLabel; FResult_Mul: TLabel; FResult_Div: TLabel; procedure SetResult_Add(const Value: TLabel); procedure SetResult_Div(const Value: TLabel); procedure SetResult_Mul(const Value: TLabel); procedure SetResult_Sub(const Value: TLabel); procedure SetX(const Value: Double); procedure SetY(const Value: Double); { Private declarations } protected { Protected declarations } public { Public declarations } published { Published declarations } property X: Double read FX write SetX; property Y: Double read FY write SetY; property Result_Add: TLabel read FResult_Add write SetResult_Add; property Result_Sub: TLabel read FResult_Sub write SetResult_Sub; property Result_Mul: TLabel read FResult_Mul write SetResult_Mul; property Result_Div: TLabel read FResult_Div write SetResult_Div; end; procedure Register; implementation procedure Register; begin RegisterComponents('gate(n)etwork', [TSenselessSample]); end; { TSenselessSample } procedure TSenselessSample.SetResult_Add(const Value: TLabel); begin FResult_Add := Value; end; procedure TSenselessSample.SetResult_Div(const Value: TLabel); begin FResult_Div := Value; end; procedure TSenselessSample.SetResult_Mul(const Value: TLabel); begin FResult_Mul := Value; end; procedure TSenselessSample.SetResult_Sub(const Value: TLabel); begin FResult_Sub := Value; end; procedure TSenselessSample.SetX(const Value: Double); begin FX := Value; end; procedure TSenselessSample.SetY(const Value: Double); begin FY := Value; end; end.
Code:
Was ist alles geschehen?
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; wird zu uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; Schauen wir uns einfach mal die aufgefüllte Zeile einer property an.
Code:
Delphi hat für uns die üblichste Behandlungsart einer Eigenschaft eingetragen. Das heisst, wenn jemand die Eigenschaft X ermitteln will, so wird der Wert der Variablen FX direkt zurückgegeben. Delphi hat auch gleich die Variable FX für uns im private Bereich deklariert. Danke Borland. Ausserdem hat Delphi auch gleich definiert, wie Änderungen der Eigenschaft übernommen werden. Damit wir bei eventuellen Änderungen reagieren können, hat Delphi das Setzen der Variable nicht direkt erledigt, sondern eine "Wrapper" Methode SetX erstellt. Diese Methode übernimmt das Speichern der Änderungen.
property X: Double;
wird zu property X: Double read FX write SetX;
Code:
Diese Art der Variablenbehandlung kommt uns jetzt noch sehr zu gute.
procedure TSenselessSample.SetX(const Value: Double);
begin FX := Value; end; "And Action!" Jetzt fügen wir noch eine Methode zum private Bereich hinzu, damit wir die die Hauptfunktionalität noch angenehm verpacken können.
Code:
Und noch einmal [STRG]+[SHIFT]+[C] für die automatische Code-[b]C[/c]ompletion drücken!
private
... procedure UpdateLabels; { Private declarations } protected
Code:
Jetzt haben wir unsere Hauptmethode fast fertig. Es müssen nur noch ein paar Zeilen Code hinein und das Ergebnis sieht wie folgt aus.
procedure TSenselessSample.UpdateLabels;
begin end;
Code:
Für jedes Ergebnis überprüfen wir zuerst, ob ein entsprechendes Label vorhanden ist und anschließend versuchen wir das Ergebnis zu ermitteln und darzustellen. Wenn das fehlschlagen sollte, liefern wir eine entsprechende Fehlermeldung zurück.
procedure TSenselessSample.UpdateLabels;
begin // summe ermitteln und darstellen if Assigned(FResult_Add) then try // label für summe wurde zugewiesen FResult_Add.Caption := FloatToStr(FX + FY); except on E: Exception do // oops FResult_Add.Caption := E.Message; end; // differenz ermitteln und darstellen if Assigned(FResult_Sub) then try // label für differenz wurde zugewiesen FResult_Sub.Caption := FloatToStr(FX - FY); except on E: Exception do // oops FResult_Sub.Caption := E.Message; end; // produkt ermitteln und darstellen if Assigned(FResult_Mul) then try // label für produkt wurde zugewiesen FResult_Mul.Caption := FloatToStr(FX * FY); except on E: Exception do // oops FResult_Mul.Caption := E.Message; end; // quotient ermitteln und darstellen if Assigned(FResult_Div) then try // label für quotient wurde zugewiesen FResult_Div.Caption := FloatToStr(FX / FY); except on E: Exception do // oops FResult_Div.Caption := E.Message; end; end; Jetzt tragen wir in alle Set Methoden noch als letzten den Aufruf zu unserer UpdateLabels; Methode ein und sind soweit fertig. Einen Schönheitsfehler müssen wir noch beseitigen. Da es geschehen kann, dass eines der zugewiesenen Labels vom Form entfernt wird, müssen wir abschliessend noch dieses Ereignis abfangen und die entsprechden FResult_XXX Variabel auf nil setzen! Dazu überlaufen wir die Standard Notification Methode.
Code:
Den kompletten Code könnt Ihr jetzt lesen.
protected
{ Protected declarations } procedure Notification( aComponent: TComponent; Operation: TOperation ); override;
Code:
Installieren der Komponente
unit SenselessSample;
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TSenselessSample = class(TComponent) private FX: Double; FY: Double; FResult_Add: TLabel; FResult_Sub: TLabel; FResult_Mul: TLabel; FResult_Div: TLabel; procedure SetResult_Add(const Value: TLabel); procedure SetResult_Div(const Value: TLabel); procedure SetResult_Mul(const Value: TLabel); procedure SetResult_Sub(const Value: TLabel); procedure SetX(const Value: Double); procedure SetY(const Value: Double); procedure UpdateLabels; { Private declarations } protected { Protected declarations } procedure Notification( aComponent: TComponent; Operation: TOperation ); override; public { Public declarations } published { Published declarations } property X: Double read FX write SetX; property Y: Double read FY write SetY; property Result_Add: TLabel read FResult_Add write SetResult_Add; property Result_Sub: TLabel read FResult_Sub write SetResult_Sub; property Result_Mul: TLabel read FResult_Mul write SetResult_Mul; property Result_Div: TLabel read FResult_Div write SetResult_Div; end; procedure Register; implementation procedure Register; begin RegisterComponents('gate(n)etwork', [TSenselessSample]); end; { TSenselessSample } procedure TSenselessSample.Notification( aComponent: TComponent; Operation: TOperation ); begin inherited Notification(aComponent, Operation); if (Operation = opRemove) then begin if aComponent = FResult_Add then FResult_Add := nil; if aComponent = FResult_Sub then FResult_Sub := nil; if aComponent = FResult_Mul then FResult_Mul := nil; if aComponent = FResult_Div then FResult_Div := nil; end; end; procedure TSenselessSample.SetResult_Add(const Value: TLabel); begin FResult_Add := Value; UpdateLabels; end; procedure TSenselessSample.SetResult_Div(const Value: TLabel); begin FResult_Div := Value; UpdateLabels; end; procedure TSenselessSample.SetResult_Mul(const Value: TLabel); begin FResult_Mul := Value; UpdateLabels; end; procedure TSenselessSample.SetResult_Sub(const Value: TLabel); begin FResult_Sub := Value; UpdateLabels; end; procedure TSenselessSample.SetX(const Value: Double); begin FX := Value; UpdateLabels; end; procedure TSenselessSample.SetY(const Value: Double); begin FY := Value; UpdateLabels; end; procedure TSenselessSample.UpdateLabels; begin // summe ermitteln und darstellen if Assigned(FResult_Add) then try // label für summe wurde zugewiesen FResult_Add.Caption := FloatToStr(FX + FY); except on E: Exception do // oops FResult_Add.Caption := E.Message; end; // differenz ermitteln und darstellen if Assigned(FResult_Sub) then try // label für differenz wurde zugewiesen FResult_Sub.Caption := FloatToStr(FX - FY); except on E: Exception do // oops FResult_Sub.Caption := E.Message; end; // produkt ermitteln und darstellen if Assigned(FResult_Mul) then try // label für produkt wurde zugewiesen FResult_Mul.Caption := FloatToStr(FX * FY); except on E: Exception do // oops FResult_Mul.Caption := E.Message; end; // quotient ermitteln und darstellen if Assigned(FResult_Div) then try // label für quotient wurde zugewiesen FResult_Div.Caption := FloatToStr(FX / FY); except on E: Exception do // oops FResult_Div.Caption := E.Message; end; end; end. Der letzte wichtige Schritt ist die Installation der Komponente in der Delphi Palette. Ausserdem könnte man jetzt noch ein Icon für die Komponente erstellen, aber dazu kommen wir ein anderes Mal, wenn es nicht gerade diese sinnlose Komponente ist. Um die Komponente zu installieren, wählt im Menü Komponenten|Komponente installieren. Delphi trägt automatisch alles ein und schlägt Euch das Standard User-Komponenten Packet vor. Das ist auch in Ordnung. Mit OK bestätigen. ![]() Anschliessend seht Ihr das Fenster zum kompilieren und installieren des Packages. ![]() "Kompilieren" und anschließend "Installieren" drücken. Fertig. Der Test des Sinnlosen Alle offenen Projekte schließen und eine neue Anwendung anlegen. 4 Labels auf das Form packen und von der "gate(n)etwork" Seite unsere Komponente auswählen und auf das Form packen. Jetzt nur noch die vier Labels den entsprechenden Eigenschaften zuordnen und ein wenig im Objekt Inspektor rumspielen. Viel Spass, ![]() ![]()
Lizbeth W.
Ich bin nicht zurück, ich tue nur so |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |