Recent

Author Topic: toolbar example (my code isn't working)  (Read 4822 times)

speter

  • Sr. Member
  • ****
  • Posts: 338
toolbar example (my code isn't working)
« on: January 23, 2022, 02:18:05 am »
G'Day Folks,

In the thread "Adding buttons to TToolBar from runtime" (https://forum.lazarus.freepascal.org/index.php/topic,57957.0.html) there was a Ttoolbar example (https://lazarus-ccr.sourceforge.io/docs/lcl/comctrls/ttoolbar.buttons.html). In looking at the example I thought that it would be more interesting / useful if it included an onClick event handler.

I wrote some code to attempt to implement this but an getting an error. In part, my code is:
Code: Pascal  [Select][+][-]
  1. type
  2.   Tproc = procedure (sender: tobject);
  3.   TMyRec = record
  4.     cap : string;
  5.     clk : Tproc;
  6.   end;
  7.   TMyArray = array of TMyRec;
  8.  
  9.   { TForm1 }
  10.  
  11.   TForm1 = class(TForm)
  12.     Button1: TButton;
  13.     Memo1: TMemo;
  14.     Panel1: TPanel;
  15.     ToolBar1: TToolBar;
  16.     procedure Button1Click(Sender: TObject);
  17.   private
  18.  
  19.   public
  20.     procedure NewClick(Sender: TObject);
  21.     procedure SaveClick(Sender: TObject);
  22.     procedure CutClick(Sender: TObject);
  23.     procedure CopyClick(Sender: TObject);
  24.     procedure PasteClick(Sender: TObject);
  25.   end;
  26.  
  27. var
  28.   Form1: TForm1;
  29.  
  30. implementation
  31.  
  32. {$R *.lfm}
  33.  
  34. { TForm1 }
  35.  
  36. procedure TForm1.Button1Click(Sender: TObject);
  37. var
  38.   tools : TMyArray = ( (cap:'New'; clk:@NewClick),
  39.                        (cap:'Save';clk:@SaveClick) );
  40. //                                     ^^^^^^^^ does NOT work

I am getting an error message referring to lines 38 & 39 above. The emphasis "of object" is mine. :o

Quote
Error: Incompatible types: got "<procedure variable type of procedure(TObject) of object;Register>" expected "<procedure variable type of procedure(TObject);Register>"

So, I think (maybe) my code is close to correct, but clearly isn't quite right!

I am attaching the lazarus project to this message.

Any suggestions would be welcomed. :)

cheers
S.
I climbed mighty mountains, and saw that they were actually tiny foothills. :)

bytebites

  • Hero Member
  • *****
  • Posts: 624
Re: toolbar example (my code isn't working)
« Reply #1 on: January 23, 2022, 10:10:42 am »
Type of the NewClick is procedure (sender: tobject) of object;
After changing the type of Tproc
Code: Pascal  [Select][+][-]
  1. Tproc = procedure (sender: tobject) of object;
error message is
Quote
Error: Typed constants of the type "procedure of object" can only be initialized with NIL

speter

  • Sr. Member
  • ****
  • Posts: 338
Re: toolbar example (my code isn't working)
« Reply #2 on: January 23, 2022, 11:48:19 am »
Thanks very much @bytebites!

Here is where the code is at presently (it works):
Code: Pascal  [Select][+][-]
  1. type
  2.   Tproc = procedure (sender: tobject) of object;
  3. ...
  4. procedure TForm1.Button1Click(Sender: TObject);
  5.  
  6.   procedure FillToolbar (ToolBar: TToolBar;
  7.                          const caps : array of string;
  8.                          const events : array of Tproc);
  9.   // based on https://lazarus-ccr.sourceforge.io/docs/lcl/comctrls/ttoolbar.buttons.html
  10.   var
  11.     i: integer;
  12.   begin
  13.     for i := 0 to High(caps) do
  14.     begin
  15.       with TToolButton.Create(ToolBar) do
  16.       begin
  17.         Parent := ToolBar;
  18.         Caption := caps[i];
  19.         if (caps[i] = '|') then
  20.           Style := tbsSeparator
  21.         else
  22.           begin
  23.             Style := tbsButton;
  24.             onclick := events[i];
  25.           end;
  26.         AutoSize := True;
  27.         left := parent.width;
  28.       end;
  29.     end;
  30.   end;
  31.  
  32. begin
  33.   FillToolbar(ToolBar1, ['New', 'Save', '|', 'Cut', 'Copy', 'Paste'],
  34.               [@NewClick,@SaveClick,nil,@CutClick,@CopyClick,@PasteClick] );
  35. end;
  36.  
  37. ...

This is OK; but I'd like to use (something like) the record in my first post.

cheers
S. :)
I climbed mighty mountains, and saw that they were actually tiny foothills. :)

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: toolbar example (my code isn't working)
« Reply #3 on: January 23, 2022, 11:56:52 am »
There's no need to declare a new type TProc for "procedure (Sender: TObject) of object" since this is a TNotifyEvent used all over the LCL.

speter

  • Sr. Member
  • ****
  • Posts: 338
Re: toolbar example (my code isn't working)
« Reply #4 on: January 24, 2022, 12:24:53 am »
Thanks WP and Jamie.

Jamie: could you post a simple project (using Add/Insert) that implements the idea shown in my second post!?
I couldn't see out how to add an event handler.

cheers
S.
I climbed mighty mountains, and saw that they were actually tiny foothills. :)

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: toolbar example (my code isn't working)
« Reply #5 on: January 24, 2022, 12:48:30 am »
My point is "It should be that way but isn't"

The buttons array exists but only serves as a reading property and inserting new buttons does not seem to assign it to Toolbar as parent so it's a bust!
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: toolbar example (my code isn't working)
« Reply #6 on: January 24, 2022, 01:19:51 am »
I think maybe you should be using a single event.

Point them all to the same event and when in that event you can identify them by checking the TAG variable for example which could be the numerical position of where they live in the array.

 When you add the button to the tool bar set the TAG property of each button to that of the array position so you can identify the correct button while on the TNotifiyEvent handler.

 I can maybe bang out some code to show you if needed.
The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: toolbar example (my code isn't working)
« Reply #7 on: January 24, 2022, 01:48:45 am »
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs,StdCtrls, ExtCtrls, ComCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     ToolBar1: TToolBar;
  17.     procedure Button1Click(Sender: TObject);
  18.   private
  19.  
  20.   public
  21.     procedure DoBUttons(Sender:Tobject);
  22.   end;
  23.  
  24. var
  25.   Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. {$R *.lfm}
  30.  
  31. { TForm1 }
  32. Procedure TForm1.DoButtons(Sender:TObject);
  33. Begin
  34.    Case TtoolButton(Sender).Tag Of
  35.     0:Caption := 'Copy'; //{Do Copy};
  36.     1:Caption := 'Paste';//{Do Paste};
  37.    end;
  38. end;
  39.  
  40. Procedure AddMeToButtons(AToolbar:TToolBar; AClickEvent:TNotifyEvent; AButtons:Array of String);
  41. Var
  42.   I :Integer;
  43. Begin
  44.      for i := 0 to High(AButtons) do
  45.     begin
  46.       with TToolButton.Create(AToolBar) do
  47.       begin
  48.         Parent := AToolBar;
  49.         Caption := AButtons[i];
  50.         if (Abuttons[i] = '|') then
  51.           Style := tbsSeparator
  52.         else
  53.           begin
  54.             Style := tbsButton;
  55.             onclick := AClickEvent;
  56.           end;
  57.         AutoSize := True;
  58.         Visible := true;
  59.         left := parent.width;
  60.         Tag := I;// Array Index;
  61.       end;
  62.     end;
  63. end;
  64.  
  65. procedure TForm1.Button1Click(Sender: TObject);
  66. begin
  67.    AddMeToButtons(ToolBar1, @doButtons,['Copy','Paste']);
  68. end;
  69.  
  70. end.
  71.  
  72.  
  73.  

have a look at that.
The only true wisdom is knowing you know nothing

CM630

  • Hero Member
  • *****
  • Posts: 1076
  • Не съм сигурен, че те разбирам.
    • http://sourceforge.net/u/cm630/profile/
Re: toolbar example (my code isn't working)
« Reply #8 on: January 26, 2022, 09:19:25 am »
As @Jamie pointed out - you should better use the tag property.
And the reason is that looking in your code:

Code: Pascal  [Select][+][-]
  1.  
  2.  FillToolbar(ToolBar1, ['New', 'Save', '|', 'Cut', 'Copy', 'Paste'],
  3.               [@NewClick,@SaveClick,nil,@CutClick,@CopyClick,@PasteClick] );
You are creating the buttons during runtime, but you have created the procedures NewClick, SaveClick before that (during design time).
Then maybe there is not much reason for not creating the buttons during design time, too.

For example, if you want to make a calculator, you will just

   
Code: Pascal  [Select][+][-]
  1. AddMeToButtons(ToolBar1, @doButtons,['Copy','Paste']);

and then

Code: Pascal  [Select][+][-]
  1. Procedure TForm1.DoButtons(Sender:TObject);
  2.  
  3. ...
  4.    Text1.Text := Text1.Text + ToolBar.Butons[TtoolButton(Sender).Tag].Caption;
  5. ...
  6. end;
Лазар 3,0 32 bit (sometimes 64 bit); FPC3,2,2; rev: Lazarus_3_0 on Win10 64bit.

speter

  • Sr. Member
  • ****
  • Posts: 338
Re: toolbar example (my code isn't working)
« Reply #9 on: January 26, 2022, 11:56:31 pm »
Thanks for that.

I am not sure why the wiki example adds buttons at runtime; of hand, I can't think of any good use for this.
My intention was to try to improve the example, but I don't think it is worth worrying about.

cheers
S.
I climbed mighty mountains, and saw that they were actually tiny foothills. :)

 

TinyPortal © 2005-2018