Forum > General

[Resolved] TNotifyEvent handler assignment not working as expected

(1/1)

Nimral:
What is the thing I am missing in the following sample code:

I do assign DoUpdate := doDisplayValue in FormCreate. Later, when I try to call doDisplayValue, the code in Timer1.Timer does never call doDisplayValue, since assigned(doUpdate) returns false. Seems the assignment does not work, but why?



--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls; type   { TValueDisplay }   TValueDisplay = class  private    FDisplayLabel: TLabel;  public    property DisplayLabel: TLabel read FDisplayLabel;  var    DoUpdate: TNotifyEvent;                           // called if the value should be updated    constructor Create(aDisplayLabel: TLabel);        // Bind this display to a certain Label  end;   TValueDisplays = array of TValueDisplay;            // the list of all value displays   { TForm1 }   TForm1 = class(TForm)    Label1: TLabel;    Label2: TLabel;    Timer1: TTimer;    procedure FormCreate(Sender: TObject);            // Create the form and register a bunch of displays    procedure Timer1Timer(Sender: TObject);           // a timer changing a value every 1 second and triggering the update of all registered displays  private    FdoDisplayValue: TNotifyEvent;    FTicks: word;    FValueDisplays: TValueDisplays;    procedure SetdoDisplayValue(AValue: TNotifyEvent);  public    function AddValueDisplay(aDisplay: TValueDisplay): TValueDisplay;     // register a display    property ValueDisplays: TValueDisplays read FValueDisplays;           // the list of registered displays    property doDisplayValue: TNotifyEvent read FdoDisplayValue write SetdoDisplayValue;  // updates the display passed in the sender parameter of TNotifyEvent    property Ticks: word read FTicks;  // just a changing value  end; var  Form1: TForm1; implementation {$R *.lfm} { TValueDisplay } constructor TValueDisplay.Create(aDisplayLabel: TLabel);begin  FDisplayLabel := aDisplayLabel;  FDisplayLabel.Caption := '##';end; { TForm1 } procedure TForm1.Timer1Timer(Sender: TObject); var  d: TValueDisplay; begin  Inc(FTicks);  for d in ValueDisplays do    if assigned(d.DoUpdate) then         // if d.DoUpdate <> NIL then      d.DoUpdate(d.DisplayLabel);end; procedure TForm1.SetdoDisplayValue(AValue: TNotifyEvent);begin  if FdoDisplayValue = AValue then Exit;  FdoDisplayValue := AValue;end; function TForm1.AddValueDisplay(aDisplay: TValueDisplay): TValueDisplay;begin  SetLength(FValueDisplays, length(FValueDisplays) + 1);  FValueDisplays[length(FValueDisplays) - 1] := aDisplay;  Result := FValueDisplays[length(FValueDisplays) - 1];end; procedure TForm1.FormCreate(Sender: TObject); begin  with AddValueDisplay(TValueDisplay.Create(Self.Label1)) do    DoUpdate := doDisplayValue;  with AddValueDisplay(TValueDisplay.Create(Self.Label2)) do    DoUpdate := doDisplayValue;end; end. 

Nimral:
Sorry I have wasted your time, I found the problem. Unfortunately I do not have enough forum permissions to delete the question. DoDisplayValue, which should have been a procedure, was declared as a property, and thus initialized NIL. The assignment worked, but DoDisplayValue was never assigned a value.

This works:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls; type   { TValueDisplay }   TValueDisplay = class  private    FDisplayLabel: TLabel;  public    property DisplayLabel: TLabel read FDisplayLabel;  var    DoUpdate: TNotifyEvent;                           // called if the value should be updated    constructor Create(aDisplayLabel: TLabel);        // Bind this display to a certain Label  end;   TValueDisplays = array of TValueDisplay;            // the list of all value displays   { TForm1 }   TForm1 = class(TForm)    Label1: TLabel;    Label2: TLabel;    Timer1: TTimer;    procedure FormCreate(Sender: TObject);            // Create the form and register a bunch of displays    procedure Timer1Timer(Sender: TObject);           // a timer changing a value every 1 second and triggering the update of all registered displays  private    FTicks: word;    FValueDisplays: TValueDisplays;  public    function AddValueDisplay(aDisplay: TValueDisplay): TValueDisplay;     // register a display    property ValueDisplays: TValueDisplays read FValueDisplays;           // the list of registered displays    procedure doDisplayValue(Sender:TObject);  // updates the display passed in the sender parameter of TNotifyEvent    property Ticks: word read FTicks;  // just a changing value  end; var  Form1: TForm1; implementation {$R *.lfm} { TValueDisplay } constructor TValueDisplay.Create(aDisplayLabel: TLabel);begin  FDisplayLabel := aDisplayLabel;  FDisplayLabel.Caption := '##';end; { TForm1 } procedure TForm1.Timer1Timer(Sender: TObject); var  d: TValueDisplay; begin  Inc(FTicks);  for d in ValueDisplays do    if assigned(d.DoUpdate) then         // if d.DoUpdate <> NIL then      d.DoUpdate(d.DisplayLabel);end; function TForm1.AddValueDisplay(aDisplay: TValueDisplay): TValueDisplay;begin  // aDisplay.DoUpdate := doDisplayValue;  SetLength(FValueDisplays, length(FValueDisplays) + 1);  FValueDisplays[length(FValueDisplays) - 1] := aDisplay;  // FValueDisplays[length(FValueDisplays) - 1].DoUpdate := doDisplayValue;  Result := FValueDisplays[length(FValueDisplays) - 1];end; procedure TForm1.doDisplayValue(Sender: TObject); begin   With TLabel(Sender) do     Caption := Format('%d',[Ticks]);end; procedure TForm1.FormCreate(Sender: TObject); begin  with AddValueDisplay(TValueDisplay.Create(Self.Label1)) do    DoUpdate := @doDisplayValue;  with AddValueDisplay(TValueDisplay.Create(Self.Label2)) do    DoUpdate := @doDisplayValue;end; end. 

Navigation

[0] Message Index

Go to full version