2013-02-09 10 views
5

Vorrei creare sottoclasse di TToolBar con un'altra classe denominata MyTToolBar in modo da poter eseguire l'override di un metodo. Sono nuovo di Delphi, ma dopo due ore di provare vari metodi, non riesco a ottenere MyTToolBar da utilizzare al posto di TToolBar. Non posso essere la prima persona che desidera eseguire l'override di un metodo su una classe componente visiva.Componente visivo di sottoclasse Delphi e utilizzo

Vengo più da uno sfondo Xcode in cui la sottoclasse di un componente visivo è facile. Crei una sottoclasse (ad es., MySubclass) di una classe genitore (ad es. MySuperClass) e quindi assegni semplicemente la sottoclasse nella vista Interface Builder di Xcode. La sottoclasse viene automaticamente riconosciuta e utilizzata.

Perché non riesco a farlo in Delphi RAD Studio XE3?

Dopo aver aggiunto un TToolBar a un TForm, non sembra possibile modificare la classe. Ho provato attraverso l'Object Inspector e attraverso il file di codice sorgente .PAS. Se cambio la classe nel file .PAS, viene visualizzato un messaggio di errore che indica che la barra degli strumenti "deve essere di tipo Vcl.ComCtrls.TToolBar ma viene dichiarata come MyTToolbar. Correggere la dichiarazione?" Questo sembra solo sciocco ...

Oh, e ho anche utilizzato il nuovo componente guidato dalla selezione di: File -> Nuovo -> Altro -> Progetti Delphi -> File Delphi -> Componente. Seleziono l'antenato per MyTToolBar come TToolBar e gli dico di registrarsi nella pagina della palette 'Samples'. Tuttavia, non appare nella pagina "Samples".

+0

Per quanto riguarda l'ultimo paragrafo, la mia risposta risolve questo problema (la parte riguardante la creazione di un pacchetto e l'installazione di quel pacchetto alla fine dopo che il componente è stato creato). –

+0

