Newsgroup: it.comp.lang.delphi
Titolo: TComboBox e OnKeyDown

Ciao a tutti,
 
per necessita mi sono creato un mio componente derivato da TComboBox,
perchè avevo la necessità di creare un evento standard alla pressione del 
tasto F1.
 
Per fare questo sul codice del mio componente personalizzato ( sul mio 
package) ho creato un evento OnKeyDown che controlla se ho premuto il
tasto 
F1.
Alla creazione dell'oggetto ho attribuisco all 'evento onKeyDown il mio 
evento personalizzato.
 
Quando utilizzo il mio componente su qualsiasi form di un progetto
funziona 
tutto senza problemi, il problema nasce quando su una determinata form 
voglio andare a creare un ulteriore evento OnkeyDown apposito per quel 
determinato combobox.
 
Vorrei fare in modo che se anche inserisco un nuovo evento OnKeyDown,
venga 
eseguito prima l'evento originale e poi successivamente il nuovo evento,
ma 
non riesco a trovare una soluzione; sul nuovo evento ho provato ad
inserire 
anche Inherited ma il mio evento originario non viene eseguito.
 
Come potrei fare?
 
Grazie a tutti
 
Loris
 
 
 
 
-- 
 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it
 
 
 

 anche Inherited ma il mio evento originario non viene eseguito.
 
Posta il codice che hai scritto: magari non è strutturato correttamente per consentire la corretta propagazione dell'evento.
 
Ciao,
  Marco.
 
-- 
MARCO BREVEGLIERI
#Home: 
http://www.marco.breveglieri.name
 
#Blog: 
http://www.compilaquindiva.net
 

Sorgente del package:
 
  MyComboBox = class (TComboBox)
  private
    FOnMyEvent : TNotifyEvent;
  published
    property OnMyEvent: TNotifyEvent read FOnMyEvent write FOnMyEvent;
 
    procedure OnInternalKeyDown(Sender: TObject; var Key: Word; Shift:  
TShiftState);
  public
    constructor Create(AOwner: TComponent); override;
  end;
 
 
 
constructor MyComboBox.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  OnKeyDown := OnInternalKeyDown;
end;
 
 
procedure MyComboBox.OnInternalKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_F1 then begin
    if Assigned(FOnMyEvent) then
      FOnMyEvent(Sender);
  end;
  //
end;
 
Sorgente per utilizzare il componente:
 
  sul form FormCreate:
 
  MyComboBox1.OnMyEvent := DoShowMyEvent;
  MyComboBox1.OnKeyDown := MyComboBox1KeyDown;
 
 
procedure Form1.DoShowMyEvent(Sender: TObject);
begin
  ShowMessage( (Sender as TComponent).Name);
end;
 
procedure Form1.MyComboBox1KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  inherited;
  if Key = VK_F2 then
    ShowMessage('F2');
end;
 
 
Se premo F1 non succede nulla 
Se premo F2 funziona correttamente
 
 
Grazie


 MyComboBox1.OnKeyDown := MyComboBox1KeyDown; // <--
 
Nella pratica, per intercettare la pressione del tasto, tu assegni la proprietà "OnKeyDown" nel costruttore e, successivamente, quando crei un'istanza del controllo, vai ad assegnare un nuovo evento perdendo il riferimento al primo impostato nel costruttore.
 
La via corretta è quella di ridefinire il metodo virtuale che viene richiamato quando si preme un tasto, cioè "KeyDown", tramite la clausola *override*:
 
 
  TMyComboBox = class (TComboBox)
  protected
    procedure KeyDown(var Key: Word; Shift: TShiftState); override;
  end;
 
  procedure TMyComboBox.KeyDown(var Key: Word; Shift: TShiftState);
  begin
    inherited;
    if Key = VK_F1 then
    begin
      if Assigned(FOnMyEvent) then
        FOnMyEvent(Sender);
    end;
  end;
 
 
Già che ci sono, ti suggerisco di modificare il nome della classe come sopra, mettendo il prefisso "T" al tipo: è molto di più di una semplice convenzione in Delphi. :)


   end;
 
Grazie funziona, 
 
unica particolarità è questa:
 
   procedure TMyComboBox.KeyDown(var Key: Word; Shift: TShiftState);
   begin
     if Key = VK_F1 then
     begin
       if Assigned(FOnMyEvent) then
         FOnMyEvent(Sender);
     end;
     inherited; //<- Va messo alla fine....
   end;
 
Inherited va messo alla fine, altrimenti prima esegue il codice 
ridefinito a progetto e poi quello sul controllo.....mi sembra strano
ma non saprei il motivo.
 
Grazie mille
 
Ciao
Loris


 ma non saprei il motivo.
 
E' normale che sia così: la parola chiave *inherited* invoca il metodo ereditato dalla classe base, che nel nostro caso è stato "ridefinito", il quale va a generare l'evento e a richiamare il gestore associato.
 
Detto questo, se la parola chiave precede la tua logica, l'evento verrà eseguito prima, altrimenti verrà eseguito dopo.
 
In questo caso, puoi tranquillamente collocare la chiamata al metodo ereditato dove vuoi nel codice, prima o dopo, in base all'ordine in cui desideri vengano gestiti gli eventi.
 
Ciao!


 ridefinito a progetto e poi quello sul controllo.....mi sembra strano
 
xche?
 
 
A.

 xche?
 
Secondo me avrebbe dovuto prima eseguire il codice sul controllo e poi
quello 
ridefinito a progetto, ma MArco ha spiegato molto bene il comportamento
del 
compilatore 


 del compilatore
 
Non è il compilatore, ma il sorgente: se metti l'istruzione A prima
della B, viene eseguita prima la A e poi la B.
 
(e suppongo a tutti noi sembrerebbe strano il contrario :-))
 
Saluti
Paolo Arosio