Circle progress bar

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: Circle progress bar

02 Apr 2015, 14:08

Learning one wrote:FanaticGuru, I don't get such errors...
I imagine you do a #include <Gdip> in your script.

I typically don't do that. I generally just make sure I do a pToken := Gdip_Startup() before I start calling any other functions. After you call one library function all functions in the library are callable even if they do not follow the library naming convention.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Circle progress bar

02 Apr 2015, 14:15

But this is a doughnut progress! :morebeard: :lol:
How about a class for a wheel with wedges like in Chrome download?
User avatar
Learning one
Posts: 173
Joined: 04 Oct 2013, 13:59
Location: Croatia
Contact:

Re: Circle progress bar

02 Apr 2015, 16:23

Bruttosozialprodukt, OK ;)
FanaticGuru, yes I always use #Include LibFullPathHere.ahk in my scripts
Guest10, I'm not sure what do you have on mind... can you show me what do you imagine - how would progress bar loading look in such "Chrome's wheel with wedges" style?

toralf, I just tried to include WM_LBUTTONDOWN monitoring in the class itself, but I never did that before and it seems I don't know to do it :(
I put this in __New():

Code: Select all

if (this.UseClickThrough=0)	; so it's clickable - therefore enable click & drag and handle that via WM_LBUTTONDOWN() method
	OnMessage(0x201,  this["WM_LBUTTONDOWN"])
Now, if i make WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) method, i'll get error because it requires 5 parameters; (4 +1 hidden; this) and this is documented in OnMessage(): "Failure occurs when Function is known to require more than four parameters"

If I just make WM_LBUTTONDOWN() method (no params) I can't make use of it because this.hwnd returns blank value

Code: Select all

;class CircleProgressClass {	
	WM_LBUTTONDOWN() {
		MsgBox % this.hwnd	; returns blank value!
		if (this.hwnd = A_Gui) {
			PostMessage, 0xA1, 2
			KeyWait, LButton
			WinGetPos, x,y,,, % "ahk_id " this.hwnd
			this.x := x, this.y := y	; update coords			
		}
		;else
		;	ToolTip, Not CircleProgressClass gui ; that is not one of GUIs we want to monitor - do nothing
	}
;}
I could do something like OnMessage(0x201, Func("CircleProgressClass_WM_LBUTTONDOWN")) but I think that's the wrong approach...
Any advices? How to monitor WM_LBUTTONDOWN message in the class?

Edit: I asked for help here
Last edited by Learning one on 02 Apr 2015, 19:08, edited 3 times in total.
Guest10
Posts: 578
Joined: 01 Oct 2013, 02:50

Re: Circle progress bar

02 Apr 2015, 16:28

A small wheel with wedges appears in Chrome browser when I download something and it is a small progress indicator that appears on the lower-left corner of my Chrome book during downloads.
User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: Circle progress bar

02 Apr 2015, 22:08

Another Problem solved :)
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
DataLife
Posts: 445
Joined: 29 Sep 2013, 19:52

Re: Circle progress bar

15 Feb 2020, 01:47

Learning one wrote:
02 Apr 2015, 10:28
@Bruttosozialprodukt: lol :) 8-) As joedf suggested, I would like to put the following text in CircleProgressClass comments: "Credits: Bruttosozialprodukt, Learning one. This code is public domain." Is that OK with you?
fischgeek wrote:... make it move-able ...
No problem :)

Code: Select all

OnMessage(0x201, "WM_LBUTTONDOWN")
CircleProgress := new CircleProgressClass({UseClickThrough: 0})	; don't use click-through style so we can click and drag it
Loop, 100 {
	CircleProgress.Update(A_Index, "Drag me...`n`n" A_Index "%")
	Sleep, 150
}
return

