Newsgroup: it.comp.lang.delphi
Titolo: Evento su Package

prevedendo di caricare a runtime un package, non
e' possibile dichiarare un'evento sul form chiamante.
esiste un'alternativa ?
eventualmente esiste un modo per chiamare un'azione presente
su un TActionList del form principale con
Application.MainForm.ExecuteAction(???) ?
Maurizio
^^^^^
procedure Tfrm_Main.Button1Click(Sender: TObject);
var Handle:HModule;
    FormClass:TFormClass;
    myForm:TForm;
begin
   Handle:=LoadPackage('Test_Pck01.bpl');
   if Handle>0 then
   begin
     FormClass:=TFormClass(GetClass('Tfrm_Secondario'));
     if Assigned(FormClass) then
     begin
       myForm:=FormClass.Create(Self);
    end;
    // questa dichiarazione non e' accettata non essendoci
    // riferimenti al form secondario
    //myForm.OnButtonPress := ButtonPressed;
     myForm.Show;
   end;
end;
// form su Pacakge
....
type
  Tfrm_Secondario = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    FOnButtonPress: TNotifyEvent;
    { Private declarations }
  public
    { Public declarations }
    property OnButtonPress: TNotifyEvent read FOnButtonPress write 
FOnButtonPress;
  end;
procedure Tfrm_Secondario.Button1Click(Sender: TObject);
begin
  if Assigned(FOnButtonPress) then
  begin
    FOnButtonPress(Sender);
  end;
  close;
end; 

 esiste un'alternativa ?
Suppongo che in queste situazioni si possa ricorrere solo alle funzioni 
RTTI per impostare una proprietà specifica dell'istanza di una classe 
caricata dinamicamente.
Oppure, è possibile seguire un'altra strada (ipotetica): supponendo che 
tu faccia uso dei package per estendere determinate funzionalità della 
tua applicazione, potrebbe essere utile creare un package che contenga 
le classi di base, ad esempio una classe di un Form generico da cui 
discendono tutte le classi di Form preposte ad una determinata 
funzionalità che, attraverso il polimorfismo, aggiungano aspetti 
specifici ad un determinato comportamento comune.
In quel caso, potresti riferirti nel codice direttamente alla classe 
base del Form da cui discendono tutte le classi implementate nei package 
  "satelliti".
Se la tua situazione non è questa, cioè se stai implementando in ciascun 
package delle finestre slegate tra loro e individuali, caricandole poi 
da programma attraverso un riferimento diretto, fatto però con il nome 
sottoforma di stringa e non utilizzando la classe come tipo di dato, non 
comprendo bene che utilità riveste, per te, il package, se non quello di 
poter dilazionare il caricamento del package stesso gestendo questa 
operazione manualmente, ma poco altro.
In breve, qual è il motivo della tua scelta architetturale?
C'è un motivo preciso per cui carichi i package manualmente?
Ciao,
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)


il motivo della scelta, sarebbe di poter distribuire gli aggiornamenti
tramite file .bpl
cosi' se per ipotesi devo gestire 2 tipi di report diversi tra loro ,
che so 1 per i panettieri ed 1 per i meccanici, ma facenti parte dello
stesso applicativo, potrei solo fare manutenzione del package relativo
alla singola attivita'.
di solito pero' uso un solo eseguibile, fatto di varie unit, di cui solo
la principale ed il datamodule sono sempre in memoria, gli altri form
delle varie unit vengono creati quando sevono e distrutti alla loro 
chiusura.
da quanto sto sperimentando , mi pare che i packages non diano maggiore
flessibilita'.
Maurizio 

 flessibilita'.
Non è sufficiente caricare dinamicamente una classe al posto di 
referenziarla direttamente per poter sperimentare la flessibilità: si 
tratta di una caratteristica che viene conferita se si utilizzano gli 
strumenti in un certo modo, e secondo me la strada che hai seguito non 
lo consente. :-|


