Newsgroup: it.comp.lang.delphi
Titolo: esporre gli eventi di un componente figlio ... how to

enuncio i fatti :
ho un componente che espone come proprietà un componente per la gestione
della porta seriale
vorrei poter esporre anche l' evento OnRecive del componente porta seriale
quando il componente porta seriale seriale riceve (viene innescato l'evento
OnRecive)
vorrei innescare l'evento OnRecive_PortaSeriale
ogni spunto è ben accetto
Grazie in anticipo
Cordialmente,
Stefano
=============================================
unit ADSWStrumentoSeriale;
interface
uses
  Windows, SysUtils, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, ExtCtrls, ADSWDefine, ADSWComm, ADSWeverLiquidIndicator;
type
   TADSWStrumentoSeriale = class(TADSWeverLiquidIndicator)
   private
    FPortaSeriale: TADSWComm;
    FReadBufferFull: TReadBufferFull;
    FReadBufferThreshold: TReadBufferThreshold;
    FReceive: TReceive;
    FReceiveEventChar: TReceiveEventChar;
   protected
       procedure SetPortaSeriale(const Value: TADSWComm);
       procedure ProcessOnRecive_PortaSeriale;
   public
      constructor Create (AOwner : TComponent);override;
      destructor Destroy;override;
      procedure Loaded;override;
      function GetChildOwner : TComponent;override;
      function GetChildParent : TComponent;override;
      procedure GetChildren(Proc: TGetChildProc; Root: TComponent);override;
   published
      property PortaSeriale : TADSWComm read FPortaSeriale write
SetPortaSeriale;
      property OnReceive_PortaSeriale : TReceive read FReceive write
FReceive;
   end;
implementation
{ TADSWStrumentoSeriale }
constructor TADSWStrumentoSeriale.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);
   if not (csLoading in AOwner.ComponentState) then begin
      FPortaSeriale := TADSWComm.Create(Self);
      FPortaSeriale.OnReceive := ProcessOnRecive_PortaSeriale;
   end;
end;
{---------------------------------------------------------------------------
---}
destructor TADSWStrumentoSeriale.Destroy;
begin
  FPortaSeriale.Free;
  inherited Destroy;
end;
{---------------------------------------------------------------------------
---}
function TADSWStrumentoSeriale.GetChildOwner: TComponent;
begin
   Result := Self;
end;
{---------------------------------------------------------------------------
---}
function TADSWStrumentoSeriale.GetChildParent: TComponent;
begin
   Result := Self;
end;
{---------------------------------------------------------------------------
---}
procedure TADSWStrumentoSeriale.GetChildren(Proc: TGetChildProc;
  Root: TComponent);
begin
  inherited;
  Proc(PortaSeriale);
end;
{---------------------------------------------------------------------------
---}
procedure TADSWStrumentoSeriale.Loaded;
var
   i : integer;
begin
  inherited;
  FPortaSeriale := TADSWComm(Components[0]);
end;
{---------------------------------------------------------------------------
---}
procedure TADSWStrumentoSeriale.ProcessOnRecive_PortaSeriale
begin
   if Assigned(FReceive) then begin
      FReceive(Sender, Buffer, Count);
   end;
end;
{---------------------------------------------------------------------------
---}
procedure TADSWStrumentoSeriale.SetPortaSeriale(const Value: TADSWComm);
begin
  FPortaSeriale.Assign(Value);
end;
initialization
   RegisterClass(TADSWComm);
end.
=======================================
unit ADSWComm;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, ADSWDefine;
type
  TADSWComm = class(TADSWComponent)
   private
    { Private declarations }
    hCommFile            : THandle;
    FReceive             : TReceive;
    FReceiveEventChar    : TReceiveEventChar;
    FReadBufferFull      : TReadBufferFull;
    FReadBufferThreshold : TReadBufferThreshold;
    FPort                : TPort;
    FBaudRate        : TBaudRate;
    FParity              : TParity;
    FStopBits          : TStopBits;
    FDataBits          : TDataBits;
    FThreshold           : Word;
    FRxInterval          : integer;
    FEventChar           : Byte;
    Error                : boolean;
    Timer                : TTimer;
    gClose : boolean;
    ThresholdExceed : boolean;
    sBuffer : array[0..BUFF_TMP_SIZE-1] of char;
    sRead : array [0..BUFF_SIZE-1] of char;
    nRead : integer;
    procedure SetThreshold (Value: Word);
    procedure SetPort (Value: TPort);
    procedure SetDataBits (Value: TDataBits);
    procedure SetStopBits (Value: TStopBits);
    procedure SetParity (Value: TParity);
    procedure SetBaudRate (Value: TBaudRate);
    procedure SetRxInterval (Value : integer);
    function GetInCount: LongInt;
    function CharIn (szInputBuffer: PChar; Start: integer;
                             nNumberOfBytesRead: integer; Ch:Char): boolean;
    procedure TimerEvent (Sender: TObject);
  protected
    { Protected declarations }
    procedure DoReceive;
    procedure DoReceiveEventChar;
    procedure DoReadBufferFull;
    procedure DoReadBufferThreshold;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Assign(Source : TPersistent);override;
    function StartComm(P:TPort): Boolean;
    procedure StopComm;
    function Write( Data: PChar; Len: Word ): Boolean;
    function IsError: Boolean;
    procedure Flush;
  published
    { Published declarations }
    property EventChar: Byte read FEventChar write FEventChar
      default DEF_EVENTCHAR;
    property Threshold: word read FThreshold write SetThreshold
      default DEF_THRESHOLD;
    property BaudRate: TBaudRate read FBaudRate write SetBaudRate
      default DEF_BAUDRATE;
    property Parity: TParity read FParity write SetParity
      default DEF_PARITY;
    property StopBits: TStopBits read FStopBits write SetStopBits
      default DEF_STOPBITS;
    property DataBits: TDataBits read FDataBits write SetDataBits
      default DEF_DATABITS;
    property Port: TPort read FPort write FPort;
    property RxInterval: integer read FRxInterval write FRxInterval;
    property OnReceive       : TReceive read FReceive write FReceive;
    property OnReceiveEventChar : TReceiveEventChar read FReceiveEventChar