WM_LBUTTONDOWN() {
	global CircleProgress
	PostMessage, 0xA1, 2
	KeyWait, LButton
	WinGetPos, x,y,,, % "ahk_id " CircleProgress.hwnd
	CircleProgress.x := x, CircleProgress.y := y	; update coords
}
I have tried for several hours to figure out how to get the final X and Y coordinates of the CircleProgress Gui after clicking and dragging it.
Also, after clicking on the Get Position button I can no longer click and drag the CircleProgress Gui.

Suggestions please? Below is a functioning sample script I wrote to post on the forum to show the issue. Of course you need Gdip_all to run this script.

Code: Select all

#Include gdip_all.ahk
OnMessage(0x201, "WM_LBUTTONDOWN")
IniRead,CurrentXpos,config.ini,GuiPosition,Xpos,100
IniRead,CurrentYpos,config.ini,GuiPosition,Ypos,100
Gui, add, button, gGetPosition,Get Position
Gui, show, autosize
pToken := Gdip_Startup()
CircleProgressDownloading := new CircleProgressClass({UseClickThrough: 0, x: CurrentXpos, y: CurrentYpos, BackgroundColor: "ff" "ff0000", BarColor: "aa" "c0c0c0", TextColor: "ff" "000000", TextStyle: "regular", BarThickness: 30, BarDiameter: 80}) 
SetTimer, StepsNotificationMessage, 13
return
WM_LBUTTONDOWN()
{
	global CircleProgress
	PostMessage, 0xA1, 2
	KeyWait, LButton
	WinGetPos, x,y,,, % "ahk_id " CircleProgress.hwnd
	CircleProgress.x := x, CircleProgress.y := y	; update coords
}
StepsNotificationMessage:
CompleteCircle++
CircleProgressDownloading.Update(CompleteCircle, "Done" )
if CompleteCircle > 99
 {
  SetTimer, StepsNotificationMessage, off
  Gdip_Shutdown(pToken)
 }
return

