2015-10-16 15 views
6

Ciò fa seguito a mia risposta a questa Q:Ottenere un riferimento a un oggetto all'interno della Delphi

Can I change the display format for strings in the watch list?

Si scopre che ad un certo punto tra il D7 e XE3, l'attuazione dei Guardiani della IDE Finestra modificata dall'utilizzo di TListView a TVirtualStringTree.

Anche se ho inviato un aggiornamento alla mia risposta che funziona con XE4 ignorando il VST e ottenendo il valore dell'orologio dagli appunti, mi piacerebbe comunque essere in grado di ottenere il valore di orologio dal VST se posso. Penso di sapere come fare questo una volta che ho un riferimento al VST, ma il problema è che il mio tentativo di ottenere uno fallisce.

Di seguito è riportato un MCVE del codice che sto utilizzando nel mio pacchetto personalizzato. Spero che ciò che fa sia auto-esplicativo. Il problema è che il codice nel blocco

if WatchWindow.Components[i] is TVirtualStringTree then begin 
    [...] 
    end; 

non esegue mai, nonostante il classname "TVirtualStringTree" che appare in Memo1. Ovviamente il componente con quel nome di classe fallisce il test "è". Immagino che il motivo per cui TVirtualTreeView sia stato compilato nell'IDE sia una versione diversa da quella che sto usando, v.5.3.0, che è il predecessore più vicino che potrei trovare su XE4.

Quindi, la mia domanda è, è la spiegazione probabile, e c'è qualcosa che posso fare al riguardo? Sospetto che qualcuno possa far prosperare la versione di TVirtualStringTree utilizzata per XE4 da un cappello, che potrebbe risolvere il mio problema.

type 
    TOtaMenuForm = class(TForm) 
    Memo1: TMemo; 
    procedure FormCreate(Sender: TObject); 
    private 
    WatchWindow : TForm; 
    VST : TVirtualStringTree; 
    end; 

procedure TOtaMenuForm.FormCreate(Sender: TObject); 
var 
    i : Integer; 
    S : String; 
begin 

    WatchWindow := Nil; 
    VST := Nil; 

    // Iterate the IDE's forms to find the Watch Window 
    for i := 0 to Screen.FormCount - 1 do begin 
    S := Screen.Forms[i].Name; 
    if CompareText(S, 'WatchWindow') = 0 then begin 
     WatchWindow := Screen.Forms[i]; 
     Break; 
    end; 
    end; 

    Assert(WatchWindow <> Nil); 

    if WatchWindow <> Nil then begin 
    Memo1.Lines.Add('Looking for VST'); 
    for i := 0 to WatchWindow.ComponentCount - 1 do begin 
     Memo1.Lines.Add(IntToStr(i) + ':' + WatchWindow.Components[i].ClassName); 
     if WatchWindow.Components[i] is TVirtualStringTree then begin 
     VST := TVirtualStringTree(WatchWindow.Components[i]); 
     Memo1.Lines.Add('found VST'); 
     Break; 
     end; 
    end; 
    if VST = Nil then 
     Memo1.Lines.Add('VST not found'); 
    end; 
end; 

Btw, mi rendo conto che le soluzioni che dipendono di dettagli attuativi di IDE sono suscettibili di essere fragile, ma questo è solo per il divertimento (mi piaceva la sfida di ottenere dati di stringa da una componente che va fuori del suo modo per evitare di conservarne uno qualsiasi).

+3

La versione VST non è l'unico problema. L'operatore 'is' fallisce se il codice è compilato con RTTI diversi da quelli dell'IDE, quindi un componente VST all'interno del file binario è diverso da un componente VST all'interno dell'IDE. Anche se il tuo codice utilizza la stessa identica versione VST, RTTI non corrisponde ancora. È qui che entrano in gioco i pacchetti di runtime. Il tuo binario deve collegarsi al pacchetto runtime in modo che condivida lo stesso RTL dell'IDE e deve collegarsi allo stesso pacchetto che l'IDE utilizza per il suo componente VST. Ma se VST è compilato direttamente nell'IDE e non importato da un pacchetto, sei SOL ... –

+3

... dovresti rinunciare all'operatore 'is' e usare invece un confronto' ClassName() '. Ciò consentirà almeno di rilevare il componente VST dell'IDE. Ma * l'accesso * non sarà sicuro a meno che non si disponga della stessa versione ESATTA in modo che i layout di memoria corrispondano ancora. –

+0

@RemyLebeau: Grazie. In effetti, avevo cercato di ignorare il risultato "i" e di eseguire il casting rigido sulla base del nome della classe, ma di quello di AV quando provo a chiamare i metodi dell'oggetto. Fwiw, ho usato la stessa tecnica "è" in D7 in cui la finestra di controllo è una TListView e che ha funzionato bene, in termini di ottenere il riferimento e usarlo. – MartynA

risposta

0

Può essere possibile provare a utilizzare solo le proprietà pubblicate di incorporate nell'implementazione IDE TVirtualStringTree tramite i metodi RTTI per fare ciò che si desidera?

+0

In realtà, ho risolto questo problema utilizzando quello che descrivo nella mia seconda risposta a questo q: http://stackoverflow.com/questions/33121397/can-i-change-the-display-format-for-strings-in- the-watch-list/33127943 # 33127943 – MartynA