Recent

Author Topic: Custom Component Width and Height  (Read 822 times)

Aruna

  • Sr. Member
  • ****
  • Posts: 494
Custom Component Width and Height
« on: August 31, 2024, 12:57:29 pm »
Hi, I have a custom control that functions as intended. However, when I first click on it in the component panel and then click on the form to place an instance, it initially appears as a small black box (it looks like a dot, but Iā€™m not sure how else to describe it). You can see this issue in the first attached screenshot..

I have explicitly set height and width in the code:

Code: Pascal  [Select][+][-]
  1.  FMemo.Width  :=600;  
  2.  FMemo.Height :=180;
Once I manually drag the bottom-right corner of the component to resize it, I can adjust the width and height to my liking, and everything works as expected. You can see this in the second attached screenshot.

My question is: How can I ensure that Lazarus uses the width and height specified in my code for the control? For some reason, it t seems like Lazarus either doesn't pick up these dimensions or ignores them.

Here is the source:
Code: Pascal  [Select][+][-]
  1. unit Tlsusb;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Controls, StdCtrls, Process;
  9.  
  10. type
  11.   { TLSB }
  12.   TLSB = class(TCustomControl)
  13.   private
  14.     FMemo: TMemo;
  15.     procedure DoRunCommand;
  16.   protected
  17.     procedure CreateWnd; override;
  18.   public
  19.     constructor Create(AOwner: TComponent); override;
  20.   published
  21.     property Align;
  22.     property Anchors;
  23.     property Font;
  24.     property ParentFont;
  25.     property ParentShowHint;
  26.     property ShowHint;
  27.     property TabOrder;
  28.     property TabStop;
  29.     property Visible;
  30.   end;
  31.  
  32. procedure Register;
  33.  
  34. implementation
  35.  
  36. constructor TLSB.Create(AOwner: TComponent);
  37. begin
  38.   inherited Create(AOwner);
  39.  
  40.   // Initialize the memo
  41.   FMemo        := TMemo.Create(Self);
  42.   FMemo.Parent := Self;
  43.   FMemo.Align  := alClient;
  44. //  FMemo.Width  :=600;
  45. //  FMemo.Height :=180;
  46.   FMemo.Font.Name:= 'Monospace';
  47.   //FMemo.ScrollBars := ssVertical;
  48.   // Run the command
  49.   DoRunCommand;
  50. end;
  51.  
  52. procedure TLSB.CreateWnd;
  53. begin
  54.   inherited CreateWnd;
  55.   // Additional initialization if necessary
  56. end;
  57.  
  58. procedure TLSB.DoRunCommand;
  59. var
  60.   outstr: string;
  61. begin
  62.   RunCommand('lsusb', [''], outstr);
  63.   FMemo.Lines.Add(outstr);
  64. end;
  65.  
  66. procedure Register;
  67. begin
  68.   RegisterComponents('Linux Sysinfo', [TLSB]);
  69. end;
  70.  
  71. end.
  72.  

Second question is if I change the FMemo.Align  := alClient; to alNone things do not work.
Code: Pascal  [Select][+][-]
  1.  FMemo.Align  := alClient;

Why is this? And how do I fix?

EDIT: Oh btw, is how I have gone about doing this ok? Or there are more elegant ways to do this? If so please do share. Thank you!
« Last Edit: August 31, 2024, 01:07:32 pm by Aruna »

bobby100

  • Sr. Member
  • ****
  • Posts: 260
    • Malzilla
Re: Custom Component Width and Height
« Reply #1 on: August 31, 2024, 01:14:29 pm »
Try to put this into Create method:
Code: Pascal  [Select][+][-]
  1. with GetControlClassDefaultSize do
  2.     SetInitialBounds(0, 0, 50, 50);

wp

  • Hero Member
  • *****
  • Posts: 12409
