Recent

Author Topic: How to expose an OnClick event of a compound component  (Read 7637 times)

andrew Bubble

  • Jr. Member
  • **
  • Posts: 57
How to expose an OnClick event of a compound component
« on: May 06, 2017, 10:17:06 am »
Hi All

I have made a compound component called TLedPanel (TCustomPanel) consisting of a TPanel, TShape and a TLabel. The component all works except in one area.

I have exposed the OnClick event of the TLedPanel by placing this in the published section, If I place the new component on the form and double click then the OnClick procedure is shown in lazarus as normal.

The issue is in run time the Oncllick event does not fire, I am assuming as the TLabel on the component is in front the OnClick event of this is actually firing. not the TCustomPanel.

My question is how can I expose the TLabel OnClick event at design time.

Regards Andrew     

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: How to expose an OnClick event of a compound component
« Reply #1 on: May 06, 2017, 10:20:24 am »
No chance to give you a solid answer without having seen your code.

andrew Bubble

  • Jr. Member
  • **
  • Posts: 57
Re: How to expose an OnClick event of a compound component
« Reply #2 on: May 06, 2017, 10:30:59 am »
Hi wp

Unfortunately the code for the component is quite long but basically I have placed the new component's OnClick event as below.

 published
    { Published declarations }
    property OnClick;

This works as expected in design time but when I run the component and click the event does not fire.

Regards Andrew

wp

  • Hero Member
  • *****
  • Posts: 11916
Re: How to expose an OnClick event of a compound component
« Reply #3 on: May 06, 2017, 10:56:42 am »
You must make sure that the event is called. Just calling a procedure an event does not mean that it is called...

Here's an example how I would do it. The OnClick fires when you click on the LED or the label.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.   TLedPanel = class(TPanel)
  12.   private
  13.     FLabel: TLabel;
  14.     FLED: TShape;
  15.     FOnClick: TNotifyEvent;
  16.   protected
  17.     procedure ClickHandler(Sender: TObject);
  18.   public
  19.     constructor Create(AOwner: TComponent); override;
  20.     procedure Toggle;
  21.   published
  22.     property OnClick: TNotifyEvent read FOnClick write FOnClick;
  23.   end;
  24.  
  25.   { TForm1 }
  26.  
  27.   TForm1 = class(TForm)
  28.     procedure FormCreate(Sender: TObject);
  29.   private
  30.     FCounter: Integer;
  31.     FLedPanel: TLedPanel;
  32.     procedure LedPanelClick(Sender: TObject);
  33.  
  34.   public
  35.  
  36.   end;
  37.  
  38. var
  39.   Form1: TForm1;
  40.  
  41. implementation
  42.  
  43. {$R *.lfm}
  44.  
  45. { TForm1 }
  46.  
  47. procedure TForm1.FormCreate(Sender: TObject);
  48. begin
  49.   FLedPanel := TLedPanel.Create(self);
  50.   FLedPanel.OnClick := @LedPanelClick;
  51.   FLedPanel.Parent := self;
  52. end;
  53.  
  54. procedure TForm1.LedPanelClick(Sender: TObject);
  55. begin
  56.   inc(FCounter);
  57.   Caption := 'Click counter ' + IntToStr(FCounter);
  58. end;
  59.  
  60. constructor TLedPanel.Create(AOwner: TComponent);
  61. begin
  62.   inherited;
  63.   FLed := TShape.Create(self);
  64.   FLed.Shape := stCircle;
  65.   FLed.Parent := self;
  66.   FLed.Width := 16;
  67.   FLed.Height := 16;
  68.   FLed.Brush.Color := clRed;
  69.   FLed.OnClick := @ClickHandler;
  70.  
  71.   FLabel := TLabel.Create(self);
  72.   FLabel.Parent := Self;
  73.   FLabel.Left := FLed.Width + 8;
  74.   FLabel.Caption := 'OFF';
  75.   FLabel.OnClick := @ClickHandler;
  76. end;
  77.  
  78. procedure TLedPanel.ClickHandler(Sender: TObject);
  79. begin
  80.   Toggle;
  81.   if Assigned(FOnClick) then FOnClick(self);
  82. end;
  83.  
  84. procedure TLedPanel.Toggle;
  85. begin
  86.   if FLed.Brush.Color = clRed then begin
  87.     FLed.Brush.Color := clGreen;
  88.     FLabel.Caption := 'ON';
  89.   end else begin
  90.     FLed.Brush.Color := clRed;
  91.     FLabel.Caption := 'OFF';
  92.   end;
  93. end;
  94.  
  95. end.
  96.  
« Last Edit: May 06, 2017, 11:00:39 am by wp »

balazsszekely

  • Guest
Re: How to expose an OnClick event of a compound component
« Reply #4 on: May 06, 2017, 10:57:15 am »
Hi Andrew,