> consente. :-|
non mi e' chiaro , se creo una classe base su una unit separata,
e poi eredito da questa, non vengono mantenuti i valori.
entrambe le form "usano" la unit con la classe TAuto
Maurizio
es: unit con la classe base
  TAuto=Class
  private
    { Private declarations }
    iNrRuote:Integer;
  public
    { Public declarations }
    Constructor Create(Ruote:Integer);
    function LeggeRuote:Integer;
  end;
unit che eredita da TAuto
type
  TForm3 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  TMyAuto=Class(TAuto)
  end;
procedure TForm3.FormCreate(Sender: TObject);
var myCar:TMyAuto;
    NRuote:Integer;
begin
  myCar:=TMyAuto.Create(4);
  NRuote:=myCar.LeggeRuote;
  ShowMessage(IntToStr(NRuote));
end;
altra unit che eredita da TAuto
la classe Auto e' gia' istanziata, ma il valore letto dalla
funzione non e' quello memorizzato nella variabile
****************************************
type
  TForm5 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  TNewAuto=Class(TAuto)
  private
    { Private declarations }
  public
    { Public declarations }
  end;
procedure TForm5.Button1Click(Sender: TObject);
var nAuto:TNewAuto;
    iTRuote:Integer;
begin
  iTRuote:=nAuto.LeggeRuote;
  ShowMessage('Tot Ruote ' + IntToStr(iTRuote));
end;

 e poi eredito da questa, non vengono mantenuti i valori.
Per forza: si tratta di oggetti distinti, anzi il secondo non sembra 
essere stato nemmeno creato.
Credo che ci sia qualche lacuna in ambito OOP... :-)


   iTRuote:=nAuto.LeggeRuote;
             ^^^^^^^^^^^^^^^^^^^^
Tu vuoi leggere un metodo nAuto che è di tipo TNewAuto e non è neanche
istanziato.. (come dice il buon Alka)
Devi leggere invece l'istanza di tMyAuto se ce l'hai da qualche parte..
altrimenti devi fare
var 
  nMyAuto:TMyAuto;
begin
  nMyAuto := tMyAuto.create(3); // si tratta di un apecar :P
  iTRuote:=nAuto.LeggeRuote;
Ti manca forse il concetto di istanza di classe, oppure si tratta di
semplice distrazione..? ;-)
-- 
Morde

>  nMyAuto := tMyAuto.create(3); // si tratta di un apecar :P
io farei sempre tMyAuto.create(2); // tropppo bello scorazzare in moto !
grazie delle indicazioni

 ci sono arrivato [...]
Non so se dirti di sì o di no, perché - almeno io - non riesco mai ad 
avere un "quadro" di ciò che stai cercando, e quando ce l'ho hai già 
cambiato obiettivo. :-|



la risposta era relativa all'istanza coretta di una classe;
per il resto il mio obiettivo non e' cambiato, e' sempre
capire meglio il funzionamento dei package, e del perche'
di certi comportamenti.
questo form e' stato spostato su un pacakge e rimosso
dal progetto
type
  TFormProva = class(TForm)
    Button1: TButton;
    Panel1: TPanel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
...
da un form per caricare il package, eseguo la
verifica dell'Hande ed in seguito devo creare il form
ma FClass risulta sempre nil, eppure
1 - TFormProva e' presente nel package
2 - il package e' stato compilato con Build
3 - nelle opzioni di progetto e' stato spuntato Compile with RuntimePackages
procedure TForm3.Button4Click(Sender: TObject);
var Handle:HModule;
    FClass:TFormClass;
    Form:TForm;
begin
  Handle:=LoadPackage('Test_PckA.bpl');
  if Handle>0 then
  begin
    FClass:=TFormClass(GetClass('TFormProva'));
    if FClass<>nil then
    begin
      // crea form
    end;
  end;
end;


mancava RegisterClass nella unit spstata nel package
initialization
  RegisterClass(TFormProva);
  testClasseRif:=TClasseProva.Create;
con RegisterClass(TFormProva)
FClass non risulta piu' nil
Maurizio