2013-02-09 7 views
5

Ich möchte TToolBar mit einer anderen Klasse namens MyTToolBar Unterklasse, so dass ich eine Methode überschreiben kann. Ich bin neu in Delphi, aber nach zwei Stunden, in denen ich verschiedene Methoden ausprobiert habe, kann ich MyTToolBar nicht anstelle von TToolBar verwenden. Ich kann nicht die erste Person sein, die eine Methode für eine visuelle Komponentenklasse überschreiben möchte.Delphi Unterklasse visuelle Komponente und verwenden Sie

Ich komme mehr aus einem Xcode-Hintergrund, wo Unterklasse eine visuelle Komponente ist einfach. Sie erstellen eine Unterklasse (z. B. MySubclass) einer übergeordneten Klasse (z. B. MySuperClass) und weisen dann einfach die Unterklasse in der Interface Builder-Ansicht von Xcode zu. Die Unterklasse wird automatisch erkannt und verwendet.

Warum kann ich das in Delphi RAD Studio XE3 nicht tun?

Nach dem Hinzufügen einer TToolBar zu einem TForm scheint es nicht möglich, die Klasse zu ändern. Ich habe den Objektinspektor sowie die .PAS-Quellcodedatei ausprobiert. Wenn ich die Klasse in der .PAS-Datei ändere, erhalte ich die Fehlermeldung, dass die Symbolleiste "vom Typ Vcl.ComCtrls.TToolBar sein sollte, aber als MyTToolbar deklariert ist. Korrigiere die Deklaration?" Das scheint einfach albern zu sein ...

Oh, und ich habe auch den Assistenten für neue Komponenten verwendet: Datei -> Neu -> Andere -> Delphi-Projekte -> Delphi-Dateien -> Komponente. Ich wähle den Vorgänger für MyTToolBar als TToolBar aus und sage ihm, dass er auf der Palettenseite "Samples" registriert werden soll. Es erscheint jedoch nicht auf der Seite "Samples".

+0

In Bezug auf Ihren letzten Absatz behandelt meine Antwort dieses Problem (der Teil über das Erstellen eines Pakets zuerst und das Installieren dieses Pakets am Ende, nachdem Ihre Komponente erstellt wurde). –

+0