GetPosition:
;I need a way to get the x and y coordinates of the CircleProgress
MsgBox, X%NewXPos%`nY%NewYPos%
return

class CircleProgressClass {		; http://ahkscript.org/boards/viewtopic.php?p=41794#p41794
	; Credits: Bruttosozialprodukt, Learning one. This code is public domain.
	static Version := 1.04
	__New(Options="") {
        this.BarDiameter := (Options.HasKey("BarDiameter") = 1) ? Options.BarDiameter : 110
		this.BarThickness := (Options.HasKey("BarThickness") = 1) ? Options.BarThickness : 16
		this.BarColor := (Options.HasKey("BarColor") = 1) ? Options.BarColor : "dd228822"
		this.BackgroundColor := (Options.HasKey("BackgroundColor") = 1) ? Options.BackgroundColor : "ffffffff"
		this.TextColor := (Options.HasKey("TextColor") = 1) ? Options.TextColor : "ee000000"
		this.TextSize := (Options.HasKey("TextSize") = 1) ? Options.TextSize : 11
		this.TextRendering := (Options.HasKey("TextRendering") = 1) ? Options.TextRendering : 5
		this.TextFont := (Options.HasKey("TextFont") = 1) ? Options.TextFont : "Arial"
		this.TextStyle := (Options.HasKey("TextStyle") = 1) ? Options.TextStyle : ""									; you can use for example  "Bold Italic"
		this.X := (Options.HasKey("X") = 1) ? Options.X : Round(A_ScreenWidth/2-this.BarDiameter/2-this.BarThickness)	; centered is defualt
		this.Y := (Options.HasKey("Y") = 1) ? Options.Y : Round(A_ScreenHeight/2-this.BarDiameter/2-this.BarThickness)	; centered is defualt
		this.W := this.BarDiameter+this.BarThickness*2+2	; it's good to add 2 extra pixels
		this.UseClickThrough := (Options.HasKey("UseClickThrough") = 1) ? Options.UseClickThrough : 1					; 1 = use it, 0 = don't use it
		Gui, New, +Hwndhwnd
		Gui %hwnd%: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
		Gui %hwnd%: Show, NA

		;if (this.UseClickThrough = 1)
			;WinSet, ExStyle, +0x20, % "ahk_id " hwnd	; click through style
		
		hbm := CreateDIBSection(this.W, this.W), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
		pPen:=Gdip_CreatePen("0x" this.BarColor, this.BarThickness)
		if (pPen = 0) {	; GDI+ is not started up - start it up now and shut it down in __Delete() automatically.
			pToken := Gdip_Startup()
			pPen:=Gdip_CreatePen("0x" this.BarColor, this.BarThickness)	; call it again (with GDI+ started up now)
		}
		G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)
		
		if (this.BackgroundColor > 0)
			pBrush:=Gdip_BrushCreateSolid("0x" this.BackgroundColor)
			
		this.hwnd := hwnd, this.hdc := hdc, this.obm := obm, this.hbm := hbm, this.pPen := pPen, this.pBrush := pBrush, this.G := G, this.pToken := pToken
	}
	Update(Percent=0, Text="") {
		Gdip_GraphicsClear(this.G)		
		if (this.BackgroundColor > 0)
			Gdip_FillEllipse(this.G, this.pBrush, this.BarThickness+1, this.BarThickness+1, this.BarDiameter,this.BarDiameter)
		if (Percent>0)
			Gdip_DrawArc(this.G, this.pPen, Round(this.BarThickness/2)+1,  Round(this.BarThickness/2)+1, this.BarDiameter+this.BarThickness, this.BarDiameter+this.BarThickness, 270, Round(360/100*percent))
		if (Text!="") {
			Options := Trim("x1 y1 w" this.W-2 " h" this.W-2 " Center Vcenter r" this.TextRendering " s" this.TextSize " c" this.TextColor A_Space this.TextStyle)
			Gdip_TextToGraphics(this.G, Text, Options, this.TextFont)
		}
		;pControlPen:=Gdip_CreatePen("0xffff0000", 1), Gdip_DrawRectangle(this.G, pControlPen, 1, 1, this.W-2,this.W-2), Gdip_DeletePen(pControlPen)
		UpdateLayeredWindow(this.hwnd, this.hdc, this.X, this.Y, this.W, this.W)
	}
	Clear() {	; Just clears the graphics and updates layered window. Doesn't destroy object nor clear resources.
		Gdip_GraphicsClear(this.G)
		UpdateLayeredWindow(this.hwnd, this.hdc, this.X, this.Y, this.W, this.W)
	}
	__Delete() {
		Gdip_DeletePen(this.pPen)
		if (this.BackgroundColor > 0)
			Gdip_DeleteBrush(this.pBrush)
		Gdip_DeleteGraphics(this.G)
		SelectObject(this.hdc, this.obm)
		DeleteObject(this.hbm)
		DeleteDC(this.hdc)
		if (this.pToken != "") 	; GDI+ was obviously automatically started up in __New(), and therefore shut it down automatically now
			Gdip_Shutdown(this.pToken)
		hwnd := this.hwnd
		Gui %hwnd%: Destroy
	}
}
Check out my scripts. (MyIpChanger) (ClipBoard Manager) (SavePictureAs)
All my scripts are tested on Windows 10, AutoHotkey 32 bit Ansi unless otherwise stated.
User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: Circle progress bar

15 Feb 2020, 13:22

@DataLife

is this what you're going for?

Code: Select all

#SingleInstance,Force
#Include gdip_all.ahk

pToken := Gdip_Startup()
OnMessage(0x201, "WM_LBUTTONDOWN")
CurrentXpos:= 100
CurrentYpos:= 100
Gui, add, button, gGetPosition,Get Position
Gui, show, w300 h200

global CircleProgressDownloading := new CircleProgressClass({UseClickThrough: 0, x: CurrentXpos, y: CurrentYpos, BackgroundColor: "ff" "ff0000", BarColor: "aa" "c0c0c0", TextColor: "ff" "000000", TextStyle: "regular", BarThickness: 30, BarDiameter: 80}) 
SetTimer, StepsNotificationMessage, 13
return
*ESC::ExitApp
WM_LBUTTONDOWN()
{
	if(WinActive("ahk_id " CircleProgressDownloading.hwnd)){
		PostMessage, 0xA1, 2
		KeyWait, LButton
		WinGetPos, x,y,,, % "ahk_id " CircleProgressDownloading.hwnd
		CircleProgressDownloading.x := x, CircleProgressDownloading.y := y	; update coords
	}
}

StepsNotificationMessage:
CompleteCircle++
CircleProgressDownloading.Update(CompleteCircle, CompleteCircle )
if CompleteCircle > 99
 {
  SetTimer, StepsNotificationMessage, off
  CircleProgressDownloading.Update(CompleteCircle, "Done" )
  Gdip_Shutdown(pToken)
 }
return

GetPosition:
;I need a way to get the x and y coordinates of the CircleProgress
;~ MsgBox, X%NewXPos%`nY%NewYPos%
MsgBox, % CircleProgressDownloading.x

