2011-01-13 12 views
13

So di aver visto un esempio da qualche parte di un hack per definire una versione personalizzata di un componente VCL esistente, come TButton o TEdit, con lo stesso nome di classe e fare qualcosa per renderlo tale lo streamer DFM crea un'istanza della versione anziché dell'originale. Sfortunatamente, mi trovo in una situazione in cui devo essere in grado di farlo e non riesco a trovare la recensione. Qualcuno sa dove trovare informazioni su come realizzare questo?Sostituzione di una classe componente in delphi

+1

Hai guardato nel tuo sacco di trucchi? http://windwings.wordpress.com/2009/10/07/turbocharging-delphi-2010-2-adding-dynamic-functionality-to-3rd-parties-the-solution/#comment-1066 ;-) –

+0

@ Jørn , questo è ciò che questa risposta mostra: http://stackoverflow.com/questions/4685863/replacing-a-component-class-in-delphi/4686920#4686920 –

+1

@Jeroen, lo so ... Ho solo bisogno di mostrare @ Mason il suo "visto da qualche parte". :-) –

risposta

18

Nel modulo è possibile ignorare il metodo ReadState in questo modo:

type 
    TMyForm = class(TForm) 
    protected 
    procedure ReadState(Reader: TReader); override; 
    end; 

procedure TMyForm.ReadState(Reader: TReader); 
begin 
    Reader.OnFindComponentClass := FindComponentClass; 
    inherited; 
end; 

procedure TMyForm.FindComponentClass(Reader: TReader; const ClassName: string; 
    var ComponentClass: TComponentClass); 
begin 
    if ComponentClass=TButton then begin 
    ComponentClass := TMySuperDuperButton; 
    end else if ComponentClass=TEdit then begin 
    ComponentClass := TMyTotallyAwesomeEdit; 
    end; 
end; 

ci sono probabilmente molti altri modi per fare questo, ma questo è come lo faccio!

MODIFICA: l'ispezione di TReader.GetFieldClass(Instance: TObject; const ClassName: string) suggerisce l'hack che Mason ricorda. La prima riga imposta ClassType := Instance.ClassType. Pertanto, sospetto che modificando la dichiarazione nel file pas da Button1: TButton a Button1: MyUnit.TButton, il tuo pulsante venga creato. O forse l'hack è stato quello di aggiungere MyUnit alla clausola uses proprio alla fine in modo che la tua versione di TButton sia quella che fa parte dell'ambito. Tuttavia, niente di tutto ciò sembra molto pratico.

+0

Posso sbagliare, ma aggiungerei anche il controllo per ClassName e non solo ComponentClass. Nel caso in cui qualcosa è cambiato tra Delphi 2 e Delphi XE;) –

+0

Interessante. Non ho sentito parlare di questa versione, ma potrebbe funzionare per quello che devo fare. –

+0

@Eugene Mi dispiace, non capisco cosa intendi. –

11

Immagino che quello che stai cercando di ricordare sia un "interposer class": ereditare una classe che ha lo stesso nome dell'antenato, facendo precedere il nome dell'unità dell'antenato. Poiché il nome della classe non viene modificato, il meccanismo di streaming di dfm non viene disturbato. Avrebbe effetto solo sull'unità in cui la classe viene dichiarata nuovamente, a meno che non sia messa in un'unità separata e quell'unità sia inclusa nella sezione usi dopo le classi base. Ovviamente, non è possibile avere proprietà pubblicate in una classe interposta.

type 
    TButton = class(stdctrls.TButton) 
    protected 
    procedure CreateParams(var Params: TCreateParams); override; 
    end; 

    TForm1 = class(TForm) 
    Button1: TButton; 
    [...] 
    private 
+0

Sì, questo è quello che stavo pensando. Ma la soluzione di David si è rivelata più efficace per il problema che stavo cercando di risolvere. –

Problemi correlati