write FReceiveEventChar;
    property OnReadBufferFull: TReadBufferFull read FReadBufferFull write
FReadBufferFull;
    property OnReadBufferThreshold: TReadBufferThreshold read
FReadBufferThreshold write FReadBufferThreshold;
  end;
implementation
{---------------------------------------------------------------------------
---}
constructor TADSWComm.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  hCommFile := 0;
  gClose := TRUE;
  FEventChar       := DEF_EVENTCHAR;
  FThreshold       := DEF_THRESHOLD;
  FBaudRate        := DEF_BAUDRATE;
  FDataBits        := DEF_DATABITS;
  FStopBits        := DEF_STOPBITS;
  FParity          := DEF_PARITY;
  FPort            := DEF_PORT;
  FRxInterval      := DEF_RXINTERVAL;
  Error := FALSE;
  Timer := TTimer.Create(Self);
  Timer.Enabled := FALSE;
  Timer.Interval := FRxInterval;
  Timer.OnTimer := TimerEvent;
  nRead := 0;
  ThresholdExceed := FALSE;
  StrCopy (sBuffer,'');
  StrCopy (sRead,'');
end;
{---------------------------------------------------------------------------
---}
procedure TADSWComm.DoReceive;
var B : LPSTR;
begin
  B := sRead;
  if Assigned(FReceive) then begin
    FReceive (Self,B,nRead);
    nRead := 0;
    ThresholdExceed := FALSE;
    StrCopy (sBuffer,'');
    StrCopy (sRead,'');
  end;
end;
{---------------------------------------------------------------------------
---}
procedure TADSWComm.Assign(Source: TPersistent);
begin
   if Source is TADSWComm then begin
      Self.Port := TADSWComm(Source).Port;
      Self.RxInterval := TADSWComm(Source).RxInterval;
      Self.BaudRate := TADSWComm(Source).BaudRate;
      Self.Parity := TADSWComm(Source).Parity;
      Self.StopBits := TADSWComm(Source).StopBits;
      Self.EventChar := TADSWComm(Source).EventChar;
      Self.DataBits := TADSWComm(Source).DataBits;
      Self.Threshold := TADSWComm(Source).Threshold;
      //
      // Self.OnReceive := TADSWComm(Source).FReceive;
      //
   end
   else begin
      // raise an exception
   end;
end;
{---------------------------------------------------------------------------
---}
procedure TADSWComm.TimerEvent (Sender: TObject);
var Len,NCharRead : DWord;
    bReceive                : boolean;
    bReceiveEventChar       : boolean;
    bReadBufferThreshold    : boolean;
    bReadBufferFull         : boolean;
begin
  Timer.Enabled := FALSE;
  Len := GetInCount;
  while Len > 0 do begin
    { Azzero i flag degli eventi }
     bReceive                := FALSE;
    if Len > BUFF_TMP_SIZE-1 then
      Len := BUFF_TMP_SIZE-1;
    ReadFile( hCommFile,
              sBuffer, Len,
              NCharRead,nil);
    {--------- OnReceive ----------}
    bReceive := TRUE;
    sBuffer[NCharRead] := #0;
    strCat (sRead,sBuffer);
    Inc(nRead,NCharRead);
    if bReceive then
      DoReceive;
    Len := GetInCount;
    if Len > 0 then
      Application.ProcessMessages;
  end;
  Timer.Enabled := TRUE;
end;
{---------------------------------------------------------------------------
---}
end.

ogni spunto č ben accetto


 spero di essere stato chiaro :)
probabilmente sono io che continuo a non capire
Stefano

> spero di essere stato chiaro :)
sicuramente non sono stato chiaro non esprimendo correttamente
ciň che vorrei realizzare
TADSWComm č un componente che gestisce la porta seriale
preso a se stante TADSWComm funziona egregiamente :
TADSW ogni x millisecondi controlla se č stato ricevuto qualcosa
in caso abbia  ricevuto qualcosa innesca l'evento OnRecive
procedure TADSWComm.DoReceive;
var B : LPSTR;
begin
  B := sRead;
  if Assigned(FReceive) then begin
    FReceive (Self,B,nRead);
    nRead := 0;
    ThresholdExceed := FALSE;
    StrCopy (sBuffer,'');
    StrCopy (sRead,'');
  end;