If I understood you correctly you need to redirect all OnClick events to a single one. Please try something like this(untested):
Code: Pascal  [Select][+][-]
  1. unit LadPanelUnit;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, ExtCtrls, StdCtrls, Graphics;
  9.  
  10. type
  11.  
  12.   { TLedPanel }
  13.  
  14.   TLedPanel = class(TPanel)
  15.   private
  16.     FLabel: TLabel;
  17.     FShape: TShape;
  18.     FOnLedClick: TNotifyEvent;
  19.     procedure DoOnClick(Sender: TObject);
  20.   public
  21.     constructor Create(TheOwner: TComponent);
  22.     destructor Destroy; override;
  23.   published
  24.     property OnLedClick: TNotifyEvent read FOnLedClick write FOnLedClick;
  25.   end;
  26.  
  27.  
  28. implementation
  29.  
  30. { TLedPanel }
  31.  
  32. procedure TLedPanel.DoOnClick(Sender: TObject);
  33. begin
  34.   if Assigned(FOnLedClick) then
  35.     FOnLedClick(Self);
  36. end;
  37.  
  38. constructor TLedPanel.Create(TheOwner: TComponent);
  39. begin
  40.   inherited Create(nil);
  41.   Self.Width := 300;
  42.   Self.Height := 200;
  43.   Self.OnClick := @DoOnClick;
  44.  
  45.   FLabel := TLabel.Create(nil);
  46.   with FLabel do
  47.   begin
  48.     Parent := Self;
  49.     Left := 50;
  50.     Top := 10;
  51.     Caption := 'Test';
  52.     OnClick := @DoOnClick;
  53.   end;
  54.   FShape := TShape.Create(nil);
  55.   with FShape do
  56.   begin
  57.     Parent := Self;
  58.     Left := 120;
  59.     Top := 55;
  60.     Pen.Color := clBlack;
  61.     Brush.Color := clRed;
  62.     OnClick := @DoOnClick;
  63.   end;
  64. end;
  65.  
  66. destructor TLedPanel.Destroy;
  67. begin
  68.   FLabel.Free;
  69.   FShape.Free;
  70. end;
  71.  
  72. end.
  73.  

andrew Bubble

  • Jr. Member
  • **
  • Posts: 57
Re: How to expose an OnClick event of a compound component
« Reply #5 on: May 06, 2017, 11:12:52 am »
Hi All

Thanks for your help, it was a while ago when I did component development and that was with Delphi 7, I though the issue was the event handler.

I was having issues with the assigning the event handler, I was using Self.OnClick := DoOnClick; for example and was getting errors, did not realise the @ before the procedure call.

Anyway it is working so thanks fro all your help.

GetMem you are right by the way the Lazarus IDE is very good.

Regards Andrew

Thaddy

  • Hero Member
  • *****
  • Posts: 14369
  • Sensorship about opinions does not belong here.
Re: How to expose an OnClick event of a compound component
« Reply #6 on: May 06, 2017, 12:36:36 pm »
PPlz note that if your unit was in mode delphi instead of mode objfpc it would have worked without the @.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

andrew Bubble

  • Jr. Member
  • **
  • Posts: 57
Re: How to expose an OnClick event of a compound component
« Reply #7 on: May 06, 2017, 12:42:31 pm »
Hi Thaddy

Thanks I was not aware of that, seems there is a lot of difference between Delphi and Lazarus but I expect the underlying principles are the same.

Regards Andrew

andrew Bubble

  • Jr. Member
  • **
  • Posts: 57
Re: How to expose an OnClick event of a compound component
« Reply #8 on: May 06, 2017, 01:28:29 pm »
Hi All

The new component is now behaving as I hoped, I do have one more question and this concerns the Label TCaption property.

If I place a TLabel on a form the Tcaption shows a StringEditor Dialog box when clicked so you can enter multiple strings if so wish.

I have added a MainText : Tcaption property but this only allows the entry of a single line, how do I invoke the TSTringEditor dialoge.

Regards Andrew



wp

  • Hero Member
  • *****
  • Posts: 11916
Re: How to expose an OnClick event of a compound component
« Reply #9 on: May 06, 2017, 02:15:18 pm »
You must register the correct property editor for multiline strings for the type TCaption of the component, look at propedits.pp in folder components/ideintf of your Lazarus installation and scroll down to InitPropEdits for examples:

Code: Pascal  [Select][+][-]
  1. procedure Register;
  2. begin
  3.   RegisterComponents('MyComponents', [TLedPanel]);
  4.   RegisterPropertyEditor(TypeInfo(TCaption), TLedPanel, 'Caption', TStringMultilinePropertyEditor);
  5. end;


 

TinyPortal © 2005-2018