.. Vielleicht war ich falsch über die enge Abstimmung, dies scheint nicht über Laufzeit zu sein ... Ich glaube, [Dokumentation] (http://docwiki.embarcadero.com/RADStudio/XE3/en/Introduction_to_component_creation_Index) ist ziemlich Umfassende Informationen zum Erstellen von Komponenten zur Entwurfszeit. –

+0

@KenWhite Danke für die Information über die Verpackung der Komponente. Ich war auf der Suche nach der Möglichkeit, die Komponente während der Entwicklung spontan zu ändern und wollte daher die Verpackungslösung für diese einfache Überschreibung nicht verwenden. – spurgeon

Antwort

15

Die beste Entsprechung zu Ihrem XCode-Ansatz ist die Verwendung einer "Interposer" -Klasse in Delphi. Im Grunde ändern Sie nicht den Code, den die IDE für die Verwendung des Standards TToolBar erstellt. Sie deklarieren stattdessen eine neue Klasse, die sich von der Standardkomponente TToolBar ableitet, aber auch TToolBar heißt und sie für den Compiler sichtbar macht, nachdem der Standard TToolBar deklariert wurde. Die Klasse TToolBar, die der Compiler zuletzt gesehen hat, ist der tatsächliche Klassentyp, der immer dann instanziiert wird, wenn der DFM TForm gestreamt wird.

Sie können Ihre benutzerdefinierte TToolBar Klasse machen durch den Compiler nach dem Standard TToolBar Klasse durch eine von zwei verschiedenen Arten zu sehen:

  1. erklären die kundenspezifische TToolBar Klasse in der gleichen Einheit wie Ihre TForm Klasse:

    unit MyForm; 
    
    interface 
    
    uses 
        ..., Vcl.ComCtrls, ...; 
    
    type 
        TToolBar = class(Vcl.ComCtrls.TToolBar) 
        // override what you need... 
        end; 
    
        TMyForm = class(TForm) 
        ToolBar1: TToolBar; // <-- do not change this! 
        ... 
        end; 
    
    implementation 
    
    // implement custom TToolBar as needed... 
    
    // normal TForm implementation code as needed ... 
    
    end. 
    
  2. Sie die benutzerdefinierte TToolBar Klasse in einer eigenen Einheit erklären können, die dann in die TForm Einheit hinzugefügt wird uses Klausel nach dem ComCtrls Gerät wurde hinzugefügt:

    unit MyToolBar; 
    
    interface 
    
    uses 
        ..., Vcl.ComCtrls; 
    
    type 
        TToolBar = class(Vcl.ComCtrls.TToolBar) 
        // override what you need... 
        end; 
    
    implementation 
    
    // implement custom TToolBar as needed... 
    
    end. 
    

    .

    unit MyForm; 
    
    interface 
    
    uses 
        ..., Vcl.ComCtrls, ..., MyToolBar; 
    
    type 
        TMyForm = class(TForm) 
        ToolBar1: TToolBar; // <- do not change this! 
        ... 
        end; 
    
    implementation 
    
    // normal TForm implementation code as needed ... 
    
    end. 
    

Dieser Ansatz funktioniert auf einer Pro-Projekt nur Grundlage. Wenn Sie Ihre benutzerdefinierte Klasse TToolBar in mehreren Projekten verwenden möchten, sollten Sie sie besser in der IDE installieren, wie in @KenWhite beschrieben, und sie anstelle des Standards TToolBar verwenden. Gehen Sie zurück zum Namen TMyToolBar (oder was auch immer), nennen Sie es nicht mehr TToolBar, da es nicht als Interposer verwendet werden soll. Stellen Sie sicher, dass das Paket in seinen Projektoptionen als "Runtime and Designtime" markiert ist (das Erstellen separater Laufzeit- und Designtime-ony-Pakete liegt außerhalb des Bereichs dieser Diskussion). TMyToolBar wird zur Entwurfszeit verfügbar sein, damit Sie auf Ihre TForm wie jede andere Komponente fallen können.Wenn nicht, haben Sie es nicht richtig eingerichtet.

+2

+1, aber ich finde einen (lokalen) Klassenhelfer viel besser. Hat sogar Zugriff auf private Mitglieder, wenn Sie ihnen in den Hilfsmethoden den Präfix Self vorgeben. –

+1

Ein Klassenhelfer kann einer vorhandenen Klasse neue Eigenschaften/Methoden hinzufügen, aber vorhandene Methoden nicht überschreiben. Und nur Versionen der letzten Jahre unterstützen Klassenhelfer. –

+0

Ja, ich wechselte, als ich davon erfuhr. Und möglicherweise könnte das Erben gefälscht werden, indem eine Methode mit demselben Namen deklariert und dabei Self.MethodName verwendet wird. Der Compiler kann jedoch auf den gleichen Namen stoßen. Ich kann es im Moment nicht versuchen, da ich nur D5 auf diesem Rechner habe. –

1

eine Einheit für Sie Klasse erstellen:

Unit YourComponent; 
interface 
uses 
.... 
Type 
TYourNewClass=Class(ExistingClass) 
    private 
    ... 
    protected 
    ... 
    public 
    ... 
    published 
    end; 

    procedure Register; 

implementation 

..... 

procedure Register; 
begin 
    RegisterComponents('YourPalette', [TYourNewClass]); 
end; 

ein neues Paket erstellen (oder eine eigene bestehende öffnen), und Sie Gerät hinzufügen auf Sie Package.bpl installieren zu wählen.

+0

Wie kann ich die neue Unterklasse im laufenden Betrieb bearbeiten (packen und installieren)? Muss ich es jedes Mal neu packen, wenn ich eine Änderung an der unterklassierten visuellen Komponente vornehmen möchte? – spurgeon

+0

Ja, Sie müssten das Paket jedes Mal neu kompilieren, wenn Sie seinen Code ändern. Wenn Sie etwas "on-the-fly" möchten, verwenden Sie stattdessen den Interceptor-Ansatz, wie ich es in meiner Antwort beschrieben habe. –

5

Um eine Komponente im vorhandenen Formular zu ändern, muss sie tatsächlich eine Komponente sein, zu der die IDE zur Entwurfszeit eine Instanz erstellen kann. Dies bedeutet, dass die IDE natürlich zuerst darüber informiert werden muss.

Der Weg, dies zu tun, ist Ihre eigene Nachkommen-Komponente zu erstellen und tatsächlich in einem Design-Time-Paket in der IDE zu installieren. Sie können es dann auf Ihrem Formular anstelle der Standardversion ablegen oder es auf vorhandenen Formularen mit ein wenig Arbeit ersetzen. (Sie müssen jedoch zuerst Ihre Version erstellen und installieren.)

Starten Sie mit File->New->Package (Delphi) aus dem IDE-Menü. Speichern Sie das Paket wie jedes andere Projekt (z. B. MyComponents.dpk).

Verwenden Sie jetzt File->New->Other->Delphi Files, und doppelklicken Sie im rechten Bereich auf Component. Der Assistent New Component wird gestartet, in dem Sie die vorhandene Komponente auswählen können, von der Sie absteigen möchten (oder eine neue erstellen).

die Schritte des Assistenten folgen, und Sie werden mit der Grundschale Ihrer Komponente am Ende:

unit MyToolBar1; 

interface 

uses 
    System.SysUtils, System.Classes, Vcl.Controls, Vcl.ToolWin, Vcl.ComCtrls; 

type 
    TMyToolBar = class(TToolBar) 
    private 
    { Private declarations } 
    protected 
    { Protected declarations } 
    public 
    { Public declarations } 
    published 
    { Published declarations } 
    end; 

procedure Register; 

implementation 

procedure Register; 
begin 
    RegisterComponents('Samples', [TMyToolBar]); 
end; 

end. 

implementieren, was Funktionen, die Sie wollen in der neuen Nachkommen, und speichern Sie die Datei.

Klicken Sie mit der rechten Maustaste auf das Paket in der (standardmäßig das obere rechte Fenster in der IDE), und wählen Sie Install aus dem Kontextmenü. Dies kompiliert und erstellt das Paket und installiert es automatisch in der IDE. (Das Beispiel, das ich gezeigt habe, würde die neue Komponente auf die Seite Samples in der Palette setzen, basierend auf dem, was im -Aufruf angegeben ist.)

Danach können Sie ein bestehendes Formular ändern (machen Sie zuerst eine Sicherungskopie der .pas und .dfm Dateien!). Ich verwende die TToolBar, die Sie erwähnten, und den Beispielersatz, für den ich die Shell geschrieben habe, in den folgenden Anweisungen.

Ändern Sie den Klassennamen im Quellcode-Editor manuell von TToolBar in TMyToolBar.

Klicken Sie mit der rechten Maustaste auf das Formular und wählen Sie View as Text aus dem Kontextmenü.

Suchen Sie nach TToolBar und ändern Sie sie von TToolBar in TMyToolBar.

Klicken Sie erneut mit der rechten Maustaste und wählen Sie View as Form aus dem Kontextmenü. Wenn Sie diese Schritte richtig ausgeführt haben, sollten Sie im Objektinspektor TMyToolBar auf die Symbolleiste klicken. Wenn Sie es nicht sehen (oder Fehlermeldungen erhalten), haben Sie etwas falsch gemacht. Sie können die Registerkarte schließen, indem Sie oben im Quelltext-Editor mit der rechten Maustaste darauf klicken und "Close tab" auswählen und die Eingabeaufforderung zum Speichern von Änderungen mit "Nein" beantworten und dann ggf. die Sicherungskopien wiederherstellen.

+0

Obwohl dies nicht als Antwort akzeptiert wurde, ist dies ein gutes Tutorial zum Erstellen einer benutzerdefinierten Delphi-Komponente! –