end;
TADSWComm = class(TADSWComponent)
  private
    FReceive          : TReceive;
    Timer                : TTimer;
  protected
    { Protected declarations }
    procedure DoReceive;
  public
    property OnReceive       : TReceive read FReceive write FReceive;
end;
ora ho inserito TADSWComm
all'interno di TADSWStrumentoSeriale
TADSWStrumentoSeriale = class(TADSWeverLiquidIndicator)
   private
      FRecivePortaSeriale : TRecive
      FPortaSeriale: TADSWComm
   protected
       (* per migliore comprensione sarebbe stato meglio chiamarla
DoRecive_PortaSeriale *)
       procedure ProcessOnRecive_PortaSeriale;
  public
  published
      property PortaSeriale : TADSWComm read FPortaSeriale write
SetPortaSeriale;
      property OnReceive_PortaSeriale : TReceive read FReceivePortaSeriale
write FReceivePortaSeriale;
 end;
quello che non riesco a fare č far comunicare TADSWComm con
TADSWStrumentoSeriale
TADSWComm  dovrebbe notificare a TADSWStrumentoSeriale che qualcosa č stato
ricevuto
Cordialmente,
Stefano

 end
qui è dove TADSWComm.OnRecive mi notifica ?!?!
Stefano
P.S. : forse ora è meglio se dormo

 ricevuto
cosě a occhio mi sembra che dovresti scrivere
TADSWStrumentoSeriale = class(TADSWeverLiquidIndicator)
   private
      FRecivePortaSeriale : TRecive
      FPortaSeriale: TADSWComm
      procedure PortaSerialeReceiveEvent ...
//con lo stesso numero e tipo di parametri di TReceive
   public 
      constructor Create ... override(?) 
e nel costruttore scrivere
  FPortaSeriale.OnReceive:= PortaSerialeReceiveEvent   
-- 
Mauro Falzari 
   [ 
http://digilander.libero.it/mauro.falzari
 ]
 
 "Se guardi nell'abisso, anche l'abisso guarda in te." 
   (Friedrich Nietzsche)

   FPortaSeriale.OnReceive:= PortaSerialeReceiveEvent
come suggerito anche da Luca avevo già fatto così
facendo debug trovo questo
ADSWStrumentoSeriale.PortaSeriale.FRecive = nil
e non capisco perchè dal momento che nel costruttore del componente
padre faccio
FPortaSeriale.OnReceive:= PortaSerialeReceiveEvent
dopo questa assegnazione
ADSWStrumentoSeriale.PortaSeriale.FRecive dovrebbe avere un valore $XXXX
ed invece è sempre nil
Cordialmente,
Stefano

 ed invece č sempre nil
questo č vero utilizzando il componente a design-time
ho creato una unit di test dove creo il mio componente a runt-time
e in questo caso funziona tutto perfettamente : funzionano correttamente
sia le proprietŕ che gli eventi
a fronte di questo deduco che il problema stia
nello stream dell'/degli evento/i (nel progetto di prova in cui creo il
componente a desig-time le proprietŕ funzionano mentre l'evento mi
restituisce nil ... e da qui il motivo di questo thread)
Cordialmente,
Stefano

 restituisce nil ... e da qui il motivo di questo thread)
risolto ! :-)
date le modalità con cui delphi effettua lo stream
ho risolto aggiungendo l' assegnazione
FPortaSeriale.OnReceive := ProcessOnRecive_PortaSeriale;
nel Loaded
procedure TADSWStrumentoSeriale.Loaded;
var
   i : integer;
begin
  inherited;
  FPortaSeriale := TADSWComm(Components[0]);
  FPortaSeriale.OnReceive := ProcessOnRecive_PortaSeriale;
end;
in questo modo funziona tutto
resta il fatto che non so quanto sia tecnicamente valida come
soluzione
Cordialmente,
Stefano
P.S. : Grazie Luca, Mauro per l'assistenza

 soluzione
giusto, mi ero sbagliato io perchè non avevo tenuto conto che stiamo parlando 
di derivati da TComponent e che l'evento OnReceive è una proprietà published, 
quindi impostarla nel Create non ha senso perchè poi viene sovrascritta dal 
meccanismo di streaming con il valore presente nell'Object Inspector.
La soluzione del Loaded è tecnicamente valida e la migliore.


 La soluzione del Loaded č tecnicamente valida e la migliore.
Grazie ancora Mauro
avevo letto che un ottimo testo che approfondisce i dietro le quinte
(streaming compreso)
di delphi č "Delphi Component Design" di Danny Thorpe
Sei a conoscenza che qualcuno venda una copia usata ?
Ne ho trovati un paio su Ebay ma prima di avventurarmi
preferirei tentare di trovarlo da qualcuno qui Italia
Cordialmente,
Stefano

 Sei a conoscenza che qualcuno venda una copia usata ?
no, mi dispiace.
Ciao