return

class CircleProgressClass {		; http://ahkscript.org/boards/viewtopic.php?p=41794#p41794
	; Credits: Bruttosozialprodukt, Learning one. This code is public domain.
	static Version := 1.04
	__New(Options="") {
        this.BarDiameter := (Options.HasKey("BarDiameter") = 1) ? Options.BarDiameter : 110
		this.BarThickness := (Options.HasKey("BarThickness") = 1) ? Options.BarThickness : 16
		this.BarColor := (Options.HasKey("BarColor") = 1) ? Options.BarColor : "dd228822"
		this.BackgroundColor := (Options.HasKey("BackgroundColor") = 1) ? Options.BackgroundColor : "ffffffff"
		this.TextColor := (Options.HasKey("TextColor") = 1) ? Options.TextColor : "ee000000"
		this.TextSize := (Options.HasKey("TextSize") = 1) ? Options.TextSize : 11
		this.TextRendering := (Options.HasKey("TextRendering") = 1) ? Options.TextRendering : 5
		this.TextFont := (Options.HasKey("TextFont") = 1) ? Options.TextFont : "Arial"
		this.TextStyle := (Options.HasKey("TextStyle") = 1) ? Options.TextStyle : ""									; you can use for example  "Bold Italic"
		this.X := (Options.HasKey("X") = 1) ? Options.X : Round(A_ScreenWidth/2-this.BarDiameter/2-this.BarThickness)	; centered is defualt
		this.Y := (Options.HasKey("Y") = 1) ? Options.Y : Round(A_ScreenHeight/2-this.BarDiameter/2-this.BarThickness)	; centered is defualt
		this.W := this.BarDiameter+this.BarThickness*2+2	; it's good to add 2 extra pixels
		this.UseClickThrough := (Options.HasKey("UseClickThrough") = 1) ? Options.UseClickThrough : 1					; 1 = use it, 0 = don't use it
		Gui, New, +Hwndhwnd
		Gui %hwnd%: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
		Gui %hwnd%: Show, NA

		;if (this.UseClickThrough = 1)
			;WinSet, ExStyle, +0x20, % "ahk_id " hwnd	; click through style
		
		hbm := CreateDIBSection(this.W, this.W), hdc := CreateCompatibleDC(), obm := SelectObject(hdc, hbm)
		pPen:=Gdip_CreatePen("0x" this.BarColor, this.BarThickness)
		if (pPen = 0) {	; GDI+ is not started up - start it up now and shut it down in __Delete() automatically.
			pToken := Gdip_Startup()
			pPen:=Gdip_CreatePen("0x" this.BarColor, this.BarThickness)	; call it again (with GDI+ started up now)
		}
		G := Gdip_GraphicsFromHDC(hdc), Gdip_SetSmoothingMode(G, 4)
		
		if (this.BackgroundColor > 0)
			pBrush:=Gdip_BrushCreateSolid("0x" this.BackgroundColor)
			
		this.hwnd := hwnd, this.hdc := hdc, this.obm := obm, this.hbm := hbm, this.pPen := pPen, this.pBrush := pBrush, this.G := G, this.pToken := pToken
	}
	Update(Percent=0, Text="") {
		Gdip_GraphicsClear(this.G)		
		if (this.BackgroundColor > 0)
			Gdip_FillEllipse(this.G, this.pBrush, this.BarThickness+1, this.BarThickness+1, this.BarDiameter,this.BarDiameter)
		if (Percent>0)
			Gdip_DrawArc(this.G, this.pPen, Round(this.BarThickness/2)+1,  Round(this.BarThickness/2)+1, this.BarDiameter+this.BarThickness, this.BarDiameter+this.BarThickness, 270, Round(360/100*percent))
		if (Text!="") {
			Options := Trim("x1 y1 w" this.W-2 " h" this.W-2 " Center Vcenter r" this.TextRendering " s" this.TextSize " c" this.TextColor A_Space this.TextStyle)
			Gdip_TextToGraphics(this.G, Text, Options, this.TextFont)
		}
		;pControlPen:=Gdip_CreatePen("0xffff0000", 1), Gdip_DrawRectangle(this.G, pControlPen, 1, 1, this.W-2,this.W-2), Gdip_DeletePen(pControlPen)
		UpdateLayeredWindow(this.hwnd, this.hdc, this.X, this.Y, this.W, this.W)
	}
	Clear() {	; Just clears the graphics and updates layered window. Doesn't destroy object nor clear resources.
		Gdip_GraphicsClear(this.G)
		UpdateLayeredWindow(this.hwnd, this.hdc, this.X, this.Y, this.W, this.W)
	}
	__Delete() {
		Gdip_DeletePen(this.pPen)
		if (this.BackgroundColor > 0)
			Gdip_DeleteBrush(this.pBrush)
		Gdip_DeleteGraphics(this.G)
		SelectObject(this.hdc, this.obm)
		DeleteObject(this.hbm)
		DeleteDC(this.hdc)
		if (this.pToken != "") 	; GDI+ was obviously automatically started up in __New(), and therefore shut it down automatically now
			Gdip_Shutdown(this.pToken)
		hwnd := this.hwnd
		Gui %hwnd%: Destroy
	}
}