.. Forse mi sbagliavo sul voto ravvicinato, questo non sembra riguardare il runtime ... Credo che [documentazione] (http://docwiki.embarcadero.com/RADStudio/XE3/en/Introduction_to_component_creation_Index) sia piuttosto completo sulla creazione di componenti in fase di progettazione. –

+0

@KenWhite Grazie per le informazioni sulla confezione del componente. Stavo cercando la possibilità di modificare il componente al volo durante lo sviluppo e quindi non volevo utilizzare la soluzione di packaging per questo semplice override. – spurgeon

risposta

15

L'approccio più vicino all'approccio XCode consiste nell'utilizzare una classe "interposer" in Delphi. Fondamentalmente, non si modifica il codice creato dall'IDE per l'utilizzo dello standard TToolBar. Si dichiara invece una nuova classe che deriva dal componente standard TToolBar ma si denomina anche TToolBar e lo si rende visibile al compilatore dopo che è stato dichiarato lo standard TToolBar. Qualunque sia la classe TToolBar visualizzata per ultima dal compilatore, sarà il tipo di classe effettivo che viene istanziato ogni volta che lo stream TForm viene trasmesso in streaming.

È possibile rendere la vostra abitudine TToolBar classe essere visto dal compilatore dopo l'TToolBar classe standard da uno dei due modi diversi:

  1. dichiarare la classe personalizzata TToolBar nella stessa unità come la classe TForm:

    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. è possibile dichiarare la classe personalizzata TToolBar nella propria unità che viene quindi aggiunto al gruppo del è stato aggiuntoclausola dopo che l'unità ComCtrls:

    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. 
    

questo approccio funziona solo su una base per-progetto. Se si desidera utilizzare la classe personalizzata TToolBar in più progetti, è preferibile installarlo nell'IDE, come descritto da @KenWhite, e utilizzarlo al posto dello standard TToolBar. Tornare a nominarlo TMyToolBar (o qualsiasi altra cosa), non chiamarlo più TToolBar poiché non verrà utilizzato come interposer. Assicurati che il pacchetto sia contrassegnato come "Runtime and Designtime" nelle sue Opzioni progetto (la creazione di pacchetti separati solo in fase di esecuzione e designtime-ony esula dallo scopo di questa discussione). TMyToolBar sarà disponibile in fase di progettazione per farti cadere sul tuo TForm come qualsiasi altro componente.Se non lo è, non l'hai impostato correttamente.

+2

+1, ma trovo che un helper di classe (locale) sia molto meglio. Ha persino accesso ai membri privati ​​se li prefissi con Self nei metodi di supporto. –

+1

Un helper di classe può aggiungere nuove proprietà/metodi a una classe esistente, ma non può sovrascrivere i metodi esistenti. E solo le versioni degli ultimi anni supportano gli aiutanti di classe. –

+0

Sì, sono passato quando ho saputo di loro. E possibilmente l'ereditarietà potrebbe essere falsificata dichiarando un metodo con lo stesso nome e usando Self.MethodName in quello. Tuttavia, il compilatore potrebbe mostrare la stessa cosa. Non posso provare al momento in quanto ho solo D5 su questa macchina. –

1

creare un'unità per classe:

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

    procedure Register; 

implementation 

..... 

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

creare un nuovo pacchetto (o di aprire una propria esistente) e aggiungere voi unità scegliere installare su di voi Package.bpl.

+0

In tal modo (confezionamento e installazione), come posso modificare la nuova sottoclasse al volo? Devo ricompilarlo ogni volta che voglio apportare una modifica alla componente visiva sottoclasse? – spurgeon

+0

Sì, dovresti ricompilare il pacchetto ogni volta che cambi il suo codice. Se vuoi qualcosa di più "al volo", usa invece l'approccio dell'intercettore, come descritto nella mia risposta. –

5

Per modificare un componente nel modulo esistente, deve essere effettivamente un componente che l'IDE può creare un'istanza di in fase di progettazione. Ciò significa che l'IDE deve esserne consapevole prima, naturalmente.

Il modo per farlo è creare il proprio componente discendente e installarlo effettivamente nell'IDE in un pacchetto in fase di progettazione. È quindi possibile rilasciarlo sul modulo anziché nella versione standard oppure sostituirlo con moduli esistenti con un po 'di lavoro. (Devi comunque creare la tua versione e installarla per prima.)

Inizia con File->New->Package (Delphi) dal menu dell'IDE. Salva il pacchetto come faresti con qualsiasi altro progetto (ad esempio, MyComponents.dpk).

Ora utilizzare File->New->Other->Delphi Files e fare doppio clic su Component nel riquadro destro. Verrà avviata la procedura guidata New Component, in cui è possibile scegliere il componente esistente da cui scendere (o progettarne uno nuovo).

Seguire i passaggi della procedura guidata, e vi ritroverete con il guscio di base del componente:

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. 

implementare la funzionalità desiderata nel nuovo discendente, e quindi salvare il file.

Fare clic con il pulsante destro del mouse sulla confezione nello Project Manager (per impostazione predefinita, la finestra in alto a destra dell'IDE) e scegliere Install dal menu di scelta rapida. Questo compilerà e compilerà il pacchetto e lo installerà automaticamente nell'IDE. (L'esempio che ho mostrato inserirà il nuovo componente nella pagina Samples nella tavolozza in base a quanto indicato nella chiamata RegisterComponents.)

Dopo aver fatto quanto sopra, è possibile modificare un modulo esistente (fare un backup dei .pas e file DFM prima!). Userò lo TToolBar che hai menzionato e la sostituzione del campione per la quale ho pubblicato la shell nelle seguenti istruzioni.

Modificare manualmente il nome della classe nell'editor del codice sorgente da TToolBar a TMyToolBar.

Fare clic con il tasto destro del mouse sul modulo e selezionare View as Text dal menu di scelta rapida.

Trova il TToolBar, e modificarlo TToolBar-TMyToolBar.

Fare nuovamente clic con il tasto destro e selezionare View as Form dal menu di scelta rapida. Se hai eseguito correttamente questa procedura, facendo clic sulla barra degli strumenti dovrebbe mostrarti TMyToolBar nell'Object Inspector. Se non lo vedi (o se ricevi messaggi di errore) hai fatto qualcosa di sbagliato; è possibile chiudere la scheda facendo clic con il pulsante destro del mouse nella parte superiore dell'Editor codice e scegliendo Close tab e rispondere "No" al prompt per il salvataggio delle modifiche, quindi, se necessario, ripristinare dalle copie di backup che si è detto di eseguire prima.

+0

Anche se questo non è stato accettato come risposta, questo è davvero un buon tutorial veloce per creare un componente Delphi personalizzato! –