Re: Custom Component Width and Height
« Reply #2 on: August 31, 2024, 01:19:10 pm »
However, when I first click on it in the component panel and then click on the form to place an instance, it initially appears as a small black box (it looks like a dot, but Iā€™m not sure how else to describe it).
This happens when the component has zero size. You did not specify its Width and Height in the constructor (only those of the FMemo, but this is not relevant for the component. The recommended way how to specify component size in its constructor is by calling the function GetControlClassDefaultSize and passing its return value to SetInitialBounds. Compared to setting Width and Height directly, this avoids a lot of overhead which is unnecessary at this early stage of component creation.
Code: Pascal  [Select][+][-]
  1. procedure TLSB.Create(AOwner: TComponent);
  2. begin
  3.   inherited Create(AOwner);
  4.   with GetControlClassDefaultSize do
  5.     SetInitialBounds(0, 0, CX, CY);
  6. end;
  7.  
  8. class function TLSB.GetControlClassdefaultSize: TSize;  // must be declared in protected and as "override"
  9. begin
  10.   Result.CX := 100;     // This is the initial size of the component TLSB. Please adapt as needed.
  11.   Result.CY := 100;
  12. end;

Having set the control's size should fix also the issue with FMemo.Align.
« Last Edit: August 31, 2024, 01:20:42 pm by wp »

Aruna

  • Sr. Member
  • ****
  • Posts: 494
Re: Custom Component Width and Height
« Reply #3 on: August 31, 2024, 02:45:26 pm »
Try to put this into Create method:
Code: Pascal  [Select][+][-]
  1. with GetControlClassDefaultSize do
  2.     SetInitialBounds(0, 0, 50, 50);
Perfect! Thank you.

Aruna

  • Sr. Member
  • ****
  • Posts: 494
Re: Custom Component Width and Height
« Reply #4 on: August 31, 2024, 02:51:08 pm »
However, when I first click on it in the component panel and then click on the form to place an instance, it initially appears as a small black box (it looks like a dot, but Iā€™m not sure how else to describe it).
This happens when the component has zero size. You did not specify its Width and Height in the constructor (only those of the FMemo, but this is not relevant for the component. The recommended way how to specify component size in its constructor is by calling the function GetControlClassDefaultSize and passing its return value to SetInitialBounds. Compared to setting Width and Height directly, this avoids a lot of overhead which is unnecessary at this early stage of component creation.
Code: Pascal  [Select][+][-]
  1. procedure TLSB.Create(AOwner: TComponent);
  2. begin
  3.   inherited Create(AOwner);
  4.   with GetControlClassDefaultSize do
  5.     SetInitialBounds(0, 0, CX, CY);
  6. end;
  7.  
  8. class function TLSB.GetControlClassdefaultSize: TSize;  // must be declared in protected and as "override"
  9. begin
  10.   Result.CX := 100;     // This is the initial size of the component TLSB. Please adapt as needed.
  11.   Result.CY := 100;
  12. end;

Having set the control's size should fix also the issue with FMemo.Align.
@wp thank you for the guidance I now have a fair understanding of how things work. I have another question for you, if I may. In Linux 'lsblk' we have multiple switches one can use:
Code: Pascal  [Select][+][-]
  1. lsblk -a
  2. lsblk -S
  3. lsblk- J
  4. lsblk -t
how would I go about incorporating this into my component? I was thinking RadioGroup but cannot quite wrap my head around this. What I want is to give the user the ability to choose what they want lsblk to do. Or should I open a new thread?
« Last Edit: August 31, 2024, 02:53:56 pm by Aruna »

TRon

  • Hero Member
  • *****
  • Posts: 3477
Re: Custom Component Width and Height
« Reply #5 on: August 31, 2024, 03:01:31 pm »
In Linux 'lsblk' we have multiple switches one can use:
Code: Pascal  [Select][+][-]
  1. lsblk -a
  2. lsblk -S
  3. lsblk- J
  4. lsblk -t
how would I go about incorporating this into my component? I was thinking RadioGroup but cannot quite wrap my head around this. What I want is to give the user the ability to choose what they want lsblk to do. Or should I open a new thread?
If requiring detailed instructions then usually a new thread is preferred.

I don't believe a radiogroup supports nested buttons. e.g. some of these options are optional or working in conjunction with. the -J is one such option, it is the output format which can be turned on for every other request.

To my knowledge that should at least become something like a radiogroup /and/ (on or more) checkboxes. I am not aware of a component that combines that functionality (or could easily be produced) but also realize that my knowledge regarding (3th party) components is not that extensive.
This tagline is powered by AI

Aruna

  • Sr. Member
  • ****
  • Posts: 494
Re: Custom Component Width and Height
« Reply #6 on: August 31, 2024, 03:07:36 pm »
In Linux 'lsblk' we have multiple switches one can use:
Code: Pascal  [Select][+][-]
  1. lsblk -a
  2. lsblk -S
  3. lsblk- J
  4. lsblk -t
how would I go about incorporating this into my component? I was thinking RadioGroup but cannot quite wrap my head around this. What I want is to give the user the ability to choose what they want lsblk to do. Or should I open a new thread?
If requiring detailed instructions then usually a new thread is preferred.

I don't believe a radiogroup supports nested buttons. e.g. some of these options are optional or working in conjunction with. the -J is one such option, it is the output format which can be turned on for every other request.

To my knowledge that should at least become something like a radiogroup /and/ (on or more) checkboxes. I am not aware of a component that combines that functionality (or could easily be produced) but also realize that my knowledge regarding (3th party) components is not that extensive.
Understood and thanks. I will start a new thread as I am learning and detailed instructions would be nice:-) @TRon am not trying to plug in buttons. I have the component working right? Thanks to you showing me how to use RunCommand() some time back. So, I was thinking what if I have a group of radio buttons and when the user selects one then run the corresponding lsblk switch? No buttons are involved.

TRon

  • Hero Member
  • *****
  • Posts: 3477
Re: Custom Component Width and Height
« Reply #7 on: August 31, 2024, 03:13:39 pm »
So, I was thinking what if I have a group of radio buttons and when the user selects one then run the corresponding lsblk switch? No buttons are involved.
That should work, no doubt.

See for example the compiler commands that the Lazarus IDE passes through to the compiler for inspiration: https://wiki.lazarus.freepascal.org/IDE_Window:_Compiler_Options#Adding_a_release_and_debug_build_modes
This tagline is powered by AI

wp

  • Hero Member
  • *****
  • Posts: 12409
Re: Custom Component Width and Height
« Reply #8 on: August 31, 2024, 05:33:50 pm »
Adding a radiogroup to the component reduces its flexibility. Maybe some time in the future your form has little space and it would be better to have a combobox?

Rather than adding a control I would define an "Options" property. Then the user can decide on his own how to switch between the options.

In order to define such a property declare
Code: Pascal  [Select][+][-]
  1. type
  2.   TLSBOption = (lsboA, lsboS, lsboJ, lsboT);
  3.  
  4. type
  5.   TLSB = class(TCustomControl)
  6.   private
  7.     FOption: TLSBOption;
  8.     procedure DoRunCommand;
  9.   public
  10.     constructor Create(AOwner: TComponent);
  11.     procedure RunCommand;
  12.   published  // to have it in the ObjectInspector. Or only public?
  13.     property Option: TLSBOption read FOption write FOption;
  14.   end;
  15.  
  16. constructor TLSB.Create(AOwner: TComponent);
  17. begin
  18.   inherited Create(AOwner);
  19.   FOption := lsboJ;   // Set the default option
  20.   // Do not call DoRunCommand here
  21. end;
  22.  
  23. procedure TLSB.RunCommand;
  24. begin
  25.   DoRunCommand;
  26. end;
  27.  
  28. procedure TLSB.DoRunCommand;
  29. const
  30.   optionStr: array[TLSBOption] of string = ('-a', '-S', '-J', '-t');
  31. var
  32.   outstr: string;
  33. begin
  34.   Process.RunCommand('lsusb', [optionStr[FOption]], outstr);
  35.   FMemo.Lines.Add(outstr);
  36. end;
 
 

Aruna

  • Sr. Member
  • ****
  • Posts: 494
Re: Custom Component Width and Height
« Reply #9 on: September 01, 2024, 02:54:39 am »
Adding a radiogroup to the component reduces its flexibility. Maybe some time in the future your form has little space and it would be better to have a combobox?
Ah.. I did not think of this. Yes, very true.
Rather than adding a control I would define an "Options" property. Then the user can decide on his own how to switch between the options.
@wp yes certainly I will try this. My concern is with a property that is effective only at design time? I am not dead sure about this but this is what I have seen so far. I set the property and compile things work fine. Great!

Now if I set the property again to something else and click the button in the running application and nothing is picked up about the change in properties. I want to be able to select any option at run-time. Not have to stop the running program then change the property then recompile and run.
In order to define such a property declare
Code: Pascal  [Select][+][-]
  1. type
  2.   TLSBOption = (lsboA, lsboS, lsboJ, lsboT);
  3.  
  4. type
  5.   TLSB = class(TCustomControl)
  6.   private
  7.     FOption: TLSBOption;
  8.     procedure DoRunCommand;
  9.   public
  10.     constructor Create(AOwner: TComponent);
  11.     procedure RunCommand;
  12.   published  // to have it in the ObjectInspector. Or only public?
  13.     property Option: TLSBOption read FOption write FOption;
  14.   end;
  15.  
  16. constructor TLSB.Create(AOwner: TComponent);
  17. begin
  18.   inherited Create(AOwner);
  19.   FOption := lsboJ;   // Set the default option
  20.   // Do not call DoRunCommand here
  21. end;
  22.  
  23. procedure TLSB.RunCommand;
  24. begin
  25.   DoRunCommand;
  26. end;
  27.  
  28. procedure TLSB.DoRunCommand;
  29. const
  30.   optionStr: array[TLSBOption] of string = ('-a', '-S', '-J', '-t');
  31. var
  32.   outstr: string;
  33. begin
  34.   Process.RunCommand('lsusb', [optionStr[FOption]], outstr);
  35.   FMemo.Lines.Add(outstr);
  36. end;

Thank you so much @wp I will give this a go. Why have you said
Code: Pascal  [Select][+][-]
  1. // Do not call DoRunCommand here

Aruna

  • Sr. Member
  • ****
  • Posts: 494
Re: Custom Component Width and Height
« Reply #10 on: September 01, 2024, 03:39:21 am »
Hi, I have attached what I have managed to come up with so far. It does work ( but not the way I would like it to :-) I have learned a lot and I am thankful. If I want to set the background color of the Tmemo using a property how does one do that?

 

TinyPortal © 2005-2018