***Edit***
I have altered the Update() method a bit so that you can move the window around while it is being redrawn.

Code: Select all

Update(Percent=0, Text="") {
		static ft := 1
		Gdip_GraphicsClear(this.G)		
		if (this.BackgroundColor > 0)
			Gdip_FillEllipse(this.G, this.pBrush, this.BarThickness+1, this.BarThickness+1, this.BarDiameter,this.BarDiameter)
		if (Percent>0)
			Gdip_DrawArc(this.G, this.pPen, Round(this.BarThickness/2)+1,  Round(this.BarThickness/2)+1, this.BarDiameter+this.BarThickness, this.BarDiameter+this.BarThickness, 270, Round(360/100*percent))
		if (Text!="") {
			Options := Trim("x1 y1 w" this.W-2 " h" this.W-2 " Center Vcenter r" this.TextRendering " s" this.TextSize " c" this.TextColor A_Space this.TextStyle)
			Gdip_TextToGraphics(this.G, Text, Options, this.TextFont)
		}
		;pControlPen:=Gdip_CreatePen("0xffff0000", 1), Gdip_DrawRectangle(this.G, pControlPen, 1, 1, this.W-2,this.W-2), Gdip_DeletePen(pControlPen)
		
		( !ft ) ? ( UpdateLayeredWindow( this.hwnd , this.hdc ) ) : ( UpdateLayeredWindow( this.hwnd, this.hdc , this.X, this.Y, this.W, this.W ) , ft := 0 )
	}
