* * *

Author Topic: Cross platform progress bar in a status bar  (Read 2271 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

  • Sr. Member
  • ****
  • Posts: 476
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

  • Sr. Member
  • ****
  • Posts: 476
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

  • Sr. Member
  • ****
  • Posts: 476
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.

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus