12

I want to put a label inside progress bar. And this label caption is dynamic. How can I get the label position ALWAYS on center inside the ProgressBar?

What I've tried ;

  Label1.Parent := progressBar1;
  Label1Top :=  progressBar1.Height div 2;
  Label1.Left :=  progressBar1.Width div 2

It shows ugly, and not in center like I want.

Label inside progress bar

If I set Label1.Left := progresBar1.Width div 2 - xxx it will be on center only for certain caption. I want to have any caption be placed on center.

Edited Answer from @KenWhite is working good. Solution from @DavidHeffernan just great.

ProgressBar with Text

Bianca
  • 973
  • 2
  • 14
  • 33

2 Answers2

23

Set the label's AutoSize property to False. Change the Alignment property to taCenter and Layout to tlCenter. Size the label to the progressbar's ClientWidth and ClientHeight, and set its Left to 0.

Label1.Parent := progressBar1;
Label1.AutoSize := False;
Label1.Transparent := True;
Label1.Top :=  0;
Label1.Left :=  0;
Label1.Width := progressBar1.ClientWidth;
Label1.Height := progressBar1.ClientHeight;
Label1.Alignment := taCenter;
Label1.Layout := tlCenter;

Here's an example of the appearance:

Image of standard sized progress bar Image of double height progress bar

Ken White
  • 123,280
  • 14
  • 225
  • 444
  • BINGO ! This works great like i want. Thank you so much. – Bianca Oct 24 '14 at 00:09
  • 4
    You should probably also make `Label1.Transparent := True` in case themes are not used. +1 – kobik Oct 24 '14 at 11:58
  • One last thinng: I would probably use `Label1.Align := alClient;` with `Label1.Alignment := taCenter; Label1.Layout := tlCenter; Label1.Transparent := true;` so if the ProgressBar grows at runtime the label is always aligned to `alClient` and centered. – kobik Oct 24 '14 at 13:39
15

You might decide to derive a progress bar control that paints the text itself rather than relying on a separate label. Some sample code to demonstrate:

type
  TProgressBarWithText = class(TProgressBar)
  private
    FProgressText: string;
  protected
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  published
    property ProgressText: string read FProgressText write FProgressText;
  end;

procedure TProgressBarWithText.WMPaint(var Message: TWMPaint);
var
  DC: HDC;
  prevfont: HGDIOBJ;
  prevbkmode: Integer;
  R: TRect;
begin
  inherited;
  if ProgressText <> '' then
  begin
    R := ClientRect;
    DC := GetWindowDC(Handle);
    prevbkmode := SetBkMode(DC, TRANSPARENT);
    prevfont := SelectObject(DC, Font.Handle);
    DrawText(DC, PChar(ProgressText), Length(ProgressText),
      R, DT_SINGLELINE or DT_CENTER or DT_VCENTER);
    SelectObject(DC, prevfont);
    SetBkMode(DC, prevbkmode);
    ReleaseDC(Handle, DC);
  end;
end;

The advantage of this approach is that your progress bar and text display are self-contained. There's no need for two separate controls that you have to coordinate.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thank you Sir!. Yes this is cool. But this kinda too advance for me. May I have one more example of the implementation on progressing step + text by using `TTimer` ? – Bianca Oct 24 '14 at 11:51
  • 1
    Well, it's all here. You just use this control and set the `ProgressText` property. To do that at design time you'd need to add and register the control in a design time package. If you were prepared to set `ProgressText` at runtime you could use an interposer class. – David Heffernan Oct 24 '14 at 11:57
  • @DavidHeffernan GREAT! Thank you so much. Edited first post. Thanks again. – Bianca Oct 24 '14 at 12:26
  • 7
    Although, in my view, using a single control is better than a control and a label, I don't think you should accept this answer. I would prefer it if you accepted Ken's answer since it directly answers the question that you asked. I just offered an alternative way to look at the entire problem. Ken's answer is a better fit to the question you asked, in my view. – David Heffernan Oct 24 '14 at 12:30
  • Aha, per post title, yes it is.. OK then. Have a nice day Sir. – Bianca Oct 24 '14 at 12:35
  • The required units for the above code are: ComCtrls, Messages, Windows. – john_who_is_doe Jan 16 '18 at 12:01