Recent

Author Topic: How can I place a label in front of a button without overlapping it?  (Read 3633 times)

Galmer

  • New Member
  • *
  • Posts: 10
Hello!

I only recently started using Lazarus, so I don’t know many of the nuances. I created TBitBtn and I need to place a label “on top” of it. If this is implemented directly, then the label intercepts button events and the button does not react to anything.

I have two options. Either somehow disable the label’s response to events, or somehow “throw” these events onto the button located under it.

I would be grateful for any help. Today I spent the whole day trying to understand how TVirtualStringTree works, my head is already hard to think)

P.S. The Caption property is not suitable here because it only places text on the side of the image.

ASerge

  • Hero Member
  • *****
  • Posts: 2358
Re: How can I place a label in front of a button without overlapping it?
« Reply #1 on: March 31, 2024, 10:22:14 pm »
Replace TLabel with TStaticText. It can.

Galmer

  • New Member
  • *
  • Posts: 10
Re: How can I place a label in front of a button without overlapping it?
« Reply #2 on: April 01, 2024, 10:51:59 am »
Replace TLabel with TStaticText. It can.

Thanks for the advice, but it didn't help. Static text, intercepts mouse events just like a label.

wp

  • Hero Member
  • *****
  • Posts: 12530
Re: How can I place a label in front of a button without overlapping it?
« Reply #3 on: April 01, 2024, 11:34:44 am »
Why don't you use the Caption property of the TBitBtn? You write "The Caption property is not suitable here because it only places text on the side of the image." So, you want to have the Caption above/below the image? Use the button's Layout property for this. Further parameters for affecting the text position are Margin (distance between image and border) and Spacing (distance between text and caption). -1 means in both cases: "automatic selection of value". Or you do not want to display an image at all? Leave the Glyph property empty (or ImageIndex at -1) in this case.

Galmer

  • New Member
  • *
  • Posts: 10
Re: How can I place a label in front of a button without overlapping it?
« Reply #4 on: April 01, 2024, 12:32:23 pm »
Hello!

I use the TBitBtn properties - ImageIndex, HotImageIndex and PressImageIndex to set my textures for these events. But at the same time, I need the inscription to be placed in the center of the button. I have attached a picture, there is a button with the inscription "AAC, 64 kbps".

The Caption and Layout properties are not suitable here, because I need to place the caption not on the side, but above the button - on top of it.

cdbc

  • Hero Member
  • *****
  • Posts: 1787
    • http://www.cdbc.dk
Re: How can I place a label in front of a button without overlapping it?
« Reply #5 on: April 01, 2024, 12:46:43 pm »
Hi
Use "TSpeedButton" instead of TBitButton...
It has a 'OnPaint' event, so when /push comes to shove/, you can use that to paint your text on the button, however you please.  8-)
ps.: The rest of the properties seem equivalent to TBitButton
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

wp

  • Hero Member
  • *****
  • Posts: 12530
Re: How can I place a label in front of a button without overlapping it?
« Reply #6 on: April 01, 2024, 12:47:07 pm »
TBitBtn.Layout in action in the attached project

Quote
I need to place the caption not on the side, but above the button
Above = outside? Then I don't understand why you cannot use a Label or StaticText...

Please post a drawing demonstrating what you want the button to look like.
« Last Edit: April 01, 2024, 12:49:44 pm by wp »

Galmer

  • New Member
  • *
  • Posts: 10
Re: How can I place a label in front of a button without overlapping it?
« Reply #7 on: April 01, 2024, 02:16:07 pm »
I don’t know spoken English well, so I use a translator.
Sorry if I don't express myself clearly.
Here is a project with an example of what I need to achieve.

wp

  • Hero Member
  • *****
  • Posts: 12530
Re: How can I place a label in front of a button without overlapping it?
« Reply #8 on: April 01, 2024, 03:20:58 pm »
Now I understand (yes, this "above", "on top of it" has two meanings...)

The following code implements a handler for the OnPaint event of the associated SpeedButton:
  • it queries the button state (pressed, mouse is over button, or not)
  • gets the corresponding images from the imagelist and adjusts the button's font (bold and aqua when pressed, normal and white otherwise)
  • stretchdraws the image over the entire button
  • draws the button's caption centered over the image.
