Page 1 of 1

MonitorCPU

Posted: Fri Mar 09, 2007 11:49 am
by netmaestro
Tiny dial that will monitor the CPU usage of the program that calls it. Includes test program.

http://www.greatlakescode.com/MonitorCPU.zip

The code is pretty much what I posted in the Windows forum, I just hung a dial on it. If it's popular, I was thinking it could use a couple little windows showing memory load and gui handles.

Posted: Sun Mar 11, 2007 6:55 am
by netmaestro
I've done quite a bit of work on this, several things are improved.

- Edges of the dial are alphablended now, looks much better

- Fixed a bug where the dll could occasionally cause an invalid memory access upon closing the library

- Dll finds the process handle internally now, no need to pass it

- .lib file is included for Import, makes for a cleaner call

- generally better quality code

Those who've downloaded this are recommended to get the new version as it's a better-quality piece of work than the first one.

Posted: Sun Mar 11, 2007 7:11 am
by rsts
Pretty slick.

Thanks for another fine program.

cheers

Posted: Sun Mar 11, 2007 8:37 am
by Fred
Looks very nice :)

Posted: Thu Feb 28, 2008 3:35 pm
by Poshu
Looking for this eventually, but your website is done. Could you (or anyone else, i'm not sectarian) re-upload it?

Posted: Thu Feb 28, 2008 3:45 pm
by netmaestro
Sorry about that, my site name is changed. Link fixed.

Posted: Thu Feb 28, 2008 4:07 pm
by Poshu
omfg SO FAST?
Thx a lot.

By the way, could you give us the source? i'm pretty interested.

Posted: Thu Feb 28, 2008 4:58 pm
by netmaestro
http://www.greatlakescode.com/cpubase.png
http://www.greatlakescode.com/cpudial.png
http://www.greatlakescode.com/frogs.gif

Code: Select all

;============================================================
; Program:            MonitorCPU.dll
; Author:             Lloyd Gallant (netmaestro)
; Date:               March 11, 2007
; Target OS:          Microsoft Windows 2000/XP/Vista
; Target Compiler:    PureBasic 4.0 and later
; License:            Free, unrestricted, no warranty 
;============================================================

Prototype GdiplusStartup( *token, *input, mode ) 
Prototype GdipCreateBitmapFromStream(stream.ISTREAM, *image)
Prototype GdipCreateFromHDC( hdc, *gfx) 
Prototype GdipRotateWorldTransform( *gfx, angle.f, mode)
Prototype GdipResetWorldTransform( *gfx)
Prototype GdipTranslateWorldTransform( *gfx, wmidf.f, hmidf.f, mode)
Prototype GdipDrawImageRectI( *gfx, *image, x, y, Width, Height ) 
Prototype GdipDeleteGraphics( *gfx ) 
Prototype GdipDisposeImage( *image ) 
Prototype GdiplusShutdown( *token ) 

ProcedureDLL AttachProcess(instance)
  Structure StreamObject
    block.l
    *bits
   stream.ISTREAM
  EndStructure
  Structure frog
    imagenum.l
    duration.l
  EndStructure
  Global s1.StreamObject, s2.StreamObject, s3.StreamObject
  Global *token, *base, *second, lib, main, back, size = 90
  Global gCurrentUsage.d, imgbase, imgfinal, imgfrogs, watch, tid
  Global font = LoadFont(0, "Arial", 6), *frogs, aboutthread
  Global lib = OpenLibrary(#PB_Any, "gdiplus.dll")
  Global Dim frogpics.frog(4)
  Global mutex = CreateMutex()
  CompilerIf Defined(GdiplusStartupInput, #PB_Structure) = 0
    Structure GdiplusStartupInput 
      GdiPlusVersion.l 
      *DebugEventCallback.febug_Event
      SuppressBackgroundThread.l 
      SuppressExternalCodecs.l 
    EndStructure 
  CompilerEndIf  
  
  Global GdiplusStartup.GdiplusStartup                           = GetFunction( lib, "GdiplusStartup" )          
  Global GdipCreateBitmapFromStream.GdipCreateBitmapFromStream   = GetFunction( lib, "GdipCreateBitmapFromStream") 
  Global GdipCreateFromHDC.GdipCreateFromHDC                     = GetFunction( lib, "GdipCreateFromHDC" )      
  Global GdipDrawImageRectI.GdipDrawImageRectI                   = GetFunction( lib, "GdipDrawImageRectI" )      
  Global GdipRotateWorldTransform.GdipRotateWorldTransform       = GetFunction( lib, "GdipRotateWorldTransform" )      
  Global GdipTranslateWorldTransform.GdipTranslateWorldTransform = GetFunction( lib, "GdipTranslateWorldTransform" )      
  Global GdipResetWorldTransform.GdipResetWorldTransform         = GetFunction( lib, "GdipResetWorldTransform" ) 
  Global GdipDeleteGraphics.GdipDeleteGraphics                   = GetFunction( lib, "GdipDeleteGraphics" )      
  Global GdipDisposeImage.GdipDisposeImage                       = GetFunction( lib, "GdipDisposeImage" )        
  Global GdiplusShutdown.GdiplusShutdown                         = GetFunction( lib, "GdiplusShutdown" )  
  
EndProcedure

Procedure CreateBase()
  imgbase = CreateImage(#PB_Any, size, size, 32)
  hDC = StartDrawing(ImageOutput(imgbase))
    GdipCreateFromHDC( hdc, @*gfx)
    GdipDrawImageRectI( *gfx, *base, 0, 0, size, size)
  StopDrawing()
  GdipDeleteGraphics( *gfx)
  If IsImage(imgbase)
    ProcedureReturn 1
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure LoadImages()

  ; Load Base Image
  Length = ?baseend-?base
  s1\block = GlobalAlloc_(#GHND, Length)
  s1\bits = GlobalLock_(s1\block)
  CopyMemory(?base, s1\bits, Length)
  If CreateStreamOnHGlobal_(s1\bits, 0, @s1\stream) = #S_OK
    GdipCreateBitmapFromStream( s1\stream , @*base)
  Else
    ProcedureReturn 0
  EndIf

 ; Load Pointer Image
  Length = ?pointerend-?pointer
  s2\block = GlobalAlloc_(#GHND, Length)
  s2\bits = GlobalLock_(s2\block) 
  CopyMemory(?pointer, s2\bits, Length)
  If CreateStreamOnHGlobal_(s2\bits, 0, @s2\stream) = #S_OK
    GdipCreateBitmapFromStream( s2\stream , @*second)
  Else
    ProcedureReturn 0
  EndIf
  
 ; Load Frogs Image
  Length = ?frogend-?frog
  s3\block = GlobalAlloc_(#GHND, Length)
  s3\bits = GlobalLock_(s3\block) 
  CopyMemory(?frog, s3\bits, Length)
  If CreateStreamOnHGlobal_(s3\bits, 0, @s3\stream) = #S_OK
    GdipCreateBitmapFromStream( s3\stream , @*frogs)
  Else
    ProcedureReturn 0
  EndIf
  
  imgfrogs = CreateImage(#PB_Any, 328, 89, 24)
  hDC = StartDrawing(ImageOutput(imgfrogs))
    GdipCreateFromHDC( hdc, @*gfx)
    GdipDrawImageRectI( *gfx, *frogs, 0, 0, 328, 89)
  StopDrawing()
  GdipDeleteGraphics( *gfx)  
  
  For i=0 To 246 Step 82
    frogpics((i+82)/82)\imagenum = GrabImage(imgfrogs,#PB_Any,i,0,82,89)
  Next
  frogpics(1)\duration = 2000
  frogpics(2)\duration = 100
  frogpics(3)\duration = 2000
  frogpics(4)\duration = 100
  
  DataSection
  base: IncludeBinary "cpubase.png" 
  baseend:
  pointer: IncludeBinary "cpudial.png"
  pointerend:
  frog: IncludeBinary "frogs.gif"
  frogend:
EndDataSection
  
  ProcedureReturn 1
EndProcedure  

Procedure WatchCPU(proc_handle)
  Dim stack.f(5)
  
  creation.FILETIME 
  exit.FILETIME 
  kernel.FILETIME 
  user.FILETIME 
  
  sysinfo.SYSTEM_INFO 
  GetSystemInfo_(@sysinfo) 
  numprocs = sysinfo\dwNumberOfProcessors 

  GetProcessTimes_(proc_handle,@creation,@exit,@kernel,@user) 
  oldkernel=kernel\dwlowdatetime 
  olduser=user\dwlowdatetime 
  Delay(200)    
  
  angle.f = (gCurrentUsage * 270)/100
  
  Repeat
    GetProcessTimes_(proc_handle,@creation,@exit,@kernel,@user) 
    stack(5)=stack(4):stack(4)=stack(3):stack(3)=stack(2):stack(2)=stack(1)
    stack(1) = ((((user\dwlowdatetime-olduser)+(kernel\dwlowdatetime-oldkernel))/200)/100)/numprocs 
    If stack(2)<>0 And stack(3)<>0 And stack(4)<>0 And stack(5)<>0
      gCurrentUsage.d = (stack(1)+stack(2)+stack(3)+stack(4)+stack(5))/5
    Else
      gCurrentUsage.d = stack(1)
    EndIf
    olduser=user\dwlowdatetime 
    oldkernel=kernel\dwlowdatetime    
    Delay (200)       
  ForEver
EndProcedure

Procedure UpdatePointer(angle.f)
  wmidf.f = size/2
  hmidf.f = size/2
  wmid.l = size/2
  hmid.l = size/2  
  If angle = 0.0 Or angle = 90.0 Or angle = 180 Or angle = 270
    angle+0.001
  EndIf
  LockMutex(mutex)
  hdc=StartDrawing(ImageOutput(imgfinal))
    GdipCreateFromHDC( hdc, @*gfx)
    GdipRotateWorldTransform( *gfx, angle, 1)
    GdipTranslateWorldTransform( *gfx, wmidf, hmidf, 1)
    GdipDrawImageRectI( *gfx, *second, -wmid, -hmid, size, size)
    GdipResetWorldTransform( *gfx)
    DrawingFont(font)
    DrawText(37,66,StrD(gCurrentUsage,1),#White,0)
  StopDrawing()
  UnlockMutex(mutex)
  GdipDeleteGraphics( *gfx)
EndProcedure

Procedure Hack(hwnd, msg, wparam, lparam)
  result = #PB_ProcessPureBasicEvents
  If hwnd = WindowID(main)
    If msg = #WM_MOVING
      *loc.RECT = lparam
      MoveWindow_(WindowID(back), *loc\left+34, *loc\top+66, 24, 10, #True)
    EndIf
  EndIf
  ProcedureReturn result
EndProcedure

Procedure btnproc(hwnd,msg,wparam,lparam)
  oldproc = GetProp_(hwnd, "oldproc")
  If msg = #WM_SETFOCUS
    ProcedureReturn 0
  EndIf
  If msg = #WM_NCDESTROY
    RemoveProp_(hwnd, "oldproc")
  EndIf
  ProcedureReturn CallWindowProc_(oldproc,hwnd,msg,wparam,lparam)
EndProcedure

Procedure AboutBox(void)
  font_local = LoadFont(#PB_Any, "Arial", 11)
  backimg = CreateImage(#PB_Any,240,250,32)
  LockMutex(mutex)
  StartDrawing(ImageOutput(backimg))
    Box(0,0,240,250,#White)
    DrawingFont(FontID(font_local))
    DrawText(26,35, "MonitorCPU.dll by netmaestro",0,#White)
    DrawText(60,65, "All rights reserved",0,#White)
    Box(0,0,240,25,RGB(0,0,200))
    DrawingMode(#PB_2DDrawing_Outlined)
    Box(0,0,240,250,0)
  StopDrawing()
  UnlockMutex(mutex)
  If WindowX(main)>GetSystemMetrics_(#SM_CXSCREEN)/2
    left = WindowX(main)-245
  Else
    left = WindowX(main)+95
  EndIf

  about = OpenWindow(#PB_Any, left,WindowY(main)-90, 240,250,"About MonitorCPU",#PB_Window_BorderLess)
  If WindowY(about)<0
    MoveWindow_(WindowID(about),left,0,240,250,1)
  EndIf
  If WindowY(about)>GetSystemMetrics_(#SM_CYSCREEN)-250
    MoveWindow_(WindowID(about),left,GetSystemMetrics_(#SM_CYSCREEN)-250,240,250,1)
  EndIf
  
  CreateGadgetList(WindowID(about))
  img0 = ImageGadget(#PB_Any,0,0,0,0,ImageID(backimg))
  DisableGadget(img0,1)
  StickyWindow(about,1)
  SetWindowLong_(GadgetID(img0),#GWL_STYLE, GetWindowLong_(GadgetID(img0),#GWL_STYLE)|#WS_CLIPSIBLINGS)
  img = ImageGadget(#PB_Any, 79,100,82,89,ImageID(frogpics(1)\imagenum))
  btn = ButtonGadget(#PB_Any, 90,210,60,20,"OK")
  SetWindowLong_(GadgetID(btn),#GWL_STYLE,GetWindowLong_(GadgetID(btn),#GWL_STYLE)|#BS_FLAT)
  oldproc = SetWindowLong_(GadgetID(btn),#GWL_WNDPROC,@btnproc())
  SetProp_(GadgetID(btn), "oldproc", oldproc)
  
  start = ElapsedMilliseconds()
  curpic = 1 
  quit=0
  InvalidateRect_(WindowID(about),0,1)
  Repeat
    ev=WaitWindowEvent(20)
    If ev = #PB_Event_Gadget
      If EventGadget() = btn
        quit=1
      EndIf
    EndIf  
    If ev = #WM_LBUTTONDOWN
      If WindowMouseY(about)<=25
        SendMessage_(WindowID(about),#WM_NCLBUTTONDOWN,#HTCAPTION,0)
      EndIf
    EndIf
    If ElapsedMilliseconds()-start >= frogpics(curpic)\duration
      curpic+1:If curpic>4:curpic=1:EndIf ; roll to the next frame
      SetGadgetState(img, ImageID(frogpics(curpic)\imagenum))
      start = ElapsedMilliseconds()
    EndIf
    
  Until quit
  CloseWindow(about)
EndProcedure

Procedure TimerPulse(a)
    back = OpenWindow(#PB_Any,0,0,24,10,"",#PB_Window_BorderLess|#PB_Window_Invisible)
    main = OpenWindow(#PB_Any,100,GetSystemMetrics_(#SM_CYSCREEN)-170,90,90,"",#PB_Window_BorderLess|#PB_Window_Invisible, WindowID(back))
    SetWindowLong_(WindowID(main), #GWL_EXSTYLE, GetWindowLong_(main, #GWL_EXSTYLE) | #WS_EX_LAYERED | #WS_EX_TOOLWINDOW)
    SetWindowLong_(WindowID(back), #GWL_EXSTYLE, GetWindowLong_(back, #GWL_EXSTYLE) | #WS_EX_TOOLWINDOW)
    SetWindowCallback(@Hack(), main)
    SetWindowColor(back, #Black)
    StickyWindow(back,1)
    StickyWindow(main,1)
    HideWindow(main,0)
    HideWindow(back,0)
    GetWindowRect_(WindowID(main),@wr.RECT)
    SendMessage_(WindowID(main),#WM_MOVING,0,@wr)
    
  Repeat
    angle.f = (gCurrentUsage * 270)/100
    GrabImage(imgbase,imgfinal,0,0,size,size)
  
    UpdatePointer(angle)
    LockMutex(mutex)
    hDC = StartDrawing(ImageOutput(imgfinal)) 
      sz.SIZE
      sz\cx = ImageWidth(imgfinal)
      sz\cy = ImageHeight(imgfinal)
      ContextOffset.POINT 
      BlendMode.BLENDFUNCTION 
      BlendMode\SourceConstantAlpha = 255 
      BlendMode\AlphaFormat = 1
      UpdateLayeredWindow_(WindowID(main), 0, 0, @sz, hDC, @ContextOffset, 0, @BlendMode, 2)
    StopDrawing() 
    UnlockMutex(mutex)
    ev = WaitWindowEvent(10)

    If ev = #WM_LBUTTONDOWN
      SendMessage_(WindowID(main), #WM_NCLBUTTONDOWN, #HTCAPTION, 0)
    EndIf
    If ev = #WM_RBUTTONDOWN
      If Not IsThread(aboutthread)
        aboutthread = CreateThread(@AboutBox(),0)
      EndIf
    EndIf    
  ForEver
EndProcedure

Procedure InitGDIPlus()
  input.GdiplusStartupInput
  input\GdiPlusVersion = 1
  GdiplusStartup( @*token, @input, #Null)
EndProcedure

ProcedureDLL MonitorCPU()
  proc_handle = OpenProcess_(#PROCESS_QUERY_INFORMATION, #False, GetCurrentProcessId_())  

  If lib = 0
    MessageRequester("Error","Required component gdiplus.dll is not found. Please install it and retry    ", #MB_ICONERROR)
    ProcedureReturn 0
  EndIf
  InitGDIPlus()
  If *token
    If Loadimages()
      If CreateBase()
        watch = CreateThread(@WatchCPU(), proc_handle)
        tid = CreateThread(@TimerPulse(),0)
        If tid
          ProcedureReturn 1
        Else
          ProcedureReturn 0
        EndIf
      Else
        ProcedureReturn 0
      EndIf
    Else
      ProcedureReturn 0
    EndIf
  Else
    ProcedureReturn 0
  EndIf
EndProcedure

ProcedureDLL DetachProcess(Instance)
  KillThread(watch)
  KillThread(tid)
  WaitThread(tid,500)
  s1\stream\Release()
  s2\stream\Release()
  s3\stream\Release()
  GlobalUnlock_(s1\bits)
  GlobalFree_(s1\block)
  GlobalUnlock_(s2\bits)
  GlobalFree_(s2\block)    
  GlobalUnlock_(s3\bits)
  GlobalFree_(s3\block)    
  CloseLibrary(lib)
EndProcedure

Posted: Thu Feb 28, 2008 5:24 pm
by Poshu
Thx again (wow! longer than expected, let's investigate!)

Posted: Thu Feb 28, 2008 5:55 pm
by Dare
Hup.

Missed this all those months ago!

Thank you very much sir! Especially for the frog legs! :D

Posted: Thu Feb 28, 2008 6:50 pm
by Num3
Someone stole Vista CPU meter graphics :lol: :lol: :lol:

Posted: Thu Feb 28, 2008 7:01 pm
by netmaestro
It's their own fault, they left it sitting there on the screen... :D

Posted: Fri Feb 29, 2008 12:53 am
by Dare
:D