Elliptic Progressbars

Share your advanced PureBasic knowledge/code with the community.
User avatar
Mischa
Enthusiast
Enthusiast
Posts: 115
Joined: Fri Aug 15, 2003 7:43 pm

Elliptic Progressbars

Post by Mischa »

Code updated for 5.20+

Code: Select all

#maxroundprogresses=10

Structure rprogress
  gadgetid.i
  imageid.i
  imagecolor.i
  backcolor.i
  frontcolor.i
  textcolor.i
  font.i
  max.i
  state.i
  extension.s
EndStructure

Global Dim RoundProgresses.rprogress(#maxroundprogresses)

Procedure SetRoundProgressState(id,state)
  If state<>RoundProgresses(id)\state
    w=ImageWidth(RoundProgresses(id)\imageid) : h=ImageHeight(RoundProgresses(id)\imageid)
    dc=StartDrawing(ImageOutput(RoundProgresses(id)\imageid))
      Box(0,0,w,h,RoundProgresses(id)\imagecolor)
      pen=CreatePen_(#PS_SOLID,1,RoundProgresses(id)\backcolor)
      brush=CreateSolidBrush_(RoundProgresses(id)\backcolor)
      SelectObject_(dc,brush) : SelectObject_(dc,pen)
      Ellipse_(dc,0,0,w,h)
      DeleteObject_(brush) : DeleteObject_(pen)
      pen=CreatePen_(#PS_SOLID,1,0)
      If RoundProgresses(id)\frontcolor=-1
        cstate=state * 448 / RoundProgresses(id)\max
        If cstate<256
          color=RGB(255,cstate,0)
        Else
          cstate-256
          color=RGB(255-cstate,255,0)
        EndIf
        brush=CreateSolidBrush_(color)
      Else  
        brush=CreateSolidBrush_(RoundProgresses(id)\frontcolor)
      EndIf
      SelectObject_(dc,brush) : SelectObject_(dc,pen)
      angle.f=state * 360 / RoundProgresses(id)\max
      If angle>0
        If angle>358
          Ellipse_(dc,0,0,w,h)
        Else
          mx=w/2 : my=h/2
          rx.f = 0 - (0 - my) * Sin(6.28318531*angle/360) + mx 
          ry.f = (0 - my) * Cos(6.28318531*angle/360) + my
          x2 = rx : y2 = ry
          Pie_(dc,0,0,w,h,x2,y2,w/2,0) 
        EndIf
      EndIf
      DeleteObject_(brush) : DeleteObject_(pen)
      SelectObject_(dc,RoundProgresses(id)\font)
      SetBkMode_(dc,#TRANSPARENT)
      SetTextColor_(dc,RoundProgresses(id)\textcolor)
      text.s = Str(state)+RoundProgresses(id)\extension
      DrawText_(dc,text,-1,rect.RECT,#DT_CALCRECT)
      diffx=(w-rect\right)/2 : diffy=(h-rect\bottom)/2
      DrawText(diffx, diffy, text)
    StopDrawing()
    RoundProgresses(id)\state = state
  EndIf
  SetGadgetState(RoundProgresses(id)\gadgetid,ImageID(RoundProgresses(id)\imageid))
EndProcedure

Procedure RoundProgress(id,x,y,w,h,ic,bc,fc,tc,font,max,state,ext.s)
  RoundProgresses(id)\gadgetid   = ImageGadget(#PB_Any,x,y,w,h,0)
  RoundProgresses(id)\imageid    = CreateImage(#PB_Any,w,h)
  RoundProgresses(id)\imagecolor = ic
  RoundProgresses(id)\backcolor  = bc
  RoundProgresses(id)\frontcolor = fc
  RoundProgresses(id)\textcolor  = tc
  RoundProgresses(id)\font       = font
  RoundProgresses(id)\max        = max
  RoundProgresses(id)\state      = -1
  RoundProgresses(id)\extension  = ext
  SetRoundProgressState(id,state)
EndProcedure

Procedure RemoveRoundProgress(id)
  FreeImage(RoundProgresses(id)\imageid)
  FreeGadget(RoundProgresses(id)\gadgetid)
EndProcedure  

OpenWindow(0,50,50,450,230,"Test",#PB_Window_SystemMenu)
font1=LoadFont(#PB_Any,"Arial",14,#PB_Font_Bold)
font2=LoadFont(#PB_Any,"Times New Roman",24,#PB_Font_Bold)
font3=LoadFont(#PB_Any,"System",10)

RoundProgress(0,10,10,100,100,GetSysColor_(#COLOR_BTNFACE),RGB(160,160,160),RGB(230,128,230),RGB(255,230,255),FontID(font1),100,0,"%")
RoundProgress(1,120,10,100,100,GetSysColor_(#COLOR_BTNFACE),RGB(160,160,160),RGB(230,230,128),RGB(255,255,230),FontID(font1),100,0,"%")
RoundProgress(2,230,10,210,210,GetSysColor_(#COLOR_BTNFACE),RGB(160,160,160),-1,RGB(0,0,0),FontID(font2),100,0,"%")
RoundProgress(3,10,120,100,100,GetSysColor_(#COLOR_BTNFACE),RGB(160,160,160),RGB(128,230,230),RGB(0,0,0),FontID(font1),1000,0," Units")
RoundProgress(4,120,120,100,45,GetSysColor_(#COLOR_BTNFACE),RGB(120,120,120),RGB(64,160,160),RGB(0,0,0),FontID(font3),100,0,"%")
RoundProgress(5,120,175,100,45,GetSysColor_(#COLOR_BTNFACE),RGB(80,80,32),RGB(160,160,64),RGB(255,255,128),FontID(font3),100,100,"%")

time=timeGetTime_()
Repeat
  Event=WindowEvent()
  If timeGetTime_()-time>80
    state1+1
    If state1>100
      state1=0
    EndIf
    state2+2
    If state2>100
      state2=0
    EndIf
    state3+4
    If state3>100
      state3=0
    EndIf
    state4+5
    If state4>1000
      state4=0
    EndIf
    state5+3
    If state5>100
      state5=0
    EndIf
    state6-2
    If state6<0
      state6=100
    EndIf
    SetRoundProgressState(5,state6)
    SetRoundProgressState(4,state5)
    SetRoundProgressState(3,state4)
    SetRoundProgressState(2,state1)
    SetRoundProgressState(1,state2)
    SetRoundProgressState(0,state3)
    time=timeGetTime_()
  EndIf  
  Delay(5)
Until Event=#PB_Event_CloseWindow
Regards,
Mischa
Fred
Administrator
Administrator
Posts: 18253
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

Very nice code :)

The Delay(5) should be put only when no event occurs else the event queue will be slow to flush (try to move the mouse over the window, the refresh is stopping partially)

So just replace Delay(5) with

Code: Select all

If Event
  ; Do your normal event check here and don't wait to check if another event is following
Else
  Delay(5)
EndIf
and all the refresh is now perfect.
Fred - AlphaSND
DarkDragon
Addict
Addict
Posts: 2345
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Post by DarkDragon »

Fred wrote:Very nice code :)

The Delay(5) should be put only when no event occurs else the event queue will be slow to flush (try to move the mouse over the window, the refresh is stopping partially)

So just replace Delay(5) with

Code: Select all

If Event
  ; Do your normal event check here and don't wait to check if another event is following
Else
  Delay(5)
EndIf
and all the refresh is now perfect.
I make it better:

Code: Select all

Select Event
  Case #PB_Event_Repaint
  Case ...
  Default
    Delay(5)
EndSelect
I like that more.
bye,
Daniel
Fred
Administrator
Administrator
Posts: 18253
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

Tastes and colors.. ;)
Fred - AlphaSND
User avatar
Le Soldat Inconnu
Enthusiast
Enthusiast
Posts: 306
Joined: Wed Jul 09, 2003 11:33 am
Location: France

Post by Le Soldat Inconnu »

I do the same in 3D 1 years ago :wink:

Sorry, comments are in french

Code: Select all

; Auteur : Le Soldat Inconnu
; Version de PB : 3.92
;
; Explication du programme :
; Dessiner un camembert en 3D

#Pi.f = 3.14159265

Procedure Pie3D(HDC.l, x.l, y.l, Rayon.l, Orientation.f, Hauteur.l, AngleDepart.f, AngleFin.f, Couleur.l)
  ; HDC : Handle du dessin
  ; X, Y : centre du camembert
  ; Rayon : Rayon du camembert
  ; Orientation : Orientation du camembert qui donne l'effet 3D. cette valeur doit être comprise entre 0 et 1
  ; Hauteur : Hauteur ou épaisseur du camembert
  ; AngleDepart : Angle de départ en radian
  ; AngleFin : Angle de fin en radian
  ; Couleur : Couleur du camenbert
  
  Protected R.l, G.l, b.l, n.l, AX1.l, AY1.l, AX2.l, AY2.l, Rayon2.l
  
  Rayon2 = Rayon * Orientation ; calul du rayon sur l'axe Y du camembert
  
  y = y - Hauteur / 2 ; on recentre le camemenbert en fonction de l'épaisseur
  
  R = Red(Couleur) : G = Green(Couleur) : b = Blue(Couleur) ; On décompose la couleur en RGB
  
  AX2 = Int(x + 100 * Cos(AngleDepart)) ; calcul du point d'arriver
  AY2 = Int(y + 100 * Sin(AngleDepart) * Orientation)
  
  AX1 = Int(x + 100 * Cos(AngleFin)) ; calcul du point de départ
  AY1 = Int(y + 100 * Sin(AngleFin) * Orientation)
  
  For n = Hauteur To 1 Step -1 ; On dessine l'épaisseur du camembert
    FrontColor(R * (0.8 - 0.08 * n / Hauteur), G * (0.8 - 0.08 * n / Hauteur), b * (0.8 - 0.08 * n / Hauteur)) ; Choix de la couleur du bord du camembert
    Pie_(HDC, x - Rayon, y - Rayon2 + n, x + Rayon, y + Rayon2 + n, AX1, AY1 + n, AX2, AY2 + n)
  Next
  
  ; On dessine le dessus du camembert
  FrontColor(R, G, b)
  Pie_(HDC, x - Rayon, y - Rayon2, x + Rayon, y + Rayon2, AX1, AY1, AX2, AY2) ; on dessine le dessus du camembert
  
EndProcedure

Procedure DoublePie3D(HDC.l, x.l, y.l, Rayon.l, Orientation.f, Hauteur.l, Decalage.l, Angle.f, Couleur1.l, Couleur2.l)
  ; HDC : Handle du dessin
  ; X, Y : centre du camembert
  ; Rayon : Rayon du camembert
  ; Orientation : Orientation du camembert qui donne l'effet 3D. cette valeur doit être comprise entre 0 et 1
  ; Hauteur : Hauteur ou épaisseur du camembert
  ; Decalage : Pour mettre un espace entre les 2 zone du camenbert
  ; Angle : Angle correspondant à la zone 1 du camembert
  ; Couleur1 : Couleur de la zone 1 du camenbert
  ; Couleur2 : Couleur de la zone 2 du camenbert
  
  DecalageX = Decalage * Cos(Angle / 2)
  DecalageY = Decalage * Sin(Angle / 2)
  
  If Angle = 0
    Pie3D(HDC, x, y, Rayon, Orientation, Hauteur, 0, 2 * #Pi, Couleur1)
  ElseIf Angle <= #Pi / 2
    Pie3D(HDC, x + DecalageX, y + DecalageY, Rayon, Orientation, Hauteur, #Pi + Angle, 0, Couleur1)
    Pie3D(HDC, x - DecalageX, y - DecalageY, Rayon, Orientation, Hauteur, #Pi, #Pi + Angle, Couleur2)
    Pie3D(HDC, x + DecalageX, y + DecalageY, Rayon, Orientation, Hauteur, 0, #Pi, Couleur1)
  ElseIf Angle <= 3 * #Pi / 2
    Pie3D(HDC, x - DecalageX, y - DecalageY, Rayon, Orientation, Hauteur, #Pi, #Pi + Angle, Couleur2)
    Pie3D(HDC, x + DecalageX, y + DecalageY, Rayon, Orientation, Hauteur, #Pi + Angle, #Pi, Couleur1)
  Else
    Pie3D(HDC, x - DecalageX, y - DecalageY, Rayon, Orientation, Hauteur, #Pi, 0, Couleur2)
    Pie3D(HDC, x + DecalageX, y + DecalageY, Rayon, Orientation, Hauteur, #Pi + Angle, #Pi, Couleur1)
    Pie3D(HDC, x - DecalageX, y - DecalageY, Rayon, Orientation, Hauteur, 0, #Pi + Angle, Couleur2)
  EndIf
EndProcedure



; Création de la fenêtre et dela GadgetList
If OpenWindow(0, 0, 0, 600, 600, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget, "Test") = 0 Or CreateGadgetList(WindowID()) = 0
  End
EndIf

CreateImage(0, 600, 600)
ImageGadget(0, 0, 0, 0, 0, UseImage(0))

SetTimer_(WindowID(), 0, 50, 0)

Repeat
  Event = WaitWindowEvent()
  
  If Event = #WM_TIMER
    
    Angle.f + 0.02
    If Angle > 2 * #Pi
      Angle = 0
    EndIf
    
    HDC = StartDrawing(ImageOutput())
      Box(0, 0, 600, 600, 0)
      
      ; Camenbert normal (1 seule part)
      Pie3D(HDC, 150, 150, 120, 0.45, 20, Angle, 0, RGB(100, 200, 200))
      
      ; Camenbert normal (1 seule part)
      Pie3D(HDC, 150, 450, 120, 0.8, 20, #Pi, #Pi + Angle, RGB(100, 200, 200))
      
      ; Camenbert avec 2 parts
      DoublePie3D(HDC, 450, 150, 140, 0.6, 10, 0, Angle, RGB(100, 200, 200), RGB(0, 150, 150))
      
      ; Camenbert avec 2 parts et avec un espace entre les parts
      DoublePie3D(HDC, 450, 450, 100, 0.5, 15, 5, Angle, RGB(100, 200, 200), RGB(0, 150, 150))
      
      
    StopDrawing()
    SetGadgetState(0, UseImage(0))
    
  EndIf
  
Until Event = #PB_EventCloseWindow

KillTimer_(WindowID(), 0)

End
LSI
kawasaki
Enthusiast
Enthusiast
Posts: 182
Joined: Thu Oct 16, 2003 8:09 pm

Post by kawasaki »

Very nice example of progresspies :P
akee
Enthusiast
Enthusiast
Posts: 498
Joined: Wed Aug 18, 2004 9:52 am
Location: Penang, Malaysia

Post by akee »

nice pies...
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

nice indeed, Mischa!

and now for a fully anti-aliased version....

Relax, just kidding!
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
User avatar
Le Soldat Inconnu
Enthusiast
Enthusiast
Posts: 306
Joined: Wed Jul 09, 2003 11:33 am
Location: France

Post by Le Soldat Inconnu »

Anti-aliazed version ?
very simple

just draw your pie with a big size

and resize your image

the result is the pie Anti-aliazed.

It's low but it's a very simple way
LSI
User avatar
GeoTrail
Addict
Addict
Posts: 2794
Joined: Fri Feb 13, 2004 12:45 am
Location: Bergen, Norway
Contact:

Post by GeoTrail »

What does

Code: Select all

SetTimer_(WindowID(), 0, 50, 0)
do?
I Stepped On A Cornflake!!! Now I'm A Cereal Killer!
akee
Enthusiast
Enthusiast
Posts: 498
Joined: Wed Aug 18, 2004 9:52 am
Location: Penang, Malaysia

Post by akee »

GeoTrail wrote:What does

Code: Select all

SetTimer_(WindowID(), 0, 50, 0)
do?
It is to enable the timer so that a WM_TIMER event is trigered every specified time slice.
User avatar
GeoTrail
Addict
Addict
Posts: 2794
Joined: Fri Feb 13, 2004 12:45 am
Location: Bergen, Norway
Contact:

Post by GeoTrail »

Aaa I see, thanx :)
I Stepped On A Cornflake!!! Now I'm A Cereal Killer!
Post Reply