Page 1 of 2

Meter Control - a gadget like the task manager graph

Posted: Thu Nov 09, 2006 12:24 am
by localmotion34
so in the midst of writing image decoders, encoders, and about 5 other things, i came across tons and tons of Pelles C sources with killer controls and routines. Ive always been fascinated by the "Dave's Frame Class" of the task manager graph, and when i saw a DLL that did it in Pelles, i mimicked the source in PB.

So here it is. Grab the slider and yank it around, fast, slow - it doesnt matter.

then if you want, grab and save the resulting graph as a bitmap. let me know what you guys think. as always, comments, suggestions, and bug reports are welcome...

Code: Select all



Structure Meter
  PBimg.l
  width.l
  height.l
  offset.l
  values.l[1024]
EndStructure



#WM_UPDATEMETER	= #WM_USER+1500
#WM_SETFGCOLOR	= #WM_USER+1501
#WM_SETBGCOLOR	= #WM_USER+1502
#WM_SETGDCOLOR	= #WM_USER+1503
#WM_SETBDCOLOR	= #WM_USER+1504
#WM_FILLED		= #WM_USER+1506
#WM_PEAK			= #WM_USER+1507


Procedure MeterProc(hwnd,msg,wParam,lParam)
  Select msg
    Case #WM_UPDATEMETER
      *mr.Meter=GetWindowLong_(hwnd,#GWL_USERDATA)
      If *mr\offset=10
        *mr\offset=0
      EndIf 
      For d=0 To *mr\width-1 
        *mr\values[d]=*mr\values[d+1] 
      Next  
      *mr\values[*mr\width-1]=lParam
      StartDrawing(ImageOutput(*mr\PBimg))
      Box(0,0,*mr\width,*mr\height,#Black)
      For a=0 To *mr\height Step 10
        LineXY(0,a,*mr\width,a,$7F00)
      Next 
      For a=0 To *mr\width+*mr\offset Step 10
        LineXY(a-*mr\offset,0,a-*mr\offset,*mr\height,$7F00)
      Next 
      For d=0 To *mr\width
        bottom.l=*mr\height
        thepercent.f=(*mr\values[d]/100)
        actualheight.l=Int(thepercent* *mr\height)
        Y1.l=bottom-actualheight
        thepercent.f=(*mr\values[d+1]/100)
        actualheight.l=Int(thepercent* *mr\height)
        Y2.l=bottom-actualheight
         LineXY(d,Y1,d+1,Y2,$FF00)
      Next 
      *mr\offset+1
      StopDrawing()
      SetWindowLong_(hwnd,#GWL_USERDATA,*mr)
      SendMessage_(hwnd,#STM_SETIMAGE,#IMAGE_BITMAP,ImageID(*mr\PBimg))
  EndSelect 
  ProcedureReturn CallWindowProc_(GetProp_(hwnd,"oldproc"),hwnd,msg,wParam,lParam)
EndProcedure 

Procedure MeterControl(id.l,x,Y,width,height) 
  image=CreateImage(#PB_Any,width,height)
  StartDrawing(ImageOutput(image))
  Box(0,0,width,height,#Black)
  For a=0 To height Step 10
    LineXY(0,a,width,a,$7F00)
  Next 
  For a=0 To width Step 10
    LineXY(a,0,a,height,$7F00)
  Next 
  StopDrawing()
  imagegad.l=ImageGadget(id,x,Y,width,height,ImageID(image),#PB_Image_Border)
  setprop_(GadgetID(imagegad),"oldproc",SetWindowLong_(GadgetID(imagegad),#GWL_WNDPROC,@MeterProc()))
  If id=#PB_Any
    hwndreturn=imagegad
    hwnd=GadgetID(imagegad)
  Else
    hwndreturn=imagegad
    hwnd=imagegad
  EndIf 
  *mtr.Meter=AllocateMemory(SizeOf(Meter))
  *mtr\PBimg=image
  *mtr\width=width
  *mtr\height=height 
  SetWindowLong_(hwnd,#GWL_USERDATA,*mtr)
  ProcedureReturn hwndreturn
EndProcedure 

Procedure GetMeterImage(id.l)
  *mr.Meter=GetWindowLong_(GadgetID(id),#GWL_USERDATA)
  bitmapreturn.l=*mr\PBimg
  ProcedureReturn bitmapreturn 
EndProcedure 

OpenWindow(0,0,0,470,460,"Meter Control",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
CreateGadgetList(WindowID(0))
themeter.l=MeterControl(#PB_Any,90,10,290,180)
TrackBarGadget(20,110,300,260,30,0,100)
ButtonGadget(21,160,350,140,20,"Save Meter Image")
Repeat
  
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      SendMessage_(GadgetID(themeter),#WM_UPDATEMETER,0,GetGadgetState(20))
      Select EventGadget()
        Case 21
          Pattern$ + "Bitmap (*.bmp)|*.bmp|" 
          Pattern = 0   
          filename.s=SaveFileRequester("Please Choose The File Name To Save", "", Pattern$, Pattern)
          If filename
            If GetExtensionPart(filename)<>"bmp"
              filename+".bmp"
            EndIf 
            SaveImage(GetMeterImage(themeter),filename,#PB_ImagePlugin_BMP)
          EndIf 
      EndSelect
    Case #PB_Event_CloseWindow
      
      Quit=1
  EndSelect
Until Quit=1



Soooo many uses!!

Posted: Thu Nov 09, 2006 5:39 am
by danraymond
I have so many uses for this!!!!

thank you so much. Clever coding


Dan Raymond

Posted: Thu Nov 09, 2006 8:36 am
by Rescator
I got rid of that annoying vertical line at the end of the graph by changing
LineXY(d,Y1,d+1,Y2,$FF00)
to
LineXY(d+1,Y1,d+1,Y2,$FF00)
in the meter proc procedure.
No idea why this fixed it (did not really study the code) or if it impacts the accuracy or not.

Posted: Thu Nov 09, 2006 9:20 am
by dige
pretty nice and interessting way of coding!

Posted: Thu Nov 09, 2006 1:49 pm
by Rescator
Yeah very fun code there, and it made my fingers tingle. I knew this could be made better. So I gave it a shot.

I'm sure this can be improved even further, I did not improve the meter drawing code for example.
One idea I wanted to try but did not bother (feel free to do it anyone else)
is to "shift" the image one pixel to the left, and draw the new linexy/line/pixel at the right (end) instead of redrawing the whole thing as the original code do. There is probably other ways to do this as well I'm sure.

Anyway. The changes I did was quite a few.
The code is now platform independent. (PB native code only, no API used)
developed with EnableExplicit on to allow "slot in" use with minimal need for "fixes" by those who use EnableExplicit all the time. (don't ya just hate having to "correct" code all the time? :)
And the coolest of all, unlimited amount of MeterGadget's at the same time :)
And it behaves almost the same as a normal PB gadget (read source comments for details please)

PS! As mentioned above, this can be optimized further. I tried my best to optimize the loop itself. (getting rid of all those SendMessage API calls sped it up a lot. (Note! SendMessage waits to return, PostMessage is fire and forget and might be better)
I also put the imageid in the structure as well (I know that ImageID(image) could have been used instead but as I'm unsure how much code is in ImageID() I bet that a variable in a structure would be faster in any case.

Have fun folks!

Code: Select all

EnableExplicit

;MeterGadget is a mix of a gadget and a image, a few procedures have been made to make
;gadget handling easier. In general a MeterGadget behaves almost like a normal ImageGadget.

;Otherwise normal gadget functions can be used (that works with ImageGadget)
;and obviously since it is a imagegadget it has the same gadget events returned as well.
;Tooltips can be set just like with any other ImageGadget.
;flags constants are the same as the flags constants used for ImageGadget like #PB_Image_Border

;IMPORTANT! SetGadgetData() MUST NOT be used with the MeterGadget,
;it's used for the structure pointers.
;Use SetMeterGadgetData() and GetMeterGadgetData() instead.

Structure MeterGadget_struct
 image.l
 imageid.l
 x.l
 y.l
 w.l
 h.l
 bgcolor.l
 fgcolor.l
 linecolor.l
 offset.l
 userdata.l
 flags.l
 table.l[1024]
EndStructure


;Create #Image and #Gadget etc.
Procedure.l MeterGadget(gadget.l,x.l,y.l,width.l,height.l,bgcolor.l,fgcolor.l,linecolor.l,flags.l=#Null)
 Protected *m.MeterGadget_struct,result.l=#Null,n.l,p.l=0,newgadget.l
 If IsGadget(gadget)
  *m=GetGadgetData(gadget)
  If *m
   result=*m\image
  EndIf
 EndIf
 *m=AllocateMemory(SizeOf(MeterGadget_struct))
 If *m
  *m\flags=flags
  If *m\flags=#PB_Image_Border
   *m\w=width-2
   *m\h=height-2
  Else
   *m\w=width
   *m\h=height
  EndIf
  *m\x=x
  *m\y=y
  *m\bgcolor=bgcolor
  *m\fgcolor=fgcolor
  *m\linecolor=linecolor
  *m\image=CreateImage(#PB_Any,width,height,#PB_Image_DisplayFormat)
  If IsImage(*m\image)
   *m\imageid=ImageID(*m\image)
   If StartDrawing(ImageOutput(*m\image))
    Box(p,p,*m\w,*m\h,*m\bgcolor)
    For n=0 To *m\h Step 10
      LineXY(p,n,*m\w,n,*m\fgcolor)
    Next
    For n=0 To width Step 10
      LineXY(n,p,n,*m\h,*m\fgcolor)
    Next
    StopDrawing()
    result=ImageGadget(gadget,*m\x,*m\y,*m\w,*m\h,*m\imageid,flags)
   EndIf
  EndIf
  If gadget=#PB_Any
   newgadget=result
  Else
   newgadget=gadget
  EndIf
  If IsGadget(newgadget)
   SetGadgetData(newgadget,*m)
  Else
   If IsImage(*m\image)
    FreeImage(*m\image)
   EndIf
   FreeMemory(*m)
  EndIf
 EndIf
 ProcedureReturn result
EndProcedure

;Use this instead of SetGadgetState()
Procedure SetMeterGadgetState(gadget.l,state.l)
 Protected *m.MeterGadget_struct,result.l
 Protected n.l,x1.l,x2.l,y1.l,y2.l,bottom.l,percent.f,h.l,p.l
 *m=GetGadgetData(gadget)
 If *m\offset=10
   *m\offset=0
 EndIf
 If *m\flags=#PB_Image_Border
  p=1
 Else
  p=0
 EndIf
 For n=0 To *m\w-1
   *m\table[n]=*m\table[n+1]
 Next 
 *m\table[*m\w-1]=state
 If StartDrawing(ImageOutput(*m\image))
  Box(p,p,*m\w,*m\h,*m\bgcolor)
  For n=0 To *m\h Step 10
    LineXY(p,n,*m\w,n,*m\fgcolor)
  Next
  For n=0 To *m\w+*m\offset Step 10
    LineXY(n-*m\offset,p,n-*m\offset,*m\h,*m\fgcolor)
  Next
  For n=0 To *m\w
    bottom=*m\h
    percent=(*m\table[n]/100.0)
    h=Int(percent * *m\h)
    y1=bottom-h
    percent=(*m\table[n+1]/100)
    h=Int(percent * *m\h)
    y2.l=bottom-h
    LineXY(n+1,y1,n+1,y2,*m\linecolor)
  Next
  *m\offset+1
  StopDrawing()
  SetGadgetState(gadget,*m\imageid)
 EndIf
EndProcedure

;Use this instead of FreeGadget() to avoid memory leaks.
Procedure FreeMeterGadget(gadget.l)
 Protected *m.MeterGadget_struct
 If IsGadget(gadget)
  *m=GetGadgetData(gadget)
  FreeGadget(gadget)
  If *m
   If IsImage(*m\image)
    FreeImage(*m\image)
   EndIf
   FreeMemory(*m)
  EndIf
 EndIf
EndProcedure

;Use this instead of SetGadgetData().
Procedure SetMeterGadgetData(gadget.l,userdata.l)
 Protected *m.MeterGadget_struct
 *m=GetGadgetData(gadget)
 *m\userdata=userdata
EndProcedure

;Use this instead of GetGadgetData().
Procedure.l GetMeterGadgetData(gadget.l)
 Protected *m.MeterGadget_struct
 *m=GetGadgetData(gadget)
 ProcedureReturn *m\userdata
EndProcedure

;Use this instead of GetGadgetState(). Not that usefull but may be handy to have.
Procedure.l GetMeterGadgetState(gadget.l)
 Protected *m.MeterGadget_struct
 *m=GetGadgetData(gadget)
 ProcedureReturn *m\offset
EndProcedure

;Use this to get #Image
Procedure.l GetMeterGadgetImage(gadget.l)
 Protected *m.MeterGadget_struct,result.l=#Null
 *m=GetGadgetData(gadget)
 ProcedureReturn *m\image
EndProcedure

;******************************************************************************
;- Example of use

Define event.l,gadget.l,filename$,pattern$,patternpos.l,oldtime.l,newtime.l

Enumeration 1
 #Window
EndEnumeration

Enumeration 1
 #Meter1
 #Meter2
 #Meter3
 #Trackbar
 #Saveimage
EndEnumeration

If OpenWindow(#Window,0,0,470,460,"Meter Control",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)=#False
 End
EndIf

If CreateGadgetList(WindowID(#Window))=#False
 End
EndIf

If MeterGadget(#Meter1,90,10,290,180,RGB($0,$0,$0),RGB($0,$7F,$0),RGB($0,$FF,$0))=#False
 End
EndIf

If MeterGadget(#Meter2,90,200,290,40,RGB($0,$0,$0),RGB($7F,$0,$0),RGB($FF,$FF,$0))=#False
 End
EndIf

If MeterGadget(#Meter3,90,240,290,40,RGB($0,$0,$0),RGB($0,$0,$7F),RGB($0,$FF,$FF))=#False
 End
EndIf

If TrackBarGadget(#Trackbar,110,300,260,30,0,100)=#False
 End
EndIf

If ButtonGadget(#Saveimage,160,350,140,20,"Save Meter 1 Image")=#False
 End
EndIf


;Meter 1 only updates "manually" (by moving trackbar for example)
;some other form of userinput or info could be used to feed it as well.

;Meter 2 only updates when there is no events,
;and as the waitloop is set to 10ms this is the max update rate.

;Meter 3 updates only each 50ms, regardless of user input or not.
;However for this to work properly the waitloop need to be 50ms or lower.


oldtime=ElapsedMilliseconds()
Repeat
 newtime=ElapsedMilliseconds()
 If (newtime-oldtime)>49 ;if 50ms or higher then update Meter 3
  oldtime=newtime
  SetMeterGadgetState(#Meter3,GetGadgetState(#Trackbar))
 EndIf
 event=WaitWindowEvent(10)
 If event
  Select event
   Case #PB_Event_Gadget
    gadget=EventGadget()
    Select gadget
     Case #Trackbar ;User input, update meter 1.
      SetMeterGadgetState(#Meter1,GetGadgetState(#Trackbar))
     Case #Saveimage
      pattern$="Bitmap (*.bmp)|*.bmp|"
      patternpos=0
      filename$=SaveFileRequester("Save image as:","",pattern$,patternpos)
      If filename$
       If GetExtensionPart(filename$)<>"bmp"
        filename$+".bmp"
       EndIf
       SaveImage(GetMeterGadgetImage(#Meter1),filename$,#PB_ImagePlugin_BMP)
      EndIf
    EndSelect
  EndSelect
 Else ;No event has happen for the last 10ms, Update meter 2.
  SetMeterGadgetState(#Meter2,GetGadgetState(#Trackbar))
 EndIf
Until event=#PB_Event_CloseWindow

End

Posted: Thu Nov 09, 2006 3:06 pm
by localmotion34
Allright Rescator, you wanna play? heheh :twisted: :twisted:

thats a great idea to allow foreground and background colors, and i will include it in my structure.

as far as drawing the whole image over again, i mimicked this exactly from a PellesC source, which did it this exact way. i think you really have to redraw the whole image because the image is of a fixed size, and shifting the image to the left will leave a blank part to the right. it will have to be redrawn anyway.

since i use the same image over and over again to draw to, and the just re-set the imagegadget, all that really happens is the drawing followed by a static control hDc update and refresh.

there is probably a more optimized way to draw using the API and Lineto_ and MoveToEx.

my control works plotting CPU useage while compressing a 200 meg folder of PSD files without so much as flicker.

you way is awesome for those who want cross platform, but my intended use is to have additional notifications posted to the message loop like #wm_meterchanged, or #wm_meterreach_Max so i can track what is really going on.

http://www.penguinbyte.com/apps/pbwebst ... 1/test.bmp


here is an example with my old LEDgadget thrown in:

Code: Select all



Structure Meter
  PBimg.l
  width.l
  height.l
  offset.l
  values.l[1024]
EndStructure

Structure gauge
  imagegad.l
  imageid.l
  width.l
  height.l
  imagehwnd.l
  precision.l
  ticks.l
  textgad.l
  texthwnd.l 
  state.l
  numstates.l
EndStructure

Global theThread.l ,themeter.l,nextmeter.l

#WM_UPDATEMETER	= #WM_USER+1500
#WM_SETFGCOLOR	= #WM_USER+1501
#WM_SETBGCOLOR	= #WM_USER+1502
#WM_SETGDCOLOR	= #WM_USER+1503
#WM_SETBDCOLOR	= #WM_USER+1504
#WM_FILLED		= #WM_USER+1506
#WM_PEAK			= #WM_USER+1507

;-Meter Control 
Procedure MeterProc(hwnd,msg,wParam,lParam)
  Select msg
    Case #WM_UPDATEMETER
      *mr.Meter=GetWindowLong_(hwnd,#GWL_USERDATA)
      If *mr\offset=10
        *mr\offset=0
      EndIf 
      For d=0 To *mr\width-1 
        *mr\values[d]=*mr\values[d+1] 
      Next  
      *mr\values[*mr\width-1]=lParam
      StartDrawing(ImageOutput(*mr\PBimg))
      Box(0,0,*mr\width,*mr\height,#Black)
      For a=0 To *mr\height Step 10
        LineXY(0,a,*mr\width,a,$7F00)
      Next 
      For a=0 To *mr\width+*mr\offset Step 10
        LineXY(a-*mr\offset,0,a-*mr\offset,*mr\height,$7F00)
      Next 
      For d=0 To *mr\width
        bottom.l=*mr\height
        thepercent.f=(*mr\values[d]/100)
        actualheight.l=Int(thepercent* *mr\height)
        Y1.l=bottom-actualheight
        thepercent.f=(*mr\values[d+1]/100)
        actualheight.l=Int(thepercent* *mr\height)
        Y2.l=bottom-actualheight
        LineXY(d+1,Y1,d+1,Y2,$FF00)
      Next 
      *mr\offset+1
      StopDrawing()
      SetWindowLong_(hwnd,#GWL_USERDATA,*mr)
      SendMessage_(hwnd,#STM_SETIMAGE,#IMAGE_BITMAP,ImageID(*mr\PBimg))
  EndSelect 
  ProcedureReturn CallWindowProc_(GetProp_(hwnd,"oldproc"),hwnd,msg,wParam,lParam)
EndProcedure 


Procedure MeterControl(id.l,x,Y,width,height) 
  image=CreateImage(#PB_Any,width,height)
  StartDrawing(ImageOutput(image))
  Box(0,0,width,height,#Black)
  For a=0 To height Step 10
    LineXY(0,a,width,a,$7F00)
  Next 
  For a=0 To width Step 10
    LineXY(a,0,a,height,$7F00)
  Next 
  StopDrawing()
  imagegad.l=ImageGadget(id,x,Y,width,height,ImageID(image),#PB_Image_Border)
  setprop_(GadgetID(imagegad),"oldproc",SetWindowLong_(GadgetID(imagegad),#GWL_WNDPROC,@MeterProc()))
  If id=#PB_Any
    hwndreturn=imagegad
    hwnd=GadgetID(imagegad)
  Else
    hwndreturn=imagegad
    hwnd=imagegad
  EndIf 
  *mtr.Meter=AllocateMemory(SizeOf(Meter))
  *mtr\PBimg=image
  *mtr\width=width
  *mtr\height=height 
  SetWindowLong_(hwnd,#GWL_USERDATA,*mtr)
  ProcedureReturn hwndreturn
EndProcedure 

Procedure GetMeterImage(id.l)
  *mr.Meter=GetWindowLong_(GadgetID(id),#GWL_USERDATA)
  bitmapreturn.l=*mr\PBimg
  ProcedureReturn bitmapreturn 
EndProcedure 



;- LED Gadget Graph
ProcedureDLL LEDgadget(number,x,Y,width,height,DisplayColor)
  *led.gauge =ReAllocateMemory(*led.gauge,SizeOf(gauge))
  *led\width=width
  *led\height=height
  *led\imageid=CreateImage(#PB_Any,*led\width,*led\height)
  StartDrawing(ImageOutput(*led\imageid))
  Box(0,0,*led\width,*led\height,#Black)
  ledheight=*led\height-20
  boxwidth=(*led\width-10-1)/2
  secondx= 6+boxwidth
  tickcount=0
  For a=0 To *led\height-20 Step 4
    tickcount=tickcount+1
    Box(5,a,boxwidth,3,$7F00)
    Box(secondx,a,boxwidth,3,$7F00)
  Next 
  *led\ticks=tickcount
  BackColor(RGB(0,0,0))
  FrontColor(RGB(0, $FF, 0))
  DrawText((*led\width/2)-10,*led\height-15,"0%")
  StopDrawing()
  StaticCtl.l=ImageGadget(number,x,Y,width,height,ImageID(*led\imageid),#PB_Image_Border)
  If number=#PB_Any
    *led\imagegad=StaticCtl
    SetWindowLong_(GadgetID(StaticCtl),#GWL_USERDATA,*led.gauge)
    ProcedureReturn *led\imagegad
  Else
    *led\imagegad=number 
    SetWindowLong_(GadgetID(number),#GWL_USERDATA,*led.gauge)
    ProcedureReturn StaticCtl
  EndIf 
EndProcedure

ProcedureDLL setLEDstate(led,percent)
  *led.gauge=GetWindowLong_(GadgetID(led),#GWL_USERDATA)
  tickcount=*led\ticks
  perc.f=100/*led\ticks
  percents.f=(percent/100)
  finalpercent.f=percents*tickcount
  stringpercent.s=StrF(finalpercent)
  Result.f = Round(finalpercent, 1)
  finalresult=*led\ticks-Result
  ledheight=*led\height-20
  boxwidth=(*led\width-10-1)/2
  secondx=6+boxwidth
  ImageID(*led\imageid)
  StartDrawing(ImageOutput(*led\imageid))
  tickcount=0
  For a=0 To *led\height-20 Step 4
    tickcount=tickcount+1
    If tickcount>=finalresult
      Box(5,a,boxwidth,3,$FF00)
      Box(secondx,a,boxwidth,3,$FF00)
    Else
      Box(5,a,boxwidth,3,$7F00)
      Box(secondx,a,boxwidth,3,$7F00)
    EndIf
  Next
  Box(0,*led\height-15,*led\width,15,#Black)
  BackColor(RGB(0,0,0))
  FrontColor(RGB(0, $FF, 0))
  DrawText((*led\width/2)-10,*led\height-15,Str(percent)+"%")
  StopDrawing()
  SetGadgetState(*led\imagegad,ImageID(*led\imageid))
EndProcedure


Procedure cpuproc()
  Repeat
  cpuuse.l=Int(CpuUsage())
  SendMessage_(GadgetID(themeter),#WM_UPDATEMETER,0,cpuuse)
  SendMessage_(GadgetID(nextmeter),#WM_UPDATEMETER,0,cpuuse)
  setLEDstate(10,cpuuse)
  Delay(100)
ForEver 
EndProcedure 

OpenWindow(0,0,0,770,460,"Meter Control",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
CreateGadgetList(WindowID(0))
themeter.l=MeterControl(#PB_Any,140,10,300,200)
nextmeter.l=MeterControl(#PB_Any,460,10,300,200)
LEDgadget(10,30,10,95,200,0)
TrackBarGadget(20,110,300,260,30,0,100)
ButtonGadget(21,160,350,140,20,"Save Meter Image")
CheckBoxGadget(30,210,220,120,20,"Suspend CPU Query")
theThread.l=CreateThread(@cpuproc(),0)
Repeat
  
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      If GetGadgetState(30)=1
        SendMessage_(GadgetID(themeter),#WM_UPDATEMETER,0,GetGadgetState(20))
        SendMessage_(GadgetID(nextmeter),#WM_UPDATEMETER,0,GetGadgetState(20))
      setLEDstate(10,GetGadgetState(20))
    EndIf 
    
      Select EventGadget()
        Case 21
          Pattern$ + "Bitmap (*.bmp)|*.bmp|" 
          Pattern = 0   
          filename.s=SaveFileRequester("Please Choose The File Name To Save", "", Pattern$, Pattern)
          If filename
            If GetExtensionPart(filename)<>"bmp"
              filename+".bmp"
            EndIf 
            SaveImage(GetMeterImage(themeter),filename,#PB_ImagePlugin_BMP)
          EndIf 
        Case 30
          If GetGadgetState(30)=1
            PauseThread(theThread)
          ElseIf GetGadgetState(30)=0
              ResumeThread(theThread)
            EndIf 
      EndSelect
    Case #PB_Event_CloseWindow
      ;KillThread(theThread)
      Quit=1
  EndSelect
Until Quit=1



Posted: Thu Nov 09, 2006 3:30 pm
by dige
yeah, localmotion34 wins!! That code rocks!

Posted: Thu Nov 09, 2006 4:35 pm
by localmotion34
Flawless Victory...

Posted: Thu Nov 09, 2006 5:51 pm
by Rescator
Very nice.
Btw. CpuUsage() is not a function. so the source won't compile "out of the box" here.

PS! change SendMessage to PostMessage, here I see around 10% cpu improvement (less used). (by using Post the main process/task can continue rather than wait to see if the Send succeeded)

Also, you might try to use SetGadgetData() rather than SetWindowLong_()
I'm not entirely sure (and have not tested) but I think Fred's code do not use SetWindowLong API call at all. (but internal memory/buffers) instead, so could be faster. ditto with GetWindowLong, try PB's own functions instead.
Question, doesn't PB use the GWL_USERDATA internally for other things on some gadgets? If so you could get a conflict. (can some one confirm this or not, I can't recall the change Fred did on gadget user data).

There is also CallWindowProc_(GetProp_(hwnd,"oldproc") that I think can be simplified to save some more cpu.

Love your LED meter btw! :)

Posted: Thu Nov 09, 2006 5:56 pm
by localmotion34
here is a version where you can change the foreground, background and line/box color on the fly. it uses custom messages sent to the window procedure of the meter, and changes the userdata values before the next update.

Code: Select all



Structure Meter
  PBimg.l
  width.l
  height.l
  offset.l
  values.l[1024]
  FGcolor.l
  BGcolor.l
  Linecolor.l
EndStructure

Structure gauge
  imagegad.l
  imageid.l
  width.l
  height.l
  imagehwnd.l
  precision.l
  ticks.l
  textgad.l
  texthwnd.l 
  state.l
  numstates.l
  FGcolor.l
  BGcolor.l
  Boxcolor.l
EndStructure

Global theThread.l ,themeter.l,nextmeter.l

#WM_UPDATEMETER	= #WM_USER+1500
#WM_SETFGCOLOR	= #WM_USER+1501
#WM_SETBGCOLOR	= #WM_USER+1502
#WM_SETLNCOLOR	= #WM_USER+1503
#WM_STATICREFRESH	    = #WM_USER+1504
#WM_METERCLEAR=#WM_USER+1505
#BGDefault=#Black
#FGdefault=$7F00
#LineDefault=$FF00
#BoxDefault=$FF00

;-Meter Control 
Procedure MeterProc(hwnd,msg,wParam,lParam)
  Select msg
    Case #WM_SETFGCOLOR
      *mr.Meter=GetWindowLong_(hwnd,#GWL_USERDATA)
      *mr\FGcolor=lParam
      SetWindowLong_(hwnd,#GWL_USERDATA,*mr)
    Case #WM_SETBGCOLOR
      *mr.Meter=GetWindowLong_(hwnd,#GWL_USERDATA)
      *mr\BGcolor=lParam
      SetWindowLong_(hwnd,#GWL_USERDATA,*mr)
    Case #WM_SETLNCOLOR
      *mr.Meter=GetWindowLong_(hwnd,#GWL_USERDATA)
      *mr\Linecolor=lParam
      SetWindowLong_(hwnd,#GWL_USERDATA,*mr)
    Case #WM_UPDATEMETER
      *mr.Meter=GetWindowLong_(hwnd,#GWL_USERDATA)
      If *mr\offset=10
        *mr\offset=0
      EndIf 
      For d=0 To *mr\width-1 
        *mr\values[d]=*mr\values[d+1] 
      Next  
      *mr\values[*mr\width-1]=lParam
      StartDrawing(ImageOutput(*mr\PBimg))
      Box(0,0,*mr\width,*mr\height,*mr\BGcolor)
      For a=0 To *mr\height Step 10
        LineXY(0,a,*mr\width,a,*mr\FGcolor)
      Next 
      For a=0 To *mr\width+*mr\offset Step 10
        LineXY(a-*mr\offset,0,a-*mr\offset,*mr\height,*mr\FGcolor)
      Next 
      For d=0 To *mr\width
        bottom.l=*mr\height
        thepercent.f=(*mr\values[d]/100)
        actualheight.l=Int(thepercent* *mr\height)
        Y1.l=bottom-actualheight
        thepercent.f=(*mr\values[d+1]/100)
        actualheight.l=Int(thepercent* *mr\height)
        Y2.l=bottom-actualheight
        LineXY(d+1,Y1,d+1,Y2,*mr\Linecolor)
      Next 
      *mr\offset+1
      StopDrawing()
      SetWindowLong_(hwnd,#GWL_USERDATA,*mr)
      SendMessage_(hwnd,#STM_SETIMAGE,#IMAGE_BITMAP,ImageID(*mr\PBimg))
  EndSelect 
  ProcedureReturn CallWindowProc_(GetProp_(hwnd,"oldproc"),hwnd,msg,wParam,lParam)
EndProcedure 


Procedure MeterControl(id.l,x,Y,width,height,FGcolor.l, BGcolor.l,LNcolor.l) 
  image=CreateImage(#PB_Any,width,height)
  StartDrawing(ImageOutput(image))
  Box(0,0,width,height,#Black)
  For a=0 To height Step 10
    LineXY(0,a,width,a,$7F00)
  Next 
  For a=0 To width Step 10
    LineXY(a,0,a,height,$7F00)
  Next 
  StopDrawing()
  imagegad.l=ImageGadget(id,x,Y,width,height,ImageID(image),#PB_Image_Border)
  setprop_(GadgetID(imagegad),"oldproc",SetWindowLong_(GadgetID(imagegad),#GWL_WNDPROC,@MeterProc()))
  If id=#PB_Any
    hwndreturn=imagegad
    hwnd=GadgetID(imagegad)
  Else
    hwndreturn=imagegad
    hwnd=imagegad
  EndIf 
  *mtr.Meter=AllocateMemory(SizeOf(Meter))
  *mtr\PBimg=image
  *mtr\width=width
  *mtr\height=height 
  *mtr\FGcolor=FGcolor
  *mtr\BGcolor=BGcolor
  *mtr\Linecolor=LNcolor
  SetWindowLong_(hwnd,#GWL_USERDATA,*mtr)
  ProcedureReturn hwndreturn
EndProcedure 

Procedure GetMeterImage(id.l)
  *mr.Meter=GetWindowLong_(GadgetID(id),#GWL_USERDATA)
  bitmapreturn.l=*mr\PBimg
  ProcedureReturn bitmapreturn 
EndProcedure 



;- LED Gadget Graph
ProcedureDLL LEDgadget(number,x,Y,width,height,FGcolor.l, BGcolor.l,Boxcolor.l)
  *led.gauge =ReAllocateMemory(*led.gauge,SizeOf(gauge))
  *led\width=width
  *led\height=height
  *led\FGcolor=FGcolor
  *led\BGcolor=BGcolor
  *led\Boxcolor=Boxcolor
  *led\imageid=CreateImage(#PB_Any,*led\width,*led\height)
  StartDrawing(ImageOutput(*led\imageid))
  Box(0,0,*led\width,*led\height,*led\BGcolor)
  ledheight=*led\height-20
  boxwidth=(*led\width-10-1)/2
  secondx= 6+boxwidth
  tickcount=0
  For a=0 To *led\height-20 Step 4
    tickcount=tickcount+1
    Box(5,a,boxwidth,3,*led\FGcolor)
    Box(secondx,a,boxwidth,3,*led\FGcolor)
  Next 
  *led\ticks=tickcount
  BackColor(*led\BGcolor)
  FrontColor(*led\Boxcolor)
  DrawText((*led\width/2)-10,*led\height-15,"0%")
  StopDrawing()
  StaticCtl.l=ImageGadget(number,x,Y,width,height,ImageID(*led\imageid),#PB_Image_Border)
  If number=#PB_Any
    *led\imagegad=StaticCtl
    SetWindowLong_(GadgetID(StaticCtl),#GWL_USERDATA,*led.gauge)
    ProcedureReturn *led\imagegad
  Else
    *led\imagegad=number 
    SetWindowLong_(GadgetID(number),#GWL_USERDATA,*led.gauge)
    ProcedureReturn StaticCtl
  EndIf 
EndProcedure

ProcedureDLL setLEDstate(led,percent)
  *led.gauge=GetWindowLong_(GadgetID(led),#GWL_USERDATA)
  tickcount=*led\ticks
  perc.f=100/*led\ticks
  percents.f=(percent/100)
  finalpercent.f=percents*tickcount
  stringpercent.s=StrF(finalpercent)
  Result.f = Round(finalpercent, 1)
  finalresult=*led\ticks-Result
  ledheight=*led\height-20
  boxwidth=(*led\width-10-1)/2
  secondx=6+boxwidth
  ImageID(*led\imageid)
  StartDrawing(ImageOutput(*led\imageid))
  tickcount=0
  Box(0,0,*led\width,*led\height,*led\BGcolor)
  For a=0 To *led\height-20 Step 4
    tickcount=tickcount+1
    If tickcount>=finalresult
      Box(5,a,boxwidth,3,*led\Boxcolor)
      Box(secondx,a,boxwidth,3,*led\Boxcolor)
    Else
      Box(5,a,boxwidth,3,*led\FGcolor)
      Box(secondx,a,boxwidth,3,*led\FGcolor)
    EndIf
  Next
  Box(0,*led\height-15,*led\width,15,*led\BGcolor)
  BackColor(*led\BGcolor)
  FrontColor(*led\Boxcolor)
  DrawText((*led\width/2)-10,*led\height-15,Str(percent)+"%")
  StopDrawing()
  SetGadgetState(*led\imagegad,ImageID(*led\imageid))
EndProcedure

Procedure SetLEDcolors(id,FGcolor.l, BGcolor.l,Boxcolor.l)
  *gg.gauge=GetWindowLong_(GadgetID(id),#GWL_USERDATA)
  If FGcolor=#PB_Ignore
  Else
    *gg\FGcolor=FGcolor
  EndIf 
  If BGcolor=#PB_Ignore
  Else
    *gg\BGcolor=BGcolor
  EndIf
  If Boxcolor=#PB_Ignore
  Else
    *gg\Boxcolor=Boxcolor
  EndIf
  SetWindowLong_(GadgetID(id),#GWL_USERDATA,*gg.gauge)
EndProcedure 

Procedure cpuproc()
  Repeat
  cpuuse.l=Int(CpuUsage())
  SendMessage_(GadgetID(themeter),#WM_UPDATEMETER,0,cpuuse)
  SendMessage_(GadgetID(nextmeter),#WM_UPDATEMETER,0,cpuuse)
  setLEDstate(10,cpuuse)
  Delay(100)
ForEver 
EndProcedure 

OpenWindow(0,0,0,770,460,"Meter Control",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) 
CreateGadgetList(WindowID(0))
themeter.l=MeterControl(#PB_Any,140,10,300,200,#FGdefault,#BGDefault,#LineDefault)
nextmeter.l=MeterControl(#PB_Any,460,10,300,200,#FGdefault,#BGDefault,#LineDefault)
LEDgadget(10,30,10,95,200,#FGdefault,#BGDefault,#BoxDefault)
TrackBarGadget(20,110,300,260,30,0,100)
ButtonGadget(21,160,350,140,20,"Save Meter Image")
ButtonGadget(22,160,370,140,20,"Change Foreground")
ButtonGadget(23,160,390,140,20,"Change Background")
ButtonGadget(24,160,410,140,20,"Change Line\Box Color")
CheckBoxGadget(30,210,220,120,20,"Suspend CPU Query")
theThread.l=CreateThread(@cpuproc(),0)
;SendMessage_(GadgetID(themeter), #WM_SETFGCOLOR,0,#Red)
Repeat
  
  Select WaitWindowEvent()
    Case #PB_Event_Gadget
      If GetGadgetState(30)=1
        SendMessage_(GadgetID(themeter),#WM_UPDATEMETER,0,GetGadgetState(20))
        SendMessage_(GadgetID(nextmeter),#WM_UPDATEMETER,0,GetGadgetState(20))
      setLEDstate(10,GetGadgetState(20))
    EndIf 
    
      Select EventGadget()
        Case 21
          Pattern$ + "Bitmap (*.bmp)|*.bmp|" 
          Pattern = 0   
          filename.s=SaveFileRequester("Please Choose The File Name To Save", "", Pattern$, Pattern)
          If filename
            If GetExtensionPart(filename)<>"bmp"
              filename+".bmp"
            EndIf 
            SaveImage(GetMeterImage(themeter),filename,#PB_ImagePlugin_BMP)
          EndIf 
        Case 22
          color=ColorRequester()
          If color
            SendMessage_(GadgetID(themeter), #WM_SETFGCOLOR,0,color)
            SendMessage_(GadgetID(nextmeter), #WM_SETFGCOLOR,0,color)
            SetLEDcolors(10,color,#PB_Ignore,#PB_Ignore)
          EndIf 
        Case 23
          color=ColorRequester()
          If color
            SendMessage_(GadgetID(themeter), #WM_SETBGCOLOR,0,color)
            SendMessage_(GadgetID(nextmeter), #WM_SETBGCOLOR,0,color)
            SetLEDcolors(10,#PB_Ignore,color,#PB_Ignore)
          EndIf 
        Case 24
          color=ColorRequester()
          If color
            SendMessage_(GadgetID(themeter), #WM_SETLNCOLOR,0,color)
            SendMessage_(GadgetID(nextmeter), #WM_SETLNCOLOR,0,color)
            SetLEDcolors(10,#PB_Ignore,#PB_Ignore,color)
          EndIf 
        Case 30
          If GetGadgetState(30)=1
            PauseThread(theThread)
          ElseIf GetGadgetState(30)=0
              ResumeThread(theThread)
            EndIf 
      EndSelect
    Case #PB_Event_CloseWindow
      ;KillThread(theThread)
      Quit=1
  EndSelect
Until Quit=1



Posted: Fri Nov 10, 2006 2:34 pm
by Rescator
localmotion34 wrote:Allright Rescator, you wanna play? heheh :twisted: :twisted:
Hell yeah, I love these friendly battles on these forums.
As the result is always some damn cool code other people can use ;)
thats a great idea to allow foreground and background colors, and i will include it in my structure.
If you loved that, check out my example below you are totally gonna love what I did with the linecolor changing. CPU use is pretty much the same as my previous example, which is much less than yours.
(I blame Windows and SendMessage, try PostMessage for the #WM_UPDATEMETER messages you send in your cpu proc, it should reduce cpu use)
as far as drawing the whole image over again, i mimicked this exactly from a PellesC source, which did it this exact way. i think you really have to redraw the whole image because the image is of a fixed size, and shifting the image to the left will leave a blank part to the right. it will have to be redrawn anyway.
I actually did some hacking to test this. First of all, PB sadly do not have any image shifting (could do it with sprites I guess or use BitBlit API or similar)
Secondly, cpu usage jumped up to almost twice as much (matching your codes speed)
However it was a interesting way I did it though.
What I did was shift the image to the left (leaving a black vertical line on the right)
Then I used Plot() to do the horizontal grid lines (one Plot per 10 pixels) and and for each 10 horizontal pixels I did a Line()

Sadly it was too much work to get anything worthy too post here.
The idea was interesting though as it would have gotten rid of the entire table/static array, and if done right it could have been very fast indeed.
(a challenge for some of you others out there maybe? :)
my intended use is to have additional notifications posted to the message loop like #wm_meterchanged, or #wm_meterreach_Max so i can track what is really going on.
If all that is within the same process (program) then use a global var or two as those would be threadsafe and you'd get rid of the entire message overhead.
However if you got the whole thing inside a dll then I'm a bit unsure,
although I'm sure a function call to pass info back and forth would be faster then as well compared to sending system messages.
That's just my opinion though :wink:

Code: Select all

EnableExplicit

;MeterGadget is a mix of a gadget and a image, a few procedures have been made to make
;gadget handling easier. In general a MeterGadget behaves almost like a normal ImageGadget.

;Otherwise normal gadget functions can be used (that works with ImageGadget)
;and obviously since it is a imagegadget it has the same gadget events returned as well.
;Tooltips can be set just like with any other ImageGadget.
;flags constants are the same as the flags constants used for ImageGadget like #PB_Image_Border

;IMPORTANT! SetGadgetData() MUST NOT be used with the MeterGadget,
;it's used for the structure pointers.
;Use SetMeterGadgetData() and GetMeterGadgetData() instead.


Structure MeterGadgetTable_struct
 point.l
 color.l
EndStructure

Structure MeterGadget_struct
 image.l
 imageid.l
 x.l
 y.l
 w.l
 h.l
 bgcolor.l
 fgcolor.l
 linecolor.l
 offset.l
 userdata.l
 flags.l
 *table.MeterGadgetTable_struct
EndStructure

;Create #Image and #Gadget etc.
Procedure.l MeterGadget(gadget.l,x.l,y.l,width.l,height.l,bgcolor.l,fgcolor.l,linecolor.l,flags.l=#Null)
 Protected *m.MeterGadget_struct,result.l=#Null,n.l,p.l=0,newgadget.l,*table
 If IsGadget(gadget)
  *m=GetGadgetData(gadget)
  If *m
   result=*m\image
  EndIf
 EndIf
 *m=AllocateMemory(SizeOf(MeterGadget_struct))
 If *m
  *m\flags=flags
  If *m\flags=#PB_Image_Border
   *m\w=width-2
   *m\h=height-2
  Else
   *m\w=width
   *m\h=height
  EndIf
  *m\table=AllocateMemory(SizeOf(MeterGadget_struct) * *m\w)
  If *m\table
   *m\x=x
   *m\y=y
   *m\bgcolor=bgcolor
   *m\fgcolor=fgcolor
   *m\linecolor=linecolor
   *m\image=CreateImage(#PB_Any,width,height,#PB_Image_DisplayFormat)
   If IsImage(*m\image)
    *m\imageid=ImageID(*m\image)
    If StartDrawing(ImageOutput(*m\image))
     Box(p,p,*m\w,*m\h,*m\bgcolor)
     For n=0 To *m\h Step 10
       LineXY(p,n,*m\w,n,*m\fgcolor)
     Next
     For n=0 To width Step 10
       LineXY(n,p,n,*m\h,*m\fgcolor)
     Next
     StopDrawing()
     result=ImageGadget(gadget,*m\x,*m\y,*m\w,*m\h,*m\imageid,flags)
    EndIf
   EndIf
   If gadget=#PB_Any
    newgadget=result
   Else
    newgadget=gadget
   EndIf
  EndIf
  If IsGadget(newgadget)
   SetGadgetData(newgadget,*m)
  Else
   If IsImage(*m\image)
    FreeImage(*m\image)
   EndIf
   If *m\table
    FreeMemory(*m\table)
   EndIf
   FreeMemory(*m)
  EndIf
 EndIf
 ProcedureReturn result
EndProcedure

;Use this instead of FreeGadget() to avoid memory leaks.
;Only needed if you need to free/remove a gadget.
;All resources are automatically freed at program end like normal PB gadgets though.
Procedure FreeMeterGadget(gadget.l)
 Protected *m.MeterGadget_struct
 If IsGadget(gadget)
  *m=GetGadgetData(gadget)
  FreeGadget(gadget)
  If *m
   If IsImage(*m\image)
    FreeImage(*m\image)
   EndIf
   FreeMemory(*m)
  EndIf
 EndIf
EndProcedure

;Use this instead of SetGadgetState()
Procedure SetMeterGadgetState(gadget.l,state.l)
 Protected *m.MeterGadget_struct,result.l,*table1.MeterGadgetTable_struct,*table2.MeterGadgetTable_struct
 Protected n.l,y1.l,y2.l,bottom.l,percent.f,h.l,p.l
 *m=GetGadgetData(gadget)
 If *m\offset=10
   *m\offset=0
 EndIf
 If *m\flags=#PB_Image_Border
  p=1
 Else
  p=0
 EndIf
 For n=0 To *m\w-1
  *table1=*m\table+(n*SizeOf(MeterGadgetTable_struct))
  *table2=*m\table+((n+1)*SizeOf(MeterGadgetTable_struct))
  *table1\point=*table2\point
  *table1\color=*table2\color
 Next
 *table2\point=state
 *table2\color=*m\linecolor
 If StartDrawing(ImageOutput(*m\image))
  Box(p,p,*m\w,*m\h,*m\bgcolor)
  For n=0 To *m\h Step 10
   LineXY(p,n,*m\w,n,*m\fgcolor)
  Next
  For n=0 To *m\w+*m\offset Step 10
   LineXY(n-*m\offset,p,n-*m\offset,*m\h,*m\fgcolor)
  Next
  For n=0 To *m\w
   *table1=*m\table+(n*SizeOf(MeterGadgetTable_struct))
   *table2=*m\table+((n+1)*SizeOf(MeterGadgetTable_struct))
   bottom=*m\h
   percent=(*table1\point/100.0)
   h=Int(percent * *m\h)
   y1=bottom-h
   percent=(*table2\point/100)
   h=Int(percent * *m\h)
   y2.l=bottom-h
   LineXY(n+1,y1,n+1,y2,*table2\color)
  Next
  *m\offset+1
  StopDrawing()
  SetGadgetState(gadget,*m\imageid)
 EndIf
EndProcedure

;Use this instead of GetGadgetState(). Not that usefull but may be handy to have.
Procedure.l GetMeterGadgetState(gadget.l)
 Protected *m.MeterGadget_struct
 *m=GetGadgetData(gadget)
 ProcedureReturn *m\offset
EndProcedure

;Use this instead of SetGadgetData().
Procedure SetMeterGadgetData(gadget.l,userdata.l)
 Protected *m.MeterGadget_struct
 *m=GetGadgetData(gadget)
 *m\userdata=userdata
EndProcedure

;Use this instead of GetGadgetData().
Procedure.l GetMeterGadgetData(gadget.l)
 Protected *m.MeterGadget_struct
 *m=GetGadgetData(gadget)
 ProcedureReturn *m\userdata
EndProcedure

;Use this to get #Image
Procedure.l GetMeterGadgetImage(gadget.l)
 Protected *m.MeterGadget_struct,result.l=#Null
 *m=GetGadgetData(gadget)
 ProcedureReturn *m\image
EndProcedure

;Use this to set gadget color
Procedure.l SetMeterGadgetColor(gadget.l,colortype.l,color.l)
 Protected *m.MeterGadget_struct,result.l=#Null
 *m=GetGadgetData(gadget)
 Select colortype
  Case #PB_Gadget_BackColor
   *m\bgcolor=color
  Case #PB_Gadget_FrontColor
   *m\fgcolor=color
  Case #PB_Gadget_LineColor
   *m\linecolor=color
 EndSelect
EndProcedure

;Use this to get gadget color
Procedure.l GetMeterGadgetColor(gadget.l,colortype.l)
 Protected *m.MeterGadget_struct,result.l=#Null
 *m=GetGadgetData(gadget)
 Select colortype
  Case #PB_Gadget_BackColor
   result=*m\bgcolor
  Case #PB_Gadget_FrontColor
   result=*m\fgcolor
  Case #PB_Gadget_LineColor
   result=*m\linecolor
 EndSelect
 ProcedureReturn result
EndProcedure


;******************************************************************************
;- Example of use

Define event.l,gadget.l,filename$,pattern$,patternpos.l,oldtime.l,newtime.l

Enumeration 1
 #Window
EndEnumeration

Enumeration 1
 #Meter1
 #Meter2
 #Meter3
 #Trackbar
 #Saveimage
 #Changecolor1
 #Changecolor2
 #Changecolor3
EndEnumeration

If OpenWindow(#Window,0,0,470,460,"Meter Control",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)=#False
 End
EndIf

If CreateGadgetList(WindowID(#Window))=#False
 End
EndIf

If MeterGadget(#Meter1,90,10,290,180,RGB($0,$0,$0),RGB($0,$7F,$0),RGB($0,$FF,$0))=#False
 End
EndIf

If MeterGadget(#Meter2,90,200,290,40,RGB($0,$0,$0),RGB($7F,$0,$0),RGB($FF,$FF,$0))=#False
 End
EndIf

If MeterGadget(#Meter3,90,240,290,40,RGB($0,$0,$0),RGB($0,$0,$7F),RGB($0,$FF,$FF))=#False
 End
EndIf

If TrackBarGadget(#Trackbar,110,300,260,30,0,100)=#False
 End
EndIf

If ButtonGadget(#Saveimage,160,350,140,20,"Save Meter 1 Image")=#False
 End
EndIf

If ButtonGadget(#Changecolor1,160,370,140,20,"Change Meter 1 Line Color")=#False
 End
EndIf

If ButtonGadget(#Changecolor2,160,390,140,20,"Change Meter 2 Back Color")=#False
 End
EndIf

If ButtonGadget(#Changecolor3,160,410,140,20,"Change Meter 2 Front Color")=#False
 End
EndIf


;Meter 1 only updates "manually" (by moving trackbar for example)
;some other form of userinput or info could be used to feed it as well.

;Meter 2 only updates when there is no events,
;and as the waitloop is set to 10ms this is the max update rate.

;Meter 3 updates only each 50ms, regardless of user input or not.
;However for this to work properly the waitloop need to be 50ms or lower.

oldtime=ElapsedMilliseconds()
Repeat
 newtime=ElapsedMilliseconds()
 If (newtime-oldtime)>49 ;if 50ms or higher then update Meter 3
  oldtime=newtime
  SetMeterGadgetState(#Meter3,GetGadgetState(#Trackbar))
 EndIf
 event=WaitWindowEvent(10)
 If event
  Select event
   Case #PB_Event_Gadget
    gadget=EventGadget()
    Select gadget
     Case #Trackbar ;User input, update meter 1.
      SetMeterGadgetState(#Meter1,GetGadgetState(#Trackbar))
     Case #Saveimage
      pattern$="Bitmap (*.bmp)|*.bmp|"
      patternpos=0
      filename$=SaveFileRequester("Save image as:","",pattern$,patternpos)
      If filename$
       If GetExtensionPart(filename$)<>"bmp"
        filename$+".bmp"
       EndIf
       SaveImage(GetMeterGadgetImage(#Meter1),filename$,#PB_ImagePlugin_BMP)
      EndIf
     Case #Changecolor1
      SetMeterGadgetColor(#Meter1,#PB_Gadget_LineColor,RGB(Random($FF),Random($FF),Random($FF)))
     Case #Changecolor2
      SetMeterGadgetColor(#Meter2,#PB_Gadget_BackColor,RGB(Random($FF),Random($FF),Random($FF)))
     Case #Changecolor3
      SetMeterGadgetColor(#Meter3,#PB_Gadget_FrontColor,RGB(Random($FF),Random($FF),Random($FF)))
    EndSelect
  EndSelect
 Else ;No event has happen for the last 10ms, Update meter 2.
  SetMeterGadgetState(#Meter2,GetGadgetState(#Trackbar))
 EndIf
Until event=#PB_Event_CloseWindow

End
I think I'll make this my last "improvement" on the code/idea,
however I'd love to see others improve these examples further obviously.

PS! I thought of another improvement, not gonna do it myself but it would be the "next step" I guess. multiple lines in a graph. This combined with my linecolor stuff would allow min, average, max, current lines in a single graph.

Posted: Sun Feb 03, 2008 9:01 am
by aaron
I know its an old thread, but just wanted to thank you guys for posting these examples codes. Exactly what the doctor ordered! :D

Posted: Sun Feb 03, 2008 4:12 pm
by Kwai chang caine
Yes it' a great code 8)

But i have a error at line 181

Code: Select all

cpuuse.l=Int(CpuUsage()) 
I have commented this line, and it's works, but i know it's no the solution :oops:

Posted: Sun Feb 03, 2008 8:27 pm
by localmotion34
Kwaï chang caïne wrote:Yes it' a great code 8)

But i have a error at line 181

Code: Select all

cpuuse.l=Int(CpuUsage()) 
I have commented this line, and it's works, but i know it's no the solution :oops:
CPUusage is part of the PBOSL user libraries. just download and install that library, and it should work fine.

Posted: Sun Feb 03, 2008 11:11 pm
by Kwai chang caine
Thanks a lot localmotion34 8)