User avatar
DataLife
Posts: 445
Joined: 29 Sep 2013, 19:52

Re: Circle progress bar

15 Feb 2020, 14:42

@Hellbent
Perfect. Works great. Do you have a donation button? I would be happy to donate.
Check out my scripts. (MyIpChanger) (ClipBoard Manager) (SavePictureAs)
All my scripts are tested on Windows 10, AutoHotkey 32 bit Ansi unless otherwise stated.
User avatar
Hellbent
Posts: 2102
Joined: 23 Sep 2017, 13:34

Re: Circle progress bar

15 Feb 2020, 16:05

DataLife wrote:
15 Feb 2020, 14:42
@Hellbent
Perfect. Works great. Do you have a donation button? I would be happy to donate.
I do for yt, but it's really not necessary. It only took me around 10 mins to find / fix your problem, and alter the update method.

Thanks btw for digging up this thread, had never seen it before. It was nice to be able to finally be able to see a class that deals with similar subject matter to what often do. I have been writing classes for a little over 2 years, but because I taught myself from scratch (***Edit** Not true, nnnnik and a few others have provided some good insights along the way) without being able to compare and contrast with classes that others have written, I have always wondered if I was doing it in a somewhat normal way. Really, I just have been making it up as I go along. Now, with this thread I can see a apples to apples example. So at least now I know that if I'm wrong, I'm not the only one that does it wrong lol.

On a slightly off topic side note
Spoiler
.


Last thing. I don't know why it is that you need the coords of the window, but if it was just for redrawing. you can just replace the update method with the one I had posted under ***Edit*** and then there is no need to update the positions.
User avatar
DataLife
Posts: 445
Joined: 29 Sep 2013, 19:52

Re: Circle progress bar

15 Feb 2020, 17:28

@Hellbent
I have an autohotkey program called SavePictureAs.

I display the Circle Progress Bar when the picture has been downloaded. I was using a round Gui created with Winset, Region. I call the Gui the "Confirmation Message".
I allow the end user to use a Settings Gui to configure the "Confirmation Message".
The end user can change the colors, choose how long to display the "Confirmation Message" and choose the position on the screen to display it or not display it at all.

When the Settings Gui is open I display the "Confirmation Message" and the user can drag the Gui to the position they want it to display after a picture is saved from the internet.

I have it set to write the coordinates to an ini file when they release the mouse button.

I will look at your layer windows script now.
Check out my scripts. (MyIpChanger) (ClipBoard Manager) (SavePictureAs)
All my scripts are tested on Windows 10, AutoHotkey 32 bit Ansi unless otherwise stated.
User avatar
submeg
Posts: 326
Joined: 14 Apr 2017, 20:39
Contact:

Re: Circle progress bar

30 Apr 2020, 06:36

Before I go delving into this, just trying to get my head around it: Does it display in place of the regular download progress bar in a browser, or is it something else entirely?

Good to see Hellbent, he has recorded / created some great stuff!
____________________________________
Check out my site, submeg.com
Connect with me on LinkedIn
Courses on AutoHotkey :ugeek:
User avatar
boiler
Posts: 16768
Joined: 21 Dec 2014, 02:44

Re: Circle progress bar

30 Apr 2020, 08:02

submeg wrote:
30 Apr 2020, 06:36
Does it display in place of the regular download progress bar in a browser, or is it something else entirely?
It’s for you to use in your own scripts, not to change how other programs display their progress.
User avatar
submeg
Posts: 326
Joined: 14 Apr 2017, 20:39
Contact:

Re: Circle progress bar

30 Apr 2020, 19:42

Thanks for the explanation @boiler.
____________________________________
Check out my site, submeg.com
Connect with me on LinkedIn
Courses on AutoHotkey :ugeek:

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 133 guests