Recent

Author Topic: Cross platform progress bar in a status bar  (Read 6453 times)

ehj666

  • Jr. Member
  • **
  • Posts: 50
Cross platform progress bar in a status bar
« on: February 13, 2017, 07:20:04 pm »
I need to put a progress bar in the status bar at the bottom of the form. In Delphi on Windows, one way was as follows:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2.  
  3.   var
  4.     ProgressBarStyle: integer;
  5.  
  6.   begin
  7.   //enable status bar 2nd Panel custom drawing
  8.   StatusBar1.Panels[1].Style := psOwnerDraw;
  9.  
  10.   //place the progress bar into the status bar
  11.   ProgressBar1.Parent := StatusBar1;
  12.  
  13.   //remove progress bar border
  14.   ProgressBarStyle := GetWindowLong(ProgressBar1.Handle, GWL_EXSTYLE);
  15.   ProgressBarStyle := ProgressBarStyle - WS_EX_STATICEDGE;
  16.   SetWindowLong(ProgressBar1.Handle, GWL_EXSTYLE, ProgressBarStyle);
  17.   end;
  18.  

But off of Windows, the API calls are not recognized. Is there a way to do effectively the same thing in a cross platform manner?

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: Cross platform progress bar in a status bar
« Reply #1 on: February 13, 2017, 09:21:27 pm »
Is there a way to do effectively the same thing in a cross platform manner?
I think the StatusBar is not very suitable for placing other controls. Even in Windows the ProgressBar appears just to the left (does not shift to Panels[1]), and with enabled themes it generally leaves along when you resize the form. Use the Panel instead of the StatusBar.

derek.john.evans

  • Guest
Re: Cross platform progress bar in a status bar
« Reply #2 on: February 13, 2017, 09:25:06 pm »
Owner draw with a themed progressbar.
Code: Pascal  [Select][+][-]
  1. uses Themes, Types;
  2.  
  3. procedure TForm1.FormCreate(Sender: TObject);
  4. begin
  5.   StatusBar1.Panels[0].Style := psOwnerDraw;
  6. end;
  7.  
  8. procedure StatusPanelDrawProgressBar(A: TStatusPanel; ARect: TRect);
  9. var
  10.   LPosition: integer;
  11. begin
  12.   LPosition := StrToIntDef(A.Text, 0);
  13.   Themes.ThemeServices.DrawElement(A.StatusBar.Canvas.Handle,
  14.     Themes.ThemeServices.GetElementDetails(tpBar), ARect);
  15.   InflateRect(ARect, -4, -4);
  16.   ARect.Right := ARect.Left + ((ARect.Right - ARect.Left) * LPosition div 100);
  17.   Themes.ThemeServices.DrawElement(A.StatusBar.Canvas.Handle,
  18.     Themes.ThemeServices.GetElementDetails(tpChunk), ARect);
  19. end;
  20.  
  21. procedure TForm1.StatusBar1DrawPanel(StatusBar: TStatusBar; Panel: TStatusPanel; const Rect: TRect);
  22. begin
  23.   StatusPanelDrawProgressBar(Panel, Rect);
  24. end;
  25.  
  26. var
  27.   StatusPos: integer;
  28.  
  29. procedure TForm1.Timer1Timer(Sender: TObject);
  30. begin
  31.   Inc(StatusPos);
  32.   if StatusPos > 100 then begin
  33.     StatusPos := 0;
  34.   end;
  35.   StatusBar1.Panels[0].Text := IntToStr(StatusPos);
  36. end;  
  37.  

Im just using the panels text as the position (0..100). That way, when you change the text, the correct panel is invalidated and redrawn.

ehj666

  • Jr. Member
  • **
  • Posts: 50
Re: Cross platform progress bar in a status bar
« Reply #3 on: February 13, 2017, 10:07:04 pm »
I see what you are doing. Will give that a shot.

Thanks.

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: Cross platform progress bar in a status bar
« Reply #4 on: February 13, 2017, 11:14:32 pm »
Owner draw with a themed progressbar.
Excellent, but... it's look not same, as progress bar (XP theme and no animation).
So, let's try to adopt ProgressBar. Clear all Anchors for it and do that:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.StatusBar1DrawPanel(StatusBar: TStatusBar;
  2.   Panel: TStatusPanel; const Rect: TRect);
  3. begin
  4.   ProgressBar1.Parent := StatusBar;
  5.   ProgressBar1.BoundsRect := Rect;
  6. end;

derek.john.evans

  • Guest
Re: Cross platform progress bar in a status bar
« Reply #5 on: February 13, 2017, 11:48:20 pm »

Excellent, but... it's look not same, as progress bar (XP theme and no animation).
So, let's try to adopt ProgressBar. Clear all Anchors for it and do that:

Ooo, so close. I like the idea, but it causes problems here. But, this works:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormResize(Sender: TObject);
  2. begin
  3.   with StatusBar1 do begin
  4.     ProgressBar1.SetBounds(
  5.       Panels[0].Width + Panels[1].Width,
  6.       Top + 4, Panels[2].Width - 3,
  7.       Height - 6);
  8.   end;
  9. end;
  10.  

No need to change progressbar parent if its on top. This places it in panel[2].

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: Cross platform progress bar in a status bar
« Reply #6 on: February 14, 2017, 12:37:03 am »
Ooo, so close. I like the idea, but it causes problems here. But, this works:
I agree, it's much better. But hardcoded const, hmm, don't know. For example, for me looks nicer when Top+2, Width - 1 and Height - 3. Need to see how it looks on another OS.

ehj666

  • Jr. Member
  • **
  • Posts: 50
Re: Cross platform progress bar in a status bar
« Reply #7 on: February 14, 2017, 11:56:03 am »

Ooo, so close. I like the idea, but it causes problems here. But, this works:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormResize(Sender: TObject);
  2. begin
  3.   with StatusBar1 do begin
  4.     ProgressBar1.SetBounds(
  5.       Panels[0].Width + Panels[1].Width,
  6.       Top + 4, Panels[2].Width - 3,
  7.       Height - 6);
  8.   end;
  9. end;
  10.  

No need to change progressbar parent if its on top. This places it in panel[2].

That basically worked, except when using the last panel in the status bar, the width returned is the default 50, not the actual width of the last panel. I just calculated it from the remaining panels, although there might be an easier way.

Thanks.

 

TinyPortal © 2005-2018