Code: Pascal  [Select][+][-]
  1. uses
  2.   LCLIntf, LCLType;
  3.  
  4. procedure TForm1.SpeedButton3Paint(Sender: TObject);
  5. var
  6.   P: TPoint;
  7.   idx: Integer;
  8.   bmp: TBitmap;
  9.   R: TRect;
  10.   ts: TTextStyle;
  11.   mousePressed: Boolean;
  12.   btn: TSpeedButton;
  13. begin
  14.   // Exit when event is not fired by a speedbutton
  15.   if (Sender is TSpeedButton) then
  16.     btn := TSpeedButton(Sender)
  17.   else
  18.     exit;
  19.  
  20.   // Detect whether the mouse currently is pressed
  21.   mousePressed := (GetKeyState(VK_LBUTTON) < 0);
  22.  
  23.   // Detect whether the mouse currently is inside the speedbutton
  24.   P := btn.ScreenToClient(Mouse.CursorPos);
  25.   R := Rect(0, 0, btn.Width, btn.Height);
  26.   if PtInRect(R, P) then
  27.   begin
  28.     if mousePressed then
  29.       idx := 2      // idx identifies the image index needed from the ImageList
  30.     else
  31.       idx := 1
  32.   end else
  33.     idx := 0;
  34.  
  35.   // create a bitmap for the image
  36.   bmp := TBitmap.Create;
  37.   try
  38.     // Extract the image from the imagelist for the specified index into the bitmap
  39.     ImageList.GetBitmap(idx, bmp);
  40.     // Stretch-draw the bitmap to fit into the bounds of the speedbutton (R)
  41.     btn.Canvas.StretchDraw(R, bmp);
  42.     // Get the textstyle currently active in the speedbutton's canvas...
  43.     ts := btn.Canvas.TextStyle;
  44.     // ... and adjust it to center text horizontally
  45.     ts.Alignment := taCenter;
  46.     // ... and vertically inside the given rectangle (R)
  47.     ts.Layout := tlCenter;
  48.     // Apply the speedbutton's Font to the canvas
  49.     btn.Canvas.Font.Assign(btn.Font);
  50.     // Modify the font depending on the mouse state.
  51.     if mousePressed then
  52.     begin
  53.       btn.Canvas.Font.Style := [fsBold];
  54.       btn.Canvas.Font.Color := clAqua;
  55.     end else
  56.     begin
  57.       btn.Canvas.Font.Style := [];
  58.       btn.Canvas.Font.Color := clWhite;
  59.     end;
  60.     // Draw the text into the rectangle R using the canvas's TextStyle.
  61.     btn.Canvas.TextRect(R, 0, 0, btn.Caption, ts);
  62.   finally
  63.     // Destroy the temporary bitmap
  64.     bmp.Free;
  65.   end;
  66. end;      

I don't know how familiar you are with events in Lazarus:
  • copy the above code into your form's code
  • in the interface section of the form's unit, add the line "procedure SpeedButton3Paint(Sender: TObject);" immediately above the "private" in TForm's declaration.
  • in the object inspector select the speed button. On page "Events" of the object inspector click on dropwdown arroy next to OnPaint, and select the previously added procedure. This will assign this procedure to the OnPaint event of the button which will be executed whenever the speedbutton is repainted.
  • Repeat with other speedbutton which should share the same code.
« Last Edit: April 01, 2024, 03:23:22 pm by wp »

Galmer

  • New Member
  • *
  • Posts: 10
Re: How can I place a label in front of a button without overlapping it?
« Reply #9 on: April 01, 2024, 07:46:29 pm »
Thank you very much! Your advice helped me, but I took only part of the code with text rendering, this was enough for me.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.ButtonSourcesPaint(Sender: TObject);
  2. var
  3.    R: TRect;
  4.    ts: TTextStyle;
  5.  
  6. begin
  7.    R := Rect(0, 0, ButtonSources.Width, ButtonSources.Height);
  8.  
  9.    // Get the textstyle currently active in the speedbutton's canvas...
  10.    ts := ButtonSources.Canvas.TextStyle;
  11.    // ... and adjust it to center text horizontally
  12.    ts.Alignment := taCenter;
  13.    // ... and vertically inside the given rectangle (R)
  14.    ts.Layout := tlCenter;
  15.  
  16.    ButtonSources.Canvas.Font.Color := clHighlightText;
  17.  
  18.    ButtonSources.Canvas.TextRect(R, 0, 0, 'AAC, 64 kbps', ts);
  19. end;
  20.  

But when I used your code in full, when replacing the texture of the button from the code, for some reason it was drawn darker than when setting the texture through properties. It is not clear what this is connected with. I'll attach a screenshot to make it clearer.

Thanks again! It is very difficult to find any detailed resources on Lazarus, at least for me)


What I can do

  • Full Member
  • ***
  • Posts: 127
Re: How can I place a label in front of a button without overlapping it?
« Reply #10 on: April 29, 2024, 03:05:27 am »
I'm not a pro in any sort but I have done something similar. I think I made a button that was on/ off I use correldraw to make tow version of a bitmap so if you are a fair artist paint brush will do. I can't remember the exact button but any type with two version of bitmaps (active/inactive) in the settings should work. The on bitmap was bright blue with ON in the center colored red then the off was a bitmap with off in the center that was dark red while the rest was light gray. Sorry I don't have any code on hand but I think that should do it.  Hope this helps, keep on coding..

Чебурашка

  • Hero Member
  • *****
  • Posts: 586
  • СЛАВА УКРАЇНІ! / Slava Ukraïni!
Re: How can I place a label in front of a button without overlapping it?
« Reply #11 on: April 30, 2024, 12:07:23 am »
I had similar situation, I just created a callback method and assigned to both the components.

Procedure therealclick

Button.onclick := therealclick
Label.onclick := therralclick
FPC 3.2.0/Lazarus 2.0.10+dfsg-4+b2 on Debian 11.5
FPC 3.2.2/Lazarus 2.2.0 on Windows 10 Pro 21H2

 

TinyPortal © 2005-2018