Calculating the ( Angles / Points ) // DRAW ARROW Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Calculating the ( Angles / Points ) // DRAW ARROW

26 Jun 2021, 19:53

This should be a rather simple question for those that can remember this math, unfortunately I don't :oops:

I need to calculate for an isosceles triangle (sides A and B are twice as long as side C )
, and an equilateral triangle ( A, B, and C are the same length)

Points 1 and 2 provide the vector. Point 3 is some small distance from point 2 along the same vector.


Points 1 and 2 can be any vector!!! (Direction)

Some sample code:

Code: Select all


	;**************************************************************************************************************************
	;**************************************************************************************************************************
	;**************************************************************************************************************************
	; These are the points of the triangle 
	;	     3       4       5
	;****( "100,50|150,100|50,100|" )*****
	
	Gdip_FillPolygon( G , Brush , "100,50|150,100|50,100|" )
	
	;Example Vector points for the equilateral triangle
	
	; Point_1 := { X: 100 , Y: 330 }
	; Point_2 := { X: 100 , Y: 90 }
	
	;Point_3 := { X: 100 , Y: 50 }
	
	 Gdip_DrawLine( G , Pen , Point_1.X , Point_1.Y , Point_2.X , Point_2.Y )
	
	;Not really needed
	 ;Gdip_DrawLine( G , Pen , Point_2.X , Point_2.Y , Point_3.X , Point_3.Y )
	
	;**************************************************************************************************************************
	;**************************************************************************************************************************
	;**************************************************************************************************************************


Code: Select all

HB_BITMAP_MAKER(){
	;Bitmap Created Using: HB Bitmap Maker
	pBitmap := Gdip_CreateBitmap( 200 , 500 ) , G := Gdip_GraphicsFromImage( pBitmap ) , Gdip_SetSmoothingMode( G , 2 )
	
	
	;**************************************************************************************************************************
	;**************************************************************************************************************************
	;**************************************************************************************************************************
	; These are the points of the triangle 
	
	;****( "100,50|150,100|50,100|" )*****
	
	Brush := Gdip_BrushCreateSolid( "0xFF3399FF" ) , Gdip_FillPolygon( G , Brush , "100,50|150,100|50,100|" ) , Gdip_DeleteBrush( Brush )
	
	;Example Vector points for the equilateral triangle
	
	; Point 1 := { X: 100 , Y: 330 }
	; Point 2 := { X: 100 , Y: 90 }
	
	;Point3 := { X: 100 , Y: 50 }
	
	Pen := Gdip_CreatePen( "0xFFff0000" , 5 ) , Gdip_DrawLine( G , Pen , 100 , 330 , 100 , 90 ) , Gdip_DeletePen( Pen )
	
	
	Pen := Gdip_CreatePen( "0xFFff00ff" , 5 ) , Gdip_DrawLine( G , Pen , 100 , 50 , 100 , 90 ) , Gdip_DeletePen( Pen )
	
	;**************************************************************************************************************************
	;**************************************************************************************************************************
	;**************************************************************************************************************************
	
	
	
	
	
	
	
	
	
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_FillEllipse( G , Brush , 94 , 44 , 10 , 10 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_FillEllipse( G , Brush , 94 , 83 , 10 , 10 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_FillEllipse( G , Brush , 94 , 323 , 10 , 10 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_FillEllipse( G , Brush , 46 , 93 , 10 , 10 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_FillEllipse( G , Brush , 142 , 93 , 10 , 10 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_TextToGraphics( G , "Points ( x, y)" , "s18 Center vCenter Bold c" Brush " x40 y430" , "Segoe ui" , 70 , 50 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_FillEllipse( G , Brush , 11 , 443 , 20 , 20 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFffff00" ) , Gdip_TextToGraphics( G , "1" , "s18 Center vCenter Bold c" Brush " x100 y310" , "Segoe ui" , 50 , 50 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFffff00" ) , Gdip_TextToGraphics( G , "2" , "s18 Center vCenter Bold c" Brush " x89 y63" , "Segoe ui" , 50 , 50 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFffff00" ) , Gdip_TextToGraphics( G , "3" , "s18 Center vCenter Bold c" Brush " x89 y13" , "Segoe ui" , 50 , 50 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFffff00" ) , Gdip_TextToGraphics( G , "4" , "s18 Center vCenter Bold c" Brush " x139 y83" , "Segoe ui" , 50 , 50 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFffff00" ) , Gdip_TextToGraphics( G , "5" , "s18 Center vCenter Bold c" Brush " x9 y83" , "Segoe ui" , 50 , 50 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF00ff00" ) , Gdip_TextToGraphics( G , "A" , "s18 Center vCenter Bold c" Brush " x29 y33" , "Segoe ui" , 50 , 50 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF00ff00" ) , Gdip_TextToGraphics( G , "B" , "s18 Center vCenter Bold c" Brush " x119 y33" , "Segoe ui" , 50 , 50 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF00ff00" ) , Gdip_TextToGraphics( G , "C" , "s18 Center vCenter Bold c" Brush " x89 y93" , "Segoe ui" , 50 , 50 ) , Gdip_DeleteBrush( Brush )
	Gdip_DeleteGraphics( G )
	return pBitmap
}
20210626202207.png
20210626202207.png (8.15 KiB) Viewed 4279 times

Thanks
HB.


***Feel free to use creative liberty with the arrow design*** (4 or more points). It just needs to be scalable (small - big)
Last edited by Hellbent on 27 Jun 2021, 20:32, edited 1 time in total.
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points )

26 Jun 2021, 21:10

Just got back from a little evening stroll and I think that I may have thought out the solution. So for the time being I'll put a pause on this request.
That way if I'm wrong I get to embarrass myself twice. Once for asking and the second time for thinking that I had figured out and have to ask for help again :D

If I have my solution I'll post it once I have the time to write some code for it.
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points )

27 Jun 2021, 20:29

Close to a solution. Just haven't worked out one little detail...

Requesting help with this last bit.

I need to get it to adjust the vectors to the "StartVector" value and not just ( 0, 0 )

Code: Select all

StartVector := New HB_Vector(240,40)  ;<<<<<<<<<<<<<<<<<<<-----------------------------------
vector1 := New HB_Vector( 500  , 230  )

Vector2 := New HB_Vector(Vector1.Y,Vector1.X*-1)
Vector4 := New HB_Vector(Vector1.Y*-1,Vector1.X)
Vector3 := New HB_Vector(Vector1.X,Vector1.Y)

Vector3.SetMag(vector1.Mag() * .9)
Vector2.SetMag(10)
Vector4.SetMag(10)
Vector2.Add(Vector3)
Vector4.Add(Vector3)


Class HB_Vector	{
	__New(x:=0,y:=0){
		This.X:=x
		This.Y:=y
	}
	Add(Other_HB_Vector){
		This.X+=Other_HB_Vector.X
		This.Y+=Other_HB_Vector.Y
	}
	Sub(Other_HB_Vector){
		This.X-=Other_HB_Vector.X
		This.Y-=Other_HB_Vector.Y
	}
	mag(){
		return Sqrt(This.X*This.X + This.Y*This.Y)
	}
	magsq(){
		return This.Mag()**2
	}	
	setMag(in1){
		m:=This.Mag()
		This.X := This.X * in1/m
		This.Y := This.Y * in1/m
		return This
	}
	mult(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X*=In1.X 
			This.Y*=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X*=In1
			This.Y*=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X*=In1*In2.X
			This.Y*=In1*In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X*=In1.X*In2.X
			This.Y*=In1.Y*In2.Y
		}	
	}
	div(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X/=In1.X 
			This.Y/=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X/=In1
			This.Y/=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X/=In1/In2.X
			This.Y/=In1/In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X/=In1.X/In2.X
			This.Y/=In1.Y/In2.Y
		}	
	}
	dist(in1){
		return Sqrt(((This.X-In1.X)**2) + ((This.Y-In1.Y)**2))
	}
	dot(in1){
		return (This.X*in1.X)+(This.Y*In1.Y)
	}
	cross(in1){
		return This.X*In1.Y-This.Y*In1.X
	}
	Norm(){
		m:=This.Mag()
		This.X/=m
		This.Y/=m
	}
}
Full test code.

Code: Select all

;***************************************************************************************************
#Include <My Altered Gdip Lib>   ;Replace with your path
;***************************************************************************************************

#SingleInstance force
SetBatchLines, -1
GDIP_Startup()

Gui1 := New PopUpWindow( { WindowName: "1" , WindowOptions: " -DPIScale +AlwaysOnTop " , WindowSmoothing: 2 , X: 500 , Y: 300 , W: 700 , H: 300 } )
Gui1.PaintBackground( color := "0x6600ff00" )

StartVector := New HB_Vector(240,40)  ;<<<<<<<<<<<<<<<<<<<-----------------------------------
vector1 := New HB_Vector( 500  , 230  )

Vector2 := New HB_Vector(Vector1.Y,Vector1.X*-1)
Vector4 := New HB_Vector(Vector1.Y*-1,Vector1.X)
Vector3 := New HB_Vector(Vector1.X,Vector1.Y)

Vector3.SetMag(vector1.Mag() * .9)
Vector2.SetMag(10)
Vector4.SetMag(10)
Vector2.Add(Vector3)
Vector4.Add(Vector3)


Pen := Gdip_CreatePen( "0xff000000" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, 0, 0, Vector1.X , Vector1.Y ) , Gdip_DeletePen( Pen )  ;Needs Start vector
Pen := Gdip_CreatePen( "0xffff0000" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Vector3.X, Vector3.Y, Vector2.X , Vector2.Y ) , Gdip_DeletePen( Pen )
Pen := Gdip_CreatePen( "0xffff00ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Vector3.X, Vector3.Y, Vector4.X , Vector4.Y ) , Gdip_DeletePen( Pen )
Pen := Gdip_CreatePen( "0xffff33ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Vector2.X, Vector2.Y, Vector1.X , Vector1.Y ) , Gdip_DeletePen( Pen )
Pen := Gdip_CreatePen( "0xffff33ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Vector4.X, Vector4.Y, Vector1.X , Vector1.Y ) , Gdip_DeletePen( Pen )


Gui1.UpdateWindow()
Gui1.ShowWindow( MyWindowTitle := "" )

return
*ESC::ExitApp
Numpad3::
	PopUpWindow.Helper()
	return

;************************************************************************************************************************
;************************************************************************************************************************
;************************************************************************************************************************
;Backup
;~ vector1 := New HB_Vector( 300 , 455 )
;~ vector1.Norm()
;~ Vector2 := New HB_Vector(Vector1.Y,Vector1.X*-1)
;~ Vector4 := New HB_Vector(Vector1.Y*-1,Vector1.X)
;~ Vector1.SetMag(110)
;~ Vector3 := New HB_Vector(Vector1.X,Vector1.Y)
;~ Vector3.SetMag(110*.9)
;~ Vector2.SetMag(20)
;~ Vector4.SetMag(20)
;~ Vector2.Add(Vector3)
;~ Vector4.Add(Vector3)
;~ Pen := Gdip_CreatePen( "0xff000000" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, 0, 0, Vector1.X , Vector1.Y ) , Gdip_DeletePen( Pen )
;~ Pen := Gdip_CreatePen( "0xffff0000" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Vector3.X, Vector3.Y, Vector2.X , Vector2.Y ) , Gdip_DeletePen( Pen )
;~ Pen := Gdip_CreatePen( "0xffff00ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Vector3.X, Vector3.Y, Vector4.X , Vector4.Y ) , Gdip_DeletePen( Pen )
;~ Pen := Gdip_CreatePen( "0xffff33ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Vector2.X, Vector2.Y, Vector1.X , Vector1.Y ) , Gdip_DeletePen( Pen )
;~ Pen := Gdip_CreatePen( "0xffff33ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Vector4.X, Vector4.Y, Vector1.X , Vector1.Y ) , Gdip_DeletePen( Pen )

;************************************************************************************************************************
;************************************************************************************************************************
;************************************************************************************************************************



Class HB_Vector	{
	__New(x:=0,y:=0){
		This.X:=x
		This.Y:=y
	}
	Add(Other_HB_Vector){
		This.X+=Other_HB_Vector.X
		This.Y+=Other_HB_Vector.Y
	}
	Sub(Other_HB_Vector){
		This.X-=Other_HB_Vector.X
		This.Y-=Other_HB_Vector.Y
	}
	mag(){
		return Sqrt(This.X*This.X + This.Y*This.Y)
	}
	magsq(){
		return This.Mag()**2
	}	
	setMag(in1){
		m:=This.Mag()
		This.X := This.X * in1/m
		This.Y := This.Y * in1/m
		return This
	}
	mult(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X*=In1.X 
			This.Y*=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X*=In1
			This.Y*=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X*=In1*In2.X
			This.Y*=In1*In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X*=In1.X*In2.X
			This.Y*=In1.Y*In2.Y
		}	
	}
	div(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X/=In1.X 
			This.Y/=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X/=In1
			This.Y/=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X/=In1/In2.X
			This.Y/=In1/In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X/=In1.X/In2.X
			This.Y/=In1.Y/In2.Y
		}	
	}
	dist(in1){
		return Sqrt(((This.X-In1.X)**2) + ((This.Y-In1.Y)**2))
	}
	dot(in1){
		return (This.X*in1.X)+(This.Y*In1.Y)
	}
	cross(in1){
		return This.X*In1.Y-This.Y*In1.X
	}
	Norm(){
		m:=This.Mag()
		This.X/=m
		This.Y/=m
	}
}
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
class PopUpWindow	{
	;Class By: Hellbent
	;Apr 2021
	static Index := 0 , Windows := [] , Handles := [] , HelpHandles := [] , HelperEditHwnd
	__New( obj := "" ){
		This._SetDefaults()
		if( isObject( obj ) )
			This.SetWindowProperties( obj )
		This._SetupWindowGraphics()
	}
	_SetDefaults(){
		PopUpWindow.Index++
		This.WindowName := "HBLayeredWindow" PopUpWindow.Index
		This.WindowSmoothing := 2
		This.WindowOptions := " -DPIScale +AlwaysOnTop "
		This.X := 10
		This.Y := 10
		This.W := 10
		This.H := 10
	}
	PaintBackground( color := "0xFF000000" ){
		Brush := Gdip_BrushCreateSolid( color ) 
		Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W + 2 , This.H + 2 ) 
		Gdip_DeleteBrush( Brush )
	}
	_SetupWindowGraphics(){
		This.Hwnd := This._CreateGUI()
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.WindowSmoothing )
		PopUpWindow.Handles[ This.Hwnd ] := PopUpWindow.Index
		PopUpWindow.Windows[ PopUpWindow.Index ] := This
	}
	SetWindowProperties( obj ){
		local k , v 
		for k , v in obj
			if( k != "hwnd" )
				This[k] := v
	}
	ShowWindow( Title := "" ){
		Gui , % This.WindowName ":Show", % "x" This.X " y" This.Y " w" This.W " h" This.H " NA", % Title
	}
	HideWindow(){
		Gui , % This.WindowName ":Hide",
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	ClearWindow(){
		Gdip_GraphicsClear( This.G )
	}
	DrawBitmap( pBitmap , obj , dispose := 1 ){
		Gdip_DrawImage( This.G , pBitmap , obj.X , obj.Y , obj.W , obj.H )
		if( dispose )
			Gdip_DisposeImage( pBitmap )
	}
	DeleteWindow(){
		Gui, % This.Window ":Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		hwnd := This.Hwnd
		for k, v in PopUpWindow.Windows[ Hwnd ]
			This[k] := ""
		PopUpWindow.Windows[ Hwnd ] := ""
	}
	_CreateGUI(){
		local hwnd
		Gui , % This.WindowName ":New" , % " +E0x80000 hwndhwnd -Caption  " This.WindowOptions
		return hwnd
	}
	Helper(){
		local List := ["New Window","SetWindowProperties","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow"]
		local hwnd, bd
		
		
		Gui, HBLWHelperGui:New, +AlwaysOnTop 
		Gui, HBLWHelperGui:Color, 62666a, 24282c
		Gui, HBLWHelperGui:Font, cWhite s10 , Segoe UI
		Gui, HBLWHelperGui:Margin, 5 , 5
		
		Gui, HBLWHelperGui:Add, Edit, xm ym w200 r1 Center hwndHwnd, Gui1
		PopUpWindow.HelperEditHwnd := Hwnd
		Gui, HBLWHelperGui:Margin, 5 , 1
		Loop, % List.Length()	{
		
			Gui, HBLWHelperGui:Add, Button, xm wp h23 -Theme hwndhwnd, % List[ A_Index ]
			PopUpWindow.HelpHandles[hwnd] := List[ A_Index ]
			bd := PopUpWindow._ClipIt.Bind( PopUpWindow )
			GuiControl , HBLWHelperGui: +G , % Hwnd , % bd
		}
		
		Gui, HBLWHelperGui:Show, 
		
	}
	_ClipIt(){
		local List := ["New Window","SetWindowProperties","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow"]
		local Output , FQ := 400
		GuiControlGet, Output , HBLWHelperGui: , % PopUpWindow.HelperEditHwnd
		Switch A_GuiControl
		{
			case List[1]:
				Clipboard := Output " := New PopUpWindow( { WindowName: ""1"" , WindowOptions: "" -DPIScale +AlwaysOnTop "" , WindowSmoothing: 2 , X: ""Center"" , Y: ""Center"" , W: 100 , H: 100 } )"
				loop 2
					SoundBeep, FQ
				return
			case List[2]:
				Clipboard := Output ".SetWindowProperties( { X: """" , Y: """" , W: """" , H: """" } )"
				loop 2
					SoundBeep, FQ
				return
			case List[3]:
				Clipboard := Output ".ShowWindow( MyWindowTitle := """" )"
				loop 2
					SoundBeep, FQ
				return
			case List[4]:
				Clipboard := Output ".HideWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[5]:
				Clipboard := Output ".UpdateWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[6]:
				Clipboard := Output ".ClearWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[7]:
				Clipboard := Output ".DrawBitmap( pBitmap := """" , { X: """" , Y: """" , W: """" , H: """" } , dispose := 1 )"
				loop 2
					SoundBeep, FQ
				return
			case List[8]:
				Clipboard := Output ".PaintBackground( color := ""0xFF000000"" )"
				loop 2
					SoundBeep, FQ
				return
			case List[9]:
				Clipboard := Output ".DeleteWindow()"
				loop 2
					SoundBeep, FQ
				return
			Default:
				ToolTip, Looks like a new case needs to be added
				return
			
		}
	}
}
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

27 Jun 2021, 21:33

I have done a bit of code cleanup and added some comments.

Code: Select all

;***************************************************************************************************
#Include <My Altered Gdip Lib>   ;Replace with your path
;***************************************************************************************************

#SingleInstance force
SetBatchLines, -1
;**************************************************************************************************************************************************************************
;Window setup
GDIP_Startup() ;Loads the gdi+ lib.
Gui1 := New PopUpWindow( { WindowName: "1" , WindowOptions: " -DPIScale +AlwaysOnTop " , WindowSmoothing: 2 , X: 500 , Y: 300 , W: 700 , H: 300 } ) ;Creates a layered window to draw to.
Gui1.PaintBackground( color := "0x6600ff00" ) ;Paints the background of the layered window
;**************************************************************************************************************************************************************************
;Math stuff
Start := New HB_Vector(0,0) ;The starting point of the arrow

End := New HB_Vector(250, 130) ;The ending point of the arrow

EndCopy := New HB_Vector( End.X , End.Y ) ;Make a copy of the end vector

EndCopy.SetMag( End.Mag() * 0.9 ) ;Set the end copy to 90% of the end vector

Arm1 := New HB_Vector( End.Y , End.X * -1 ) ;Rotate the end vector 90 deg
Arm2 := New HB_Vector( End.Y * -1 , End.X ) ;Rotate the end vector -90 deg

Arm1.SetMag( 20 ) ;shortens arm 1 
Arm2.SetMag( 20 ) ;shortens arm 2 

Arm1.Add(EndCopy) ;Add the end copy to arm 1
Arm2.Add(EndCopy) ;Add the end copy to arm 2

;**************************************************************************************************************************************************************************
;Drawing to the window stuff

Pen := Gdip_CreatePen( "0xff000000" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Start.X , Start.Y , End.X , End.Y ) , Gdip_DeletePen( Pen )  ;Draw from starting position to ending position
Pen := Gdip_CreatePen( "0xffff0000" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, EndCopy.X, EndCopy.Y, Arm1.X , Arm1.Y ) , Gdip_DeletePen( Pen ) ;Draw from Endcopy (short distance from the end) to the first arrow arm
Pen := Gdip_CreatePen( "0xffff00ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, EndCopy.X, EndCopy.Y, Arm2.X , Arm2.Y ) , Gdip_DeletePen( Pen ) ;Draw from Endcopy (short distance from the end) to the second arrow arm
Pen := Gdip_CreatePen( "0xffff33ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Arm1.X, Arm1.Y, End.X , End.Y ) , Gdip_DeletePen( Pen ) ;Draw from arm 1 to the end point
Pen := Gdip_CreatePen( "0xffff33ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Arm2.X, Arm2.Y, End.X , End.Y ) , Gdip_DeletePen( Pen ) ;Draw from arm 2 to the end point
Gui1.UpdateWindow()
Gui1.ShowWindow()
;**************************************************************************************************************************************************************************
return
*ESC::ExitApp
Numpad3::
	PopUpWindow.Helper() ;Shows a list of functions that are in the "PopUpWindow" Layered Window Class
	return

;************************************************************************************************************************
;************************************************************************************************************************
;************************************************************************************************************************
;Backup
;__________________________
;~ ;Math stuff
;~ Start := New HB_Vector(0,0) ;The starting point of the arrow
;~ End := New HB_Vector(250, 130) ;The ending point of the arrow
;~ EndCopy := New HB_Vector( End.X , End.Y ) ;Make a copy of the end vector
;~ EndCopy.SetMag(End.Mag() * 0.9 ) ;Set the end copy to 90% of the end vector
;~ Arm1 := New HB_Vector( End.Y , End.X * -1 ) ;Rotate the end vector 90 deg
;~ Arm2 := New HB_Vector( End.Y * -1 , End.X ) ;Rotate the end vector -90 deg
;~ ;**************************************************************************************************************************************************************************
;~ ;Drawing to the window stuff
;~ Pen := Gdip_CreatePen( "0xff000000" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Start.X , Start.Y , End.X , End.Y ) , Gdip_DeletePen( Pen )  ;Draw from starting position to ending position
;~ Pen := Gdip_CreatePen( "0xffff0000" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, EndCopy.X, EndCopy.Y, Arm1.X , Arm1.Y ) , Gdip_DeletePen( Pen ) ;Draw from Endcopy (short distance from the end) to the first arrow arm
;~ Pen := Gdip_CreatePen( "0xffff00ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, EndCopy.X, EndCopy.Y, Arm2.X , Arm2.Y ) , Gdip_DeletePen( Pen ) ;Draw from Endcopy (short distance from the end) to the second arrow arm
;~ Pen := Gdip_CreatePen( "0xffff33ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Arm1.X, Arm1.Y, End.X , End.Y ) , Gdip_DeletePen( Pen ) ;Draw from arm 1 to the end point
;~ Pen := Gdip_CreatePen( "0xffff33ff" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Arm2.X, Arm2.Y, End.X , End.Y ) , Gdip_DeletePen( Pen ) ;Draw from arm 2 to the end point
;************************************************************************************************************************
;************************************************************************************************************************
;************************************************************************************************************************
;Vector Class
Class HB_Vector	{
	__New(x:=0,y:=0){
		This.X:=x
		This.Y:=y
	}
	Add(Other_HB_Vector){
		This.X+=Other_HB_Vector.X
		This.Y+=Other_HB_Vector.Y
	}
	Sub(Other_HB_Vector){
		This.X-=Other_HB_Vector.X
		This.Y-=Other_HB_Vector.Y
	}
	mag(){
		return Sqrt(This.X*This.X + This.Y*This.Y)
	}
	magsq(){
		return This.Mag()**2
	}	
	setMag(in1){
		m:=This.Mag()
		This.X := This.X * in1/m
		This.Y := This.Y * in1/m
		return This
	}
	mult(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X*=In1.X 
			This.Y*=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X*=In1
			This.Y*=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X*=In1*In2.X
			This.Y*=In1*In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X*=In1.X*In2.X
			This.Y*=In1.Y*In2.Y
		}	
	}
	div(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X/=In1.X 
			This.Y/=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X/=In1
			This.Y/=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X/=In1/In2.X
			This.Y/=In1/In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X/=In1.X/In2.X
			This.Y/=In1.Y/In2.Y
		}	
	}
	dist(in1){
		return Sqrt(((This.X-In1.X)**2) + ((This.Y-In1.Y)**2))
	}
	dot(in1){
		return (This.X*in1.X)+(This.Y*In1.Y)
	}
	cross(in1){
		return This.X*In1.Y-This.Y*In1.X
	}
	Norm(){
		m:=This.Mag()
		This.X/=m
		This.Y/=m
	}
}
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
;Layered Window Class
class PopUpWindow	{
	;Class By: Hellbent
	;Apr 2021
	static Index := 0 , Windows := [] , Handles := [] , HelpHandles := [] , HelperEditHwnd
	__New( obj := "" ){
		This._SetDefaults()
		if( isObject( obj ) )
			This.SetWindowProperties( obj )
		This._SetupWindowGraphics()
	}
	_SetDefaults(){
		PopUpWindow.Index++
		This.WindowName := "HBLayeredWindow" PopUpWindow.Index
		This.WindowSmoothing := 2
		This.WindowOptions := " -DPIScale +AlwaysOnTop "
		This.X := 10
		This.Y := 10
		This.W := 10
		This.H := 10
	}
	PaintBackground( color := "0xFF000000" ){
		Brush := Gdip_BrushCreateSolid( color ) 
		Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W + 2 , This.H + 2 ) 
		Gdip_DeleteBrush( Brush )
	}
	_SetupWindowGraphics(){
		This.Hwnd := This._CreateGUI()
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.WindowSmoothing )
		PopUpWindow.Handles[ This.Hwnd ] := PopUpWindow.Index
		PopUpWindow.Windows[ PopUpWindow.Index ] := This
	}
	SetWindowProperties( obj ){
		local k , v 
		for k , v in obj
			if( k != "hwnd" )
				This[k] := v
	}
	ShowWindow( Title := "" ){
		Gui , % This.WindowName ":Show", % "x" This.X " y" This.Y " w" This.W " h" This.H " NA", % Title
	}
	HideWindow(){
		Gui , % This.WindowName ":Hide",
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	ClearWindow(){
		Gdip_GraphicsClear( This.G )
	}
	DrawBitmap( pBitmap , obj , dispose := 1 ){
		Gdip_DrawImage( This.G , pBitmap , obj.X , obj.Y , obj.W , obj.H )
		if( dispose )
			Gdip_DisposeImage( pBitmap )
	}
	DeleteWindow(){
		Gui, % This.Window ":Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		hwnd := This.Hwnd
		for k, v in PopUpWindow.Windows[ Hwnd ]
			This[k] := ""
		PopUpWindow.Windows[ Hwnd ] := ""
	}
	_CreateGUI(){
		local hwnd
		Gui , % This.WindowName ":New" , % " +E0x80000 hwndhwnd -Caption  " This.WindowOptions
		return hwnd
	}
	Helper(){
		local List := ["New Window","SetWindowProperties","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow"]
		local hwnd, bd
		
		
		Gui, HBLWHelperGui:New, +AlwaysOnTop 
		Gui, HBLWHelperGui:Color, 62666a, 24282c
		Gui, HBLWHelperGui:Font, cWhite s10 , Segoe UI
		Gui, HBLWHelperGui:Margin, 5 , 5
		
		Gui, HBLWHelperGui:Add, Edit, xm ym w200 r1 Center hwndHwnd, Gui1
		PopUpWindow.HelperEditHwnd := Hwnd
		Gui, HBLWHelperGui:Margin, 5 , 1
		Loop, % List.Length()	{
		
			Gui, HBLWHelperGui:Add, Button, xm wp h23 -Theme hwndhwnd, % List[ A_Index ]
			PopUpWindow.HelpHandles[hwnd] := List[ A_Index ]
			bd := PopUpWindow._ClipIt.Bind( PopUpWindow )
			GuiControl , HBLWHelperGui: +G , % Hwnd , % bd
		}
		
		Gui, HBLWHelperGui:Show, 
		
	}
	_ClipIt(){
		local List := ["New Window","SetWindowProperties","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow"]
		local Output , FQ := 400
		GuiControlGet, Output , HBLWHelperGui: , % PopUpWindow.HelperEditHwnd
		Switch A_GuiControl
		{
			case List[1]:
				Clipboard := Output " := New PopUpWindow( { WindowName: ""1"" , WindowOptions: "" -DPIScale +AlwaysOnTop "" , WindowSmoothing: 2 , X: ""Center"" , Y: ""Center"" , W: 100 , H: 100 } )"
				loop 2
					SoundBeep, FQ
				return
			case List[2]:
				Clipboard := Output ".SetWindowProperties( { X: """" , Y: """" , W: """" , H: """" } )"
				loop 2
					SoundBeep, FQ
				return
			case List[3]:
				Clipboard := Output ".ShowWindow( MyWindowTitle := """" )"
				loop 2
					SoundBeep, FQ
				return
			case List[4]:
				Clipboard := Output ".HideWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[5]:
				Clipboard := Output ".UpdateWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[6]:
				Clipboard := Output ".ClearWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[7]:
				Clipboard := Output ".DrawBitmap( pBitmap := """" , { X: """" , Y: """" , W: """" , H: """" } , dispose := 1 )"
				loop 2
					SoundBeep, FQ
				return
			case List[8]:
				Clipboard := Output ".PaintBackground( color := ""0xFF000000"" )"
				loop 2
					SoundBeep, FQ
				return
			case List[9]:
				Clipboard := Output ".DeleteWindow()"
				loop 2
					SoundBeep, FQ
				return
			Default:
				ToolTip, Looks like a new case needs to be added
				return
			
		}
	}
}
;**************************************************************************************************************************************************************************
;**************************************************************************************************************************************************************************
;**************************************************************************************************************************************************************************
20210627223315.png
20210627223315.png (5.24 KiB) Viewed 4227 times
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

27 Jun 2021, 23:07

Got it worked out.

Here is the functioning arrow. I still need to tweak the design to look the way I want, but that should be easy now.

Code: Select all

;***************************************************************************************************
#Include <My Altered Gdip Lib>   ;Replace with your path
;***************************************************************************************************
#SingleInstance force
SetBatchLines, -1
CoordMode, Mouse, Client
;**************************************************************************************************************************************************************************
;Window setup
GDIP_Startup() ;Loads the gdi+ lib.
global Gui1 := New PopUpWindow( { WindowName: "1" , WindowOptions: " -DPIScale +AlwaysOnTop " , WindowSmoothing: 2 , X: 500 , Y: 300 , W: 700 , H: 300 } ) ;Creates a layered window to draw to.
Gui, 1:Show
;**************************************************************************************************************************************************************************
SetTimer, ArrowFunction, 30
return
GuiContextMenu:
*ESC::ExitApp

Numpad3::
	PopUpWindow.Helper() ;Shows a list of functions that are in the "PopUpWindow" Layered Window Class
	return

ArrowFunction(){
	static index := 0 , sx := 50 , sy := 50
	if(!Mod(++Index,50))
		sx := Random(0,700), sy := Random(0,300)
	Start := New HB_Vector(sx,sy)
	MouseGetPos,x,y
	End := New HB_Vector(x, y)
	EndCopy := New HB_Vector( End.X - Start.X , End.Y - Start.Y ) 
	EndCopy.Norm()
	Arrow := New HB_Vector( ( EndCopy.Y * - 1 ) - EndCopy.X , ( EndCopy.X - EndCopy.Y ) )
	Arrow.SetMag(15)
	Arm1 := New HB_Vector( End.X + Arrow.X , End.Y + Arrow.Y )
	Arm2 := New HB_Vector( End.X - Arrow.Y , End.Y + Arrow.X )
	Gui1.ClearWindow()
	Gui1.PaintBackground( color := "0x6600ff00" )
	Pen := Gdip_CreatePen( "0xff000000" , 3 ) , Gdip_DrawLine( Gui1.G , Pen, Start.X , Start.Y , End.X  , End.Y ) , Gdip_DeletePen( Pen )  
	Brush := Gdip_BrushCreateSolid( "0xFFFF0000" ) , Gdip_FillPolygon( Gui1.G , Brush , Arm1.X "," Arm1.Y  "|" Arm2.X  "," Arm2.Y  "|" End.X  "," End.Y  "|" Arm1.X "," Arm1.Y  ) , Gdip_DeleteBrush( Brush )
	Gui1.UpdateWindow()
}

random(Min, Max){
	Random, out, Min, Max
	return out
}
;Vector Class
Class HB_Vector	{
	__New(x:=0,y:=0){
		This.X:=x
		This.Y:=y
	}
	Add(Other_HB_Vector){
		This.X+=Other_HB_Vector.X
		This.Y+=Other_HB_Vector.Y
	}
	Sub(Other_HB_Vector){
		This.X-=Other_HB_Vector.X
		This.Y-=Other_HB_Vector.Y
	}
	mag(){
		return Sqrt(This.X*This.X + This.Y*This.Y)
	}
	magsq(){
		return This.Mag()**2
	}	
	setMag(in1){
		m:=This.Mag()
		This.X := This.X * in1/m
		This.Y := This.Y * in1/m
		return This
	}
	mult(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X*=In1.X 
			This.Y*=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X*=In1
			This.Y*=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X*=In1*In2.X
			This.Y*=In1*In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X*=In1.X*In2.X
			This.Y*=In1.Y*In2.Y
		}	
	}
	div(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X/=In1.X 
			This.Y/=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X/=In1
			This.Y/=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X/=In1/In2.X
			This.Y/=In1/In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X/=In1.X/In2.X
			This.Y/=In1.Y/In2.Y
		}	
	}
	dist(in1){
		return Sqrt(((This.X-In1.X)**2) + ((This.Y-In1.Y)**2))
	}
	dot(in1){
		return (This.X*in1.X)+(This.Y*In1.Y)
	}
	cross(in1){
		return This.X*In1.Y-This.Y*In1.X
	}
	Norm(){
		m:=This.Mag()
		This.X/=m
		This.Y/=m
	}
}
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
;Layered Window Class
class PopUpWindow	{
	;Class By: Hellbent
	;Apr 2021
	static Index := 0 , Windows := [] , Handles := [] , HelpHandles := [] , HelperEditHwnd
	__New( obj := "" ){
		This._SetDefaults()
		if( isObject( obj ) )
			This.SetWindowProperties( obj )
		This._SetupWindowGraphics()
	}
	_SetDefaults(){
		PopUpWindow.Index++
		This.WindowName := "HBLayeredWindow" PopUpWindow.Index
		This.WindowSmoothing := 2
		This.WindowOptions := " -DPIScale +AlwaysOnTop "
		This.X := 10
		This.Y := 10
		This.W := 10
		This.H := 10
	}
	PaintBackground( color := "0xFF000000" ){
		Brush := Gdip_BrushCreateSolid( color ) 
		Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W + 2 , This.H + 2 ) 
		Gdip_DeleteBrush( Brush )
	}
	_SetupWindowGraphics(){
		This.Hwnd := This._CreateGUI()
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.WindowSmoothing )
		PopUpWindow.Handles[ This.Hwnd ] := PopUpWindow.Index
		PopUpWindow.Windows[ PopUpWindow.Index ] := This
	}
	SetWindowProperties( obj ){
		local k , v 
		for k , v in obj
			if( k != "hwnd" )
				This[k] := v
	}
	ShowWindow( Title := "" ){
		Gui , % This.WindowName ":Show", % "x" This.X " y" This.Y " w" This.W " h" This.H " NA", % Title
	}
	HideWindow(){
		Gui , % This.WindowName ":Hide",
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	ClearWindow(){
		Gdip_GraphicsClear( This.G )
	}
	DrawBitmap( pBitmap , obj , dispose := 1 ){
		Gdip_DrawImage( This.G , pBitmap , obj.X , obj.Y , obj.W , obj.H )
		if( dispose )
			Gdip_DisposeImage( pBitmap )
	}
	DeleteWindow(){
		Gui, % This.Window ":Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		hwnd := This.Hwnd
		for k, v in PopUpWindow.Windows[ Hwnd ]
			This[k] := ""
		PopUpWindow.Windows[ Hwnd ] := ""
	}
	_CreateGUI(){
		local hwnd
		Gui , % This.WindowName ":New" , % " +E0x80000 hwndhwnd -Caption  " This.WindowOptions
		return hwnd
	}
	Helper(){
		local List := ["New Window","SetWindowProperties","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow"]
		local hwnd, bd
		
		
		Gui, HBLWHelperGui:New, +AlwaysOnTop 
		Gui, HBLWHelperGui:Color, 62666a, 24282c
		Gui, HBLWHelperGui:Font, cWhite s10 , Segoe UI
		Gui, HBLWHelperGui:Margin, 5 , 5
		
		Gui, HBLWHelperGui:Add, Edit, xm ym w200 r1 Center hwndHwnd, Gui1
		PopUpWindow.HelperEditHwnd := Hwnd
		Gui, HBLWHelperGui:Margin, 5 , 1
		Loop, % List.Length()	{
		
			Gui, HBLWHelperGui:Add, Button, xm wp h23 -Theme hwndhwnd, % List[ A_Index ]
			PopUpWindow.HelpHandles[hwnd] := List[ A_Index ]
			bd := PopUpWindow._ClipIt.Bind( PopUpWindow )
			GuiControl , HBLWHelperGui: +G , % Hwnd , % bd
		}
		
		Gui, HBLWHelperGui:Show, 
		
	}
	_ClipIt(){
		local List := ["New Window","SetWindowProperties","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow"]
		local Output , FQ := 400
		GuiControlGet, Output , HBLWHelperGui: , % PopUpWindow.HelperEditHwnd
		Switch A_GuiControl
		{
			case List[1]:
				Clipboard := Output " := New PopUpWindow( { WindowName: ""1"" , WindowOptions: "" -DPIScale +AlwaysOnTop "" , WindowSmoothing: 2 , X: ""Center"" , Y: ""Center"" , W: 100 , H: 100 } )"
				loop 2
					SoundBeep, FQ
				return
			case List[2]:
				Clipboard := Output ".SetWindowProperties( { X: """" , Y: """" , W: """" , H: """" } )"
				loop 2
					SoundBeep, FQ
				return
			case List[3]:
				Clipboard := Output ".ShowWindow( MyWindowTitle := """" )"
				loop 2
					SoundBeep, FQ
				return
			case List[4]:
				Clipboard := Output ".HideWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[5]:
				Clipboard := Output ".UpdateWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[6]:
				Clipboard := Output ".ClearWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[7]:
				Clipboard := Output ".DrawBitmap( pBitmap := """" , { X: """" , Y: """" , W: """" , H: """" } , dispose := 1 )"
				loop 2
					SoundBeep, FQ
				return
			case List[8]:
				Clipboard := Output ".PaintBackground( color := ""0xFF000000"" )"
				loop 2
					SoundBeep, FQ
				return
			case List[9]:
				Clipboard := Output ".DeleteWindow()"
				loop 2
					SoundBeep, FQ
				return
			Default:
				ToolTip, Looks like a new case needs to be added
				return
			
		}
	}
}
;**************************************************************************************************************************************************************************
;**************************************************************************************************************************************************************************
;**************************************************************************************************************************************************************************
;**************************************************************************************************************************************************************************

Temp (1).gif
Temp (1).gif (105.66 KiB) Viewed 4211 times
AHKStudent
Posts: 1472
Joined: 05 May 2018, 12:23

Re: Calculating the ( Angles / Points ) // DRAW ARROW

27 Jun 2021, 23:23

looks cool, i'd like to test it, where can I get your altered gdip?
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

28 Jun 2021, 00:25

AHKStudent wrote:
27 Jun 2021, 23:23
looks cool, i'd like to test it, where can I get your altered gdip?
You just need the normal gdip lib. When I share code that has extra functions I always include them in the script.
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

28 Jun 2021, 01:48

Overly simplified use case.

Code: Select all


;***************************************************************************************************
 #Include GDIP.Ahk  ;<<<<---------------------
;***************************************************************************************************
#SingleInstance force
SetBatchLines, -1
CoordMode, Mouse, Client
GDIP_STARTUP()
MessageList := ["Blah Blah Blah`nPress This Button","GOOD. `nNOW `nPRESS THIS BUTTON", "One `nLast `nTime!"]
global CurrentMessage := 1

Gui, 1:+AlwaysOnTop -DPIScale
Gui, 1:Margin, 10,10
Gui, 1:Add, Button, xm ym w400 h40 gMessageButton v1 , First
Gui, 1:Add, Button, xm +30 w400 h40 gMessageButton v2 , Second
Gui, 1:Add, Button, xm +30 w400 h40 gMessageButton v3 , Third

Gui, 1:Show, x500 y400 w420 h160, Arrow Demo



global Gui2 := New PopUpWindow( { WindowName: "2" , WindowOptions: " -DPIScale +AlwaysOnTop +Owner1" , WindowSmoothing: 2 , X: 500 , Y: 100 , W: 420 , H: 560 } )
Gui2.ShowWindow()
Step1(MessageList[1])


return
GuiClose:
GuiContextMenu:
*ESC::ExitApp

MessageButton:
	Gui, 1:Show, x500 y400 w420 h160, Arrow Demo
	if(CurrentMessage != A_GuiControl){
		SoundBeep, 999
		return
	}
	
	CurrentMessage++	
	Step%CurrentMessage%(MessageList[CurrentMessage])	
	if(CurrentMessage=4){
		Gui2.ClearWindow()
		Gui2.DrawBitmap( MessageGraphics("Goodbye!!!`nGo AWAY!!!", "0xFFFF0000", 36) , { X: 60 , Y: 340 , W: 300 , H: 130 } , dispose := 1 )
		Gui2.UpdateWindow()
		sleep, 3000
		ExitApp
	}
	return

Numpad3::
	PopUpWindow.Helper()
	return


Step1(Message){
	Gui2.DrawBitmap( MessageGraphics(Message) , { X: 60 , Y: 10 , W: 300 , H: 130 } , dispose := 1 )
	Pen := Gdip_CreatePen( "0xffFF0000" , 5 ) , Gdip_DrawRectangle(Gui2.G, Pen, 8 , 330 , 410 , 50 ) , Gdip_DeletePen( Pen )
	ArrowFunction( {X:0,Y:0} , {X:130,Y:270} , Gui2.G )
	ArrowFunction( {X:100,Y:140} , {X:160,Y:330} , Gui2.G )
	ArrowFunction( {X:150,Y:140} , {X:180,Y:280} , Gui2.G )
	Gui2.UpdateWindow()
	
}

Step2(Message){
	Gui2.ClearWindow()
	Gui2.DrawBitmap( MessageGraphics(Message) , { X: 60 , Y: 10 , W: 300 , H: 130 } , dispose := 1 )
	Pen := Gdip_CreatePen( "0xff00FF00" , 5 ) , Gdip_DrawRectangle(Gui2.G, Pen, 8 , 380 , 410 , 50 ) , Gdip_DeletePen( Pen )
	ArrowFunction( {X:0,Y:0} , {X:130,Y:270} , Gui2.G , "0xFF00FF00" , 20)
	ArrowFunction( {X:100,Y:140} , {X:160,Y:330} , Gui2.G , "0xFF00FF00" , 20)
	ArrowFunction( {X:150,Y:140} , {X:180,Y:280} , Gui2.G , "0xFF00FF00" , 20)
	Gui2.UpdateWindow()
	
}

Step3(Message){
	Gui2.ClearWindow()
	Gui2.DrawBitmap( MessageGraphics(Message) , { X: 60 , Y: 10 , W: 300 , H: 130 } , dispose := 1 )
	Pen := Gdip_CreatePen( "0xff00FFff" , 5 ) , Gdip_DrawRectangle(Gui2.G, Pen, 8 , 430 , 410 , 50 ) , Gdip_DeletePen( Pen )
	ArrowFunction( {X:0,Y:0} , {X:130,Y:270} , Gui2.G , "0xFF00FFff" , 40 )
	ArrowFunction( {X:100,Y:140} , {X:160,Y:330} , Gui2.G , "0xFF00FFff" , 40 )
	ArrowFunction( {X:150,Y:140} , {X:180,Y:280} , Gui2.G , "0xFF00FFff" , 40 )
	Gui2.UpdateWindow()
	
}

ArrowFunction( S , E , G , C := "0xFFFF0000" , A := 10){
	
	Start := New HB_Vector(S.X,S.Y)
	MouseGetPos,x,y
	End := New HB_Vector(E.X, E.Y)
	EndCopy := New HB_Vector( End.X - Start.X , End.Y - Start.Y ) 
	EndCopy.Norm()
	Arrow := New HB_Vector( ( EndCopy.Y * - 1 ) - EndCopy.X , ( EndCopy.X - EndCopy.Y ) )
	Arrow.SetMag(A)
	Arm1 := New HB_Vector( End.X + Arrow.X , End.Y + Arrow.Y )
	Arm2 := New HB_Vector( End.X - Arrow.Y , End.Y + Arrow.X )
	Pen := Gdip_CreatePen( "0xff000000" , 1 ) , Gdip_DrawLine( G , Pen, Start.X , Start.Y , End.X  , End.Y ) , Gdip_DeletePen( Pen )  
	Brush := Gdip_BrushCreateSolid( C ) , Gdip_FillPolygon( G , Brush , Arm1.X "," Arm1.Y  "|" Arm2.X  "," Arm2.Y  "|" End.X  "," End.Y  "|" Arm1.X "," Arm1.Y  ) , Gdip_DeleteBrush( Brush )
	
}

random(Min, Max){
	Random, out, Min, Max
	return out
}


MessageGraphics(Message , C := "0xFFFF7700" , S := 26 ){
	;Bitmap Created Using: HB Bitmap Maker
	pBitmap := Gdip_CreateBitmap( 300 , 130 ) , G := Gdip_GraphicsFromImage( pBitmap ) , Gdip_SetSmoothingMode( G , 2 )
	Brush := Gdip_CreateLineBrushFromRect( 283 , 64 , 100 , 100 , "0xFFF0F0F0" , "0xFF000000" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 2 , 3 , 295 , 120 , 5 ) , Gdip_DeleteBrush( Brush )
	Pen := Gdip_CreatePen( "0xFF880000" , 1 ) , Gdip_DrawRoundedRectangle( G , Pen , 2 , 2 , 295 , 120 , 5 ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xFF000000" ) , Gdip_TextToGraphics( G , Message , "s" S " Center vCenter Bold c" Brush " x1 y1" , "Segoe ui" , 295 , 120 ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( C ) , Gdip_TextToGraphics( G , Message , "s" S " Center vCenter Bold c" Brush " x2 y2" , "Segoe ui" , 295 , 120 ) , Gdip_DeleteBrush( Brush )
	Gdip_DeleteGraphics( G )
	return pBitmap
}

;Vector Class
Class HB_Vector	{
	__New(x:=0,y:=0){
		This.X:=x
		This.Y:=y
	}
	Add(Other_HB_Vector){
		This.X+=Other_HB_Vector.X
		This.Y+=Other_HB_Vector.Y
	}
	Sub(Other_HB_Vector){
		This.X-=Other_HB_Vector.X
		This.Y-=Other_HB_Vector.Y
	}
	mag(){
		return Sqrt(This.X*This.X + This.Y*This.Y)
	}
	magsq(){
		return This.Mag()**2
	}	
	setMag(in1){
		m:=This.Mag()
		This.X := This.X * in1/m
		This.Y := This.Y * in1/m
		return This
	}
	mult(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X*=In1.X 
			This.Y*=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X*=In1
			This.Y*=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X*=In1*In2.X
			This.Y*=In1*In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X*=In1.X*In2.X
			This.Y*=In1.Y*In2.Y
		}	
	}
	div(in1,in2:="",in3:="",in4:="",in5:=""){
		if(IsObject(in1)&&in2=""){
			This.X/=In1.X 
			This.Y/=In1.Y 
		}else if(!IsObject(In1)&&In2=""){
			This.X/=In1
			This.Y/=In1
		}else if(!IsObject(In1)&&IsObject(In2)){
			This.X/=In1/In2.X
			This.Y/=In1/In2.Y
		}else if(IsObject(In1)&&IsObject(In2)){
			This.X/=In1.X/In2.X
			This.Y/=In1.Y/In2.Y
		}	
	}
	dist(in1){
		return Sqrt(((This.X-In1.X)**2) + ((This.Y-In1.Y)**2))
	}
	dot(in1){
		return (This.X*in1.X)+(This.Y*In1.Y)
	}
	cross(in1){
		return This.X*In1.Y-This.Y*In1.X
	}
	Norm(){
		m:=This.Mag()
		This.X/=m
		This.Y/=m
	}
}
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
;************************************************************************************************************************************************************************************************
;Layered Window Class
class PopUpWindow	{
	;Class By: Hellbent
	;Apr 2021
	static Index := 0 , Windows := [] , Handles := [] , HelpHandles := [] , HelperEditHwnd
	__New( obj := "" ){
		This._SetDefaults()
		if( isObject( obj ) )
			This.SetWindowProperties( obj )
		This._SetupWindowGraphics()
	}
	_SetDefaults(){
		PopUpWindow.Index++
		This.WindowName := "HBLayeredWindow" PopUpWindow.Index
		This.WindowSmoothing := 2
		This.WindowOptions := " -DPIScale +AlwaysOnTop "
		This.X := 10
		This.Y := 10
		This.W := 10
		This.H := 10
	}
	PaintBackground( color := "0xFF000000" ){
		Brush := Gdip_BrushCreateSolid( color ) 
		Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W + 2 , This.H + 2 ) 
		Gdip_DeleteBrush( Brush )
	}
	_SetupWindowGraphics(){
		This.Hwnd := This._CreateGUI()
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.WindowSmoothing )
		PopUpWindow.Handles[ This.Hwnd ] := PopUpWindow.Index
		PopUpWindow.Windows[ PopUpWindow.Index ] := This
	}
	SetWindowProperties( obj ){
		local k , v 
		for k , v in obj
			if( k != "hwnd" )
				This[k] := v
	}
	ShowWindow( Title := "" ){
		Gui , % This.WindowName ":Show", % "x" This.X " y" This.Y " w" This.W " h" This.H " NA", % Title
	}
	HideWindow(){
		Gui , % This.WindowName ":Hide",
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	ClearWindow(){
		Gdip_GraphicsClear( This.G )
	}
	DrawBitmap( pBitmap , obj , dispose := 1 ){
		Gdip_DrawImage( This.G , pBitmap , obj.X , obj.Y , obj.W , obj.H )
		if( dispose )
			Gdip_DisposeImage( pBitmap )
	}
	DeleteWindow(){
		Gui, % This.Window ":Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		hwnd := This.Hwnd
		for k, v in PopUpWindow.Windows[ Hwnd ]
			This[k] := ""
		PopUpWindow.Windows[ Hwnd ] := ""
	}
	_CreateGUI(){
		local hwnd
		Gui , % This.WindowName ":New" , % " +E0x80000 hwndhwnd -Caption  " This.WindowOptions
		return hwnd
	}
	Helper(){
		local List := ["New Window","SetWindowProperties","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow"]
		local hwnd, bd
		
		
		Gui, HBLWHelperGui:New, +AlwaysOnTop 
		Gui, HBLWHelperGui:Color, 62666a, 24282c
		Gui, HBLWHelperGui:Font, cWhite s10 , Segoe UI
		Gui, HBLWHelperGui:Margin, 5 , 5
		
		Gui, HBLWHelperGui:Add, Edit, xm ym w200 r1 Center hwndHwnd, Gui1
		PopUpWindow.HelperEditHwnd := Hwnd
		Gui, HBLWHelperGui:Margin, 5 , 1
		Loop, % List.Length()	{
		
			Gui, HBLWHelperGui:Add, Button, xm wp h23 -Theme hwndhwnd, % List[ A_Index ]
			PopUpWindow.HelpHandles[hwnd] := List[ A_Index ]
			bd := PopUpWindow._ClipIt.Bind( PopUpWindow )
			GuiControl , HBLWHelperGui: +G , % Hwnd , % bd
		}
		
		Gui, HBLWHelperGui:Show, 
		
	}
	_ClipIt(){
		local List := ["New Window","SetWindowProperties","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow"]
		local Output , FQ := 400
		GuiControlGet, Output , HBLWHelperGui: , % PopUpWindow.HelperEditHwnd
		Switch A_GuiControl
		{
			case List[1]:
				Clipboard := Output " := New PopUpWindow( { WindowName: ""1"" , WindowOptions: "" -DPIScale +AlwaysOnTop "" , WindowSmoothing: 2 , X: ""Center"" , Y: ""Center"" , W: 100 , H: 100 } )"
				loop 2
					SoundBeep, FQ
				return
			case List[2]:
				Clipboard := Output ".SetWindowProperties( { X: """" , Y: """" , W: """" , H: """" } )"
				loop 2
					SoundBeep, FQ
				return
			case List[3]:
				Clipboard := Output ".ShowWindow( MyWindowTitle := """" )"
				loop 2
					SoundBeep, FQ
				return
			case List[4]:
				Clipboard := Output ".HideWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[5]:
				Clipboard := Output ".UpdateWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[6]:
				Clipboard := Output ".ClearWindow()"
				loop 2
					SoundBeep, FQ
				return
			case List[7]:
				Clipboard := Output ".DrawBitmap( pBitmap := """" , { X: """" , Y: """" , W: """" , H: """" } , dispose := 1 )"
				loop 2
					SoundBeep, FQ
				return
			case List[8]:
				Clipboard := Output ".PaintBackground( color := ""0xFF000000"" )"
				loop 2
					SoundBeep, FQ
				return
			case List[9]:
				Clipboard := Output ".DeleteWindow()"
				loop 2
					SoundBeep, FQ
				return
			Default:
				ToolTip, Looks like a new case needs to be added
				return
			
		}
	}
}
;**************************************************************************************************************************************************************************
;**************************************************************************************************************************************************************************
;**************************************************************************************************************************************************************************
Temp (1).gif
Temp (1).gif (170.14 KiB) Viewed 4167 times
AHKStudent
Posts: 1472
Joined: 05 May 2018, 12:23

Re: Calculating the ( Angles / Points ) // DRAW ARROW

28 Jun 2021, 02:26

very cool, one use case could be for walkthroughs :thumbup:
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

28 Mar 2022, 05:30

I have finished off the last of the small tweaks needed for this to be complete.

I ended up putting it into a class to make things easy.
Animation.gif
Animation.gif (209.01 KiB) Viewed 4061 times

Here is the class:

Code: Select all

;**********************************************************************************************************************************************************************************************************************************
;**********************************************************************************************************************************************************************************************************************************
;**********************************************************************************************************************************************************************************************************************************
class ArrowHead	{
;Written By: Hellbent
;Date Started: Mar 28th, 2022
;Last Edit: 
;Details: Draws an arrow on supplied grapics layer
	__New( obj , flag := 0 ){
		local vectors := {} , points
		vectors.start := This._NewVector( obj.X1 , obj.Y1 )
		vectors.End := This._NewVector( obj.X2 , obj.Y2 )
		vectors.EndCopy := This._NewVector( obj.X2 , obj.Y2 )
		This._Sub( vectors.EndCopy , vectors.Start )
		This._SetMag( vectors.EndCopy , obj.Size * 3 )
		This._Add( vectors.EndCopy , vectors.End )
		vectors.NewEnd := This._NewVector( vectors.EndCopy.X , vectors.EndCopy.Y )
		This._Sub( vectors.EndCopy , vectors.End )
		This._Norm( vectors.EndCopy )
		vectors.Arrow := This._NewVector( ( vectors.EndCopy.Y * - 1 ) - vectors.EndCopy.X , ( vectors.EndCopy.X - vectors.EndCopy.Y ) )
		This._SetMag( vectors.Arrow , obj.Size * 5 )
		vectors.Arm1 := This._NewVector( vectors.NewEnd.X + vectors.Arrow.X , vectors.NewEnd.Y + vectors.Arrow.Y )
		vectors.Arm2 := This._NewVector( vectors.NewEnd.X - vectors.Arrow.Y , vectors.NewEnd.Y + vectors.Arrow.X )
		points := vectors.Arm1.X "," vectors.Arm1.Y "|" vectors.Arm2.X "," vectors.Arm2.Y "|" vectors.NewEnd.X "," vectors.NewEnd.Y "|" vectors.Arm1.X "," vectors.Arm1.Y
		if( flag )
			return points
		This._Draw( vectors , obj , points )	
	}_NewVector( x , y ){
		return { X: x , Y: y }
	}_SetMag( vector , value ){
		local mag := This._GetMag( vector )
		vector.X := vector.X * value / mag
		vector.Y := vector.Y * value / mag
	}_GetMag( vector ){
		return Sqrt( vector.X * vector.X + vector.Y * vector.Y )
	}_Add( vector1 , vector2 ){
		vector1.X += vector2.X
		vector1.Y += vector2.Y
	}_Sub( vector1 , vector2 ){
		vector1.X -= vector2.X
		vector1.Y -= vector2.Y
	}_Norm( vector ){
		local mag := This._GetMag( vector )
		vector.X /= mag
		vector.Y /= mag
	}_Dist( vector1 , vector2 ){
		return Sqrt( ( ( vector1.X - vector2.X ) **2 ) + ( ( vector1.Y - vector2.Y ) **2 ) )
	}_Draw( vectors , obj , points ){
		local Pen := Gdip_CreatePen( obj.color , obj.size ) , Brush := Gdip_BrushCreateSolid( obj.color )
		Gdip_DrawLine( obj.G , Pen, obj.x1 , obj.y1 , obj.x2  , obj.y2 ) , Gdip_DeletePen( Pen )
		Gdip_FillPolygon( obj.G , Brush , points ) , Gdip_DeleteBrush( Brush )
	}
}
;**********************************************************************************************************************************************************************************************************************************
;**********************************************************************************************************************************************************************************************************************************
;**********************************************************************************************************************************************************************************************************************************
And here is an example of using it. ( The class is already in the example but you will need a copy of the gdi+ lib )

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib> ;gdip.ahk
;~ #Include <PopUpWindow_V2> ; At the bottom of the script
;****************************************************************************************************************************************************************************
#SingleInstance, Force
SetBatchlines, -1
CoordMode, Mouse, Client
GDIP_STARTUP()
Gui1 := New PopUpWindow( { AutoShow: 1 , X: "Center" , Y: "Center" , W: A_ScreenWidth - 40 , H: 400 , Options: " -DPIScale +AlwaysOnTop " } )
Gui1.PaintBackground( { Color: "0x99000000" , X: 2 , Y: 2 , W: Gui1.W - 4 , H: Gui1.H - 4 , Round: 20 } , 1 )
Gui1.colors := [ "FE6C26" , "F535A8" , "4FC08A" , "F2DB03" , "89DBD3" , "E15C10" , "D126F0" , "072EAE" , "284C24" , "10E893" , "D70C92" , "43FFFE" , "B90D09" , "DF058C" , "77E1E7" , "C8DD35" , "37E9FB" , "F2A62D" , "37E9FB" ]
OnMessage( 0x201 , Func( "OnClick" ).Bind( Gui1 ) )
return
GuiClose:
GuiContextMenu:
*ESC::ExitApp

RALT::PopUpWindow.Helper()

OnClick( gui1 ){
	static tog , sx , sy , ex , ey
	
	if( tog := !tog ){
	
		MouseGetPos, sx, sy
		
	}else{
	
		MouseGetPos, ex, ey
		
		;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
		;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
		
		New ArrowHead( { 	X1: 			sx 
					 	, 	Y1: 			sy 
					 	, 	X2: 			ex 
					 	, 	Y2: 			ey 
					 	, 	Size: 			random( 1 , 5 ) 
					 	, 	G: 				Gui1.G 
					 	, 	Color: 			"0xFF" gui1.colors[ random( 1 , gui1.colors.Length() ) ] } )
					 
		;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
		;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
					 
		Gui1.UpdateWindow()
	}
}
random(Min, Max){
	Random, out, Min, Max
	return out
}

;Draw Arrow Class
;**********************************************************************************************************************************************************************************************************************************
;**********************************************************************************************************************************************************************************************************************************
;**********************************************************************************************************************************************************************************************************************************
class ArrowHead	{
;Written By: Hellbent
;Date Started: Mar 28th, 2022
;Last Edit: 
;Details: Draws an arrow on supplied grapics layer
	__New( obj , flag := 0 ){
		local vectors := {} , points
		vectors.start := This._NewVector( obj.X1 , obj.Y1 )
		vectors.End := This._NewVector( obj.X2 , obj.Y2 )
		vectors.EndCopy := This._NewVector( obj.X2 , obj.Y2 )
		This._Sub( vectors.EndCopy , vectors.Start )
		This._SetMag( vectors.EndCopy , obj.Size * 3 )
		This._Add( vectors.EndCopy , vectors.End )
		vectors.NewEnd := This._NewVector( vectors.EndCopy.X , vectors.EndCopy.Y )
		This._Sub( vectors.EndCopy , vectors.End )
		This._Norm( vectors.EndCopy )
		vectors.Arrow := This._NewVector( ( vectors.EndCopy.Y * - 1 ) - vectors.EndCopy.X , ( vectors.EndCopy.X - vectors.EndCopy.Y ) )
		This._SetMag( vectors.Arrow , obj.Size * 5 )
		vectors.Arm1 := This._NewVector( vectors.NewEnd.X + vectors.Arrow.X , vectors.NewEnd.Y + vectors.Arrow.Y )
		vectors.Arm2 := This._NewVector( vectors.NewEnd.X - vectors.Arrow.Y , vectors.NewEnd.Y + vectors.Arrow.X )
		points := vectors.Arm1.X "," vectors.Arm1.Y "|" vectors.Arm2.X "," vectors.Arm2.Y "|" vectors.NewEnd.X "," vectors.NewEnd.Y "|" vectors.Arm1.X "," vectors.Arm1.Y
		if( flag )
			return points
		This._Draw( vectors , obj , points )	
	}_NewVector( x , y ){
		return { X: x , Y: y }
	}_SetMag( vector , value ){
		local mag := This._GetMag( vector )
		vector.X := vector.X * value / mag
		vector.Y := vector.Y * value / mag
	}_GetMag( vector ){
		return Sqrt( vector.X * vector.X + vector.Y * vector.Y )
	}_Add( vector1 , vector2 ){
		vector1.X += vector2.X
		vector1.Y += vector2.Y
	}_Sub( vector1 , vector2 ){
		vector1.X -= vector2.X
		vector1.Y -= vector2.Y
	}_Norm( vector ){
		local mag := This._GetMag( vector )
		vector.X /= mag
		vector.Y /= mag
	}_Dist( vector1 , vector2 ){
		return Sqrt( ( ( vector1.X - vector2.X ) **2 ) + ( ( vector1.Y - vector2.Y ) **2 ) )
	}_Draw( vectors , obj , points ){
		local Pen := Gdip_CreatePen( obj.color , obj.size ) , Brush := Gdip_BrushCreateSolid( obj.color )
		Gdip_DrawLine( obj.G , Pen, obj.x1 , obj.y1 , obj.x2  , obj.y2 ) , Gdip_DeletePen( Pen )
		Gdip_FillPolygon( obj.G , Brush , points ) , Gdip_DeleteBrush( Brush )
	}
}
;**********************************************************************************************************************************************************************************************************************************
;**********************************************************************************************************************************************************************************************************************************
;**********************************************************************************************************************************************************************************************************************************



;Layered Window Class
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
class PopUpWindow	{
;PopUpWindow v2.2
;Date Written: Oct 28th, 2021
;Last Edit: Feb 7th, 2022 :Changed the trigger method.
;Written By: Hellbent aka CivReborn
;SpcThanks: teadrinker , malcev 
	static Index := 0 , Windows := [] , Handles := [] , EditHwnd , HelperHwnd
	__New( obj := "" ){
		This._SetDefaults()
		This.UpdateSettings( obj )
		This._CreateWindow()
		This._CreateWindowGraphics()
		if( This.AutoShow )
			This.ShowWindow( This.Title )
	}
	_SetDefaults(){
		This.X := 10
		This.Y := 10
		This.W := 10
		This.H := 10
		This.Smoothing := 2
		This.Options := " -DPIScale +AlwaysOnTop "
		This.AutoShow := 0
		This.GdipStartUp := 0
		This.Title := ""
		
		This.Controls := []
		This.Handles := []
		This.Index := 0 
	}
	AddTrigger( obj ){
		local k , v , cc , bd
		
		This.Controls[ ++This.Index ] := { 	X:		10
										,	Y:		10
										,	W:		10
										,	H:		10	}
		for k, v in obj
			This.Controls[ This.Index ][ k ] := obj[ k ] 
		cc := This.Controls[ This.Index ]
		Gui, % This.Hwnd ":Add", Text, % "x" cc.X " y" cc.Y " w" cc.W " h" cc.H " hwndhwnd"
		This.Handles[ hwnd ] := This.Index
		This.Controls[ This.Index ].Hwnd := hwnd
		
		if( IsObject( cc.Label ) ){
			bd := cc.Label
			GuiControl, % This.Hwnd ":+G" , % hwnd , % bd
		}else{
			bd := This._TriggerCall.Bind( This )
			GuiControl, % This.Hwnd ":+G" , % hwnd , % bd
		}
		return hwnd
		
	}
	_TriggerCall(){
		MouseGetPos,,,, ctrl, 2
		Try
			;~ SetTimer, % This.Controls[ This.Handles[ ctrl ] ].Label, -0
			gosub, % This.Controls[ This.Handles[ ctrl ] ].Label
		
				
	}
	DrawTriggers( color := "0xFFFF0000" , AutoUpdate := 0 ){
		local brush , cc 
		Brush := Gdip_BrushCreateSolid( color ) 
		Gdip_SetSmoothingMode( This.G , 3 )
		loop, % This.Controls.Length()	{
			cc := This.Controls[ A_Index ]
			Gdip_FillRectangle( This.G , Brush , cc.x , cc.y , cc.w , cc.h )
		
		}
		Gdip_DeleteBrush( Brush )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	UpdateSettings( obj := "" , UpdateGraphics := 0 ){
		local k , v
		if( IsObject( obj ) )
			for k, v in obj
				This[ k ] := obj[ k ]
		( This.X = "Center" ) ? ( This.X := ( A_ScreenWidth - This.W ) / 2 ) 	
		( This.Y = "Center" ) ? ( This.Y := ( A_ScreenHeight - This.H ) / 2 ) 	
		if( UpdateGraphics ){
			This._DestroyWindowsGraphics()
			This._CreateWindowGraphics()
		}
	}
	_CreateWindow(){
		local hwnd
		Gui , New, % " +LastFound +E0x80000 hwndhwnd -Caption  " This.Options
		PopUpWindow.Index++
		This.Index := PopUpWindow.Index
		PopUpWindow.Windows[ PopUpWindow.Index ] := This
		This.Hwnd := hwnd
		PopUpWindow.Handles[ hwnd ] := PopUpWindow.Index
		if( This.GdipStartUp && !PopUpWindow.pToken )
			PopUpWindow.pToken := GDIP_STARTUP()
	}
	_DestroyWindowsGraphics(){
		Gdip_DeleteGraphics( This.G )
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
	}
	_CreateWindowGraphics(){
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
	}
	ShowWindow( Title := "" ){
		Gui , % This.Hwnd ":Show", % "x" This.X " y" This.Y " w" This.W " h" This.H " NA", % Title
	}
	HideWindow(){
		Gui , % This.Hwnd ":Hide",
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	ClearWindow( AutoUpdate := 0 ){
		Gdip_GraphicsClear( This.G )
		if( Autoupdate )
			This.UpdateWindow()
	}
	DrawBitmap( pBitmap , obj , dispose := 1 , AutoUpdate := 0 ){
		Gdip_DrawImage( This.G , pBitmap , obj.X , obj.Y , obj.W , obj.H )
		if( dispose )
			Gdip_DisposeImage( pBitmap )
		if( Autoupdate )
			This.UpdateWindow()
	}
	PaintBackground( color := "0xFF000000" , AutoUpdate := 0 ){
		if( isObject( color ) ){
			Brush := Gdip_BrushCreateSolid( ( color.HasKey( "Color" ) ) ? ( color.Color ) : ( "0xFF000000" ) ) 
			if( color.Haskey( "Round" ) )
				Gdip_FillRoundedRectangle( This.G , Brush , color.X , color.Y , color.W , color.H , color.Round )
			else
				Gdip_FillRectangle( This.G , Brush , color.X , color.Y , color.W , color.H ) 
		}else{
			Brush := Gdip_BrushCreateSolid( color ) 
			Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W + 2 , This.H + 2 ) 
		}
		Gdip_DeleteBrush( Brush )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DeleteWindow( GDIPShutdown := 0 ){
		Gui, % This.Hwnd ":Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		hwnd := This.Hwnd
		for k, v in PopUpWindow.Windows[ Hwnd ]
			This[k] := ""
		PopUpWindow.Windows[ Hwnd ] := ""
		if( GDIPShutdown ){
			Gdip_Shutdown( PopUpWindow.pToken )
			PopUpWindow.pToken := ""
		}
	}
	_OnClose( wParam ){
		if( wParam = 0xF060 ){	;SC_CLOSE ;[ clicking on the gui close button ]
			Try{
				Gui, % PopUpWindow.HelperHwnd ":Destroy"
				SoundBeep, 555
			}
		}
	}
	CreateCachedBitmap( pBitmap , Dispose := 0 ){
		local pCachedBitmap
		if( This.CachedBitmap )
			This.DisposeCachedbitmap()
		DllCall( "gdiplus\GdipCreateCachedBitmap" , "Ptr" , pBitmap , "Ptr" , this.G , "PtrP" , pCachedBitmap )
		This.CachedBitmap := pCachedBitmap
		if( Dispose )
			Gdip_DisposeImage( pBitmap )
	}
	DrawCachedBitmap( AutoUpdate := 0 ){
		DllCall( "gdiplus\GdipDrawCachedBitmap" , "Ptr" , this.G , "Ptr" , This.CachedBitmap , "Int" , 0 , "Int" , 0 )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DisposeCachedbitmap(){
		DllCall( "gdiplus\GdipDeleteCachedBitmap" , "Ptr" , This.CachedBitmap )
	}
	Helper(){
		local hwnd , MethodList := ["__New","UpdateSettings","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow" , "AddTrigger" , "DrawTriggers", "CreateCachedBitmap" , "DrawCachedBitmap" , "DisposeCachedbitmap" ]
		Gui, New, +AlwaysOnTop +ToolWindow +HwndHwnd
		PopUpWindow.HelperHwnd := hwnd
		Gui, Add, Edit, xm ym w250 r1 Center hwndhwnd, Gui1
		PopUpWindow.EditHwnd := hwnd
		loop, % MethodList.Length()	
			Gui, Add, Button, xm y+1 w250 r1 gPopUpWindow._HelperClip, % MethodList[ A_Index ]
		Gui, Show,,
		OnMessage( 0x112 , This._OnClose.Bind( hwnd ) )
	}
	_HelperClip(){
		local ClipList 
		
		GuiControlGet, out, % PopUpWindow.HelperHwnd ":", % PopUpWindow.EditHwnd	
		
		ClipList := 		{ 	__New: 					" := New PopUpWindow( { AutoShow: 1 , X: 0 , Y: 0 , W: A_ScreenWidth , H: A_ScreenHeight , Options: "" -DPIScale +AlwaysOnTop "" } )"
							,	UpdateSettings:			".UpdateSettings( { X: """" , Y: """" , W: """" , H: """" } , UpdateGraphics := 0 )"
							,	ShowWindow:				".ShowWindow( Title := """" )"
							,	HideWindow:				".HideWindow()"
							,	UpdateWindow:			".UpdateWindow()"
							,	ClearWindow:			".ClearWindow( AutoUpdate := 0 )"
							,	DrawBitmap:				".DrawBitmap( pBitmap := """" , { X: 0 , Y: 0 , W: " Out ".W , H: " Out ".H } , dispose := 1 , AutoUpdate := 0 )"
							,	PaintBackground:		".PaintBackground( color := ""0xFF000000"" , AutoUpdate := 0 )  "  ";{ Color: ""0xFF000000"" , X: 2 , Y: 2 , W: " Out ".W - 4 , H: " Out ".H - 4 , Round: 10 }"
							,	DeleteWindow:			".DeleteWindow( GDIPShutdown := 0 )"
							,	AddTrigger:				".AddTrigger( { X: """" , Y: """" , W: """" , H: """" , Value: """" , Label: """" } )"	
							,	DrawTriggers:			".DrawTriggers( color := ""0xFFFF0000"" , AutoUpdate := 0 )"	
							,	CreateCachedBitmap:		".CreateCachedBitmap( pBitmap , Dispose := 0 )"	
							,	DrawCachedBitmap: 		".DrawCachedBitmap( AutoUpdate := 0 )"	
							,	DisposeCachedbitmap:	".DisposeCachedbitmap()"	}
							
		clipboard := Out ClipList[ A_GuiControl ]
		
	}
}
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

24 Aug 2022, 05:50

New updated version.
Class returns a string containing the points to draw an arrow.

Example call

Code: Select all


MouseGetPos, x , y

StartPoint := { X: 300 , Y: 300 }
EndPoint := { X: x , Y: y }
HeadLength := 30
ArmLength := 30
ElbowLength := 20

ArrowPoints := New ArrowHead( StartPoint ,  EndPoint , HeadLength , ArmLength , ElbowLength )

ToolTip, % ArrowPoints


Class:

Code: Select all

class ArrowHead	{
	;Written By: Hellbent
	;Date: Aug 24th 2022
	;Last Edit: Sept 24th, 2022
	;Purpose: Create a list of points to draw an arrow.  " x , y | x , y | etc... "
	__New( Start , End , HeadLength := 30 , ArmLength := 20 , ElbowLength := 10 , x_offset := 0 , y_offset := 0 ){
		if( This._DistanceBetweenVectors( Start , End ) < ( HeadLength + HeadLength * 2 ) ){
			temp := This._NewVector( End.X + 1 , End.Y + 1 )
			This._SubVector( temp , Start )
			This._SetVectorMag( temp ,  HeadLength + HeadLength * 2 )
			This._AddVector( temp , Start )
			End := This._NewVector( temp )
		}
		Master := This._NewVector( Start )
		This._SubVector( Master , End )
		Head := This._NewVector( Master )
		This._SetVectorMag( Head ,  HeadLength )
		This._AddVector( Head , End )
		RightArm := This._NewVector( Master , , 2 )
		This._SetVectorMag( RightArm ,  ArmLength )
		This._AddVector( RightArm , Head )
		LeftArm := This._NewVector( Master , , 1 )
		This._SetVectorMag( LeftArm ,  ArmLength )
		This._AddVector( LeftArm , Head )
		RightElbow := This._NewVector( Master , , 2 )
		This._SetVectorMag( RightElbow ,  ElbowLength )
		This._AddVector( RightElbow , Head )
		LeftElbow := This._NewVector( Master , , 1 )
		This._SetVectorMag( LeftElbow ,  ElbowLength )
		This._AddVector( LeftElbow , Head )
		output := ""
		for k , v in [ "Start" , "RightElbow" , "RightArm" , "End" , "LeftArm" , "LeftElbow" , "Start" ] {	
			
			a := %v%.X + x_offset
			b := %v%.Y + y_offset
			output .= a "," b "|"
		
		}
		return output
	}
	_CopyVector( vector ){
		return This._NewVector( vector.X , vector.Y )
	}
	_NewVector( x , y := "" , rotate := 0 ){
		if( IsObject( x ) ){
			if( rotate = 1 )
				return { X: x.Y * -1 , Y: x.X }
			else if( rotate = 2 )
				return { X: x.Y , Y: x.X * -1 }
			else
				return { X: x.X , Y: x.Y }
		}else
			return { X: x , Y: y }
	}
	_DistanceBetweenVectors( vector1 , vector2 ){
		return Sqrt( ( ( vector1.X - vector2.X ) **2 ) + ( ( vector1.Y - vector2.Y ) **2 ) )
	}
	_SubVector( vector1 , vector2 ){
		vector1.X -= vector2.X
		vector1.Y -= vector2.Y
	}
	_AddVector( vector1 , vector2 ){
		vector1.X += vector2.X
		vector1.Y += vector2.Y
	}
	_SetVectorMag( vector , mag ){
		local m := This._GetVectorMag( vector )
		vector.X := vector.X * mag / m
		vector.Y := vector.Y * mag / m
	}
	_GetVectorMag( vector ){
		return Sqrt( vector.X * vector.X + vector.Y * vector.Y )
	}
}
Intended for use with the gdip polygon functions.

For example:

Code: Select all


_FillPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFFFF0000" ){
	Brush := Gdip_BrushCreateSolid( Color ) , Gdip_FillPolygon( G , Brush , Points ) , Gdip_DeleteBrush( Brush )
}

_DrawPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFF000000" , Thickness := 3 ){
	Pen := Gdip_CreatePen( Color , Thickness ) , Gdip_DrawLines( G , Pen , Points ) , Gdip_DeletePen( Pen )
}



Design details:
20220824063842.png
20220824063842.png (26.43 KiB) Viewed 3849 times
.


Example use:
Arrows.gif
Arrows.gif (253.92 KiB) Viewed 3849 times
Last edited by Hellbent on 24 Sep 2022, 15:55, edited 1 time in total.
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW  Topic is solved

25 Aug 2022, 03:29

Another new design.
Returns a string of points to draw using the gdi+ polygon functions or other such drawing functions.

Class:

Code: Select all

class ArrowHead_2	{
	
	__New( Start , End , HeadLength := 30 , NeckLength := 10 , ArmLength := 30 , ElbowLength := 15 ){
		
		Master := This._NewVector( Start )
		This._SubVector( Master , End )
		
		Head := This._NewVector( Master )
		This._SetVectorMag( Head , HeadLength )
		This._AddVector( Head , End )
		
		Neck := This._NewVector( Master )
		This._SetVectorMag( Neck , NeckLength )
		This._AddVector( Neck , Head )
		
		RightArm := This._NewVector( Master , , 1 )
		This._SetVectorMag( RightArm , ArmLength )
		This._AddVector( RightArm , Neck )
		
		RightElbow := This._NewVector( Master , , 1 )
		This._SetVectorMag( RightElbow , ElbowLength )
		This._AddVector( RightElbow , Head )
		
		LeftArm := This._NewVector( Master , , 2 )
		This._SetVectorMag( LeftArm , ArmLength )
		This._AddVector( LeftArm , Neck )
		
		LeftElbow := This._NewVector( Master , , 2 )
		This._SetVectorMag( LeftElbow , ElbowLength )
		This._AddVector( LeftElbow , Head )
		
		OutputString := ""
		for k , v in [ "Start" , "RightElbow" , "RightArm" , "End" , "LeftArm" , "LeftElbow" , "Start" ]	
			OutputString .= %v%.X "," %v%.Y "|"
		return OutputString 
	}
	_NewVector( x , y := "" , rotate := 0 ){
		if( IsObject( x ) ){
			if( !rotate )
				return { X: x.X , Y: x.Y }
			else if( rotate = 1 )
				return { X: x.Y * -1 , Y: x.X }
			else if( rotate = 2 )
				return { X: x.Y , Y: x.X * -1 }
		}else{
			if( !rotate )
				return { X: x , Y: x }
			else if( rotate = 1 )
				return { X: y * -1 , Y: x }
			else if( rotate = 2 )
				return { X: y , Y: x * -1 }
		}
	}
	_SubVector( vector1 , vector2 ){
		vector1.X -= vector2.X
		vector1.Y -= vector2.Y
	}
	_AddVector( vector1 , vector2 ){
		vector1.X += vector2.X
		vector1.Y += vector2.Y
	}
	_SetVectorMag( vector , mag ){
		local m := This._GetVectorMag( vector )
		vector.X := vector.X * mag / m
		vector.Y := vector.Y * mag / m
	}
	_GetVectorMag( vector ){
		return Sqrt( vector.X * vector.X + vector.Y * vector.Y )
		
	}
}
Design basics:
20220825041811.png
20220825041811.png (15.5 KiB) Viewed 3795 times
.

Demo of some of the customization:
arrows2.gif
arrows2.gif (278.09 KiB) Viewed 3795 times
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

15 Jan 2023, 14:04

other polygons example.
20230115140212.png
20230115140212.png (16.54 KiB) Viewed 3483 times
poly 1.gif
poly 1.gif (738.2 KiB) Viewed 3474 times

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib> ;<<<<<<<<<<<<<<<<<<---------------------------     gdip.ahk
;~ #Include <PopUpWindow_V2> ; At the bottom of the script 
;~ #Include <HB Vectors v2>  ; At the bottom of the script 
;****************************************************************************************************************************************************************************
#SingleInstance, Off
SetBatchLines, -1
Gdip_Startup()

Gui1 := New PopUpWindow( { AutoShow: 1 , X: -350 , Y: 200 , W: 500 , H: 500 , Options: " -DPIScale +AlwaysOnTop " } )

Home := New Vector( 250 , 250 )
arm1 := []
arm2 := []
list := [ "" , 1 , 3 , 2 ]
angle := 0
rate := 0

setTimer, rotate, 10

return
GuiClose:
GuiContextMenu:
*ESC::ExitApp

RALT::PopUpWindow.Helper()

rotate:
	rate += .01
	Master1 := New Vector( 250 , 150 )
	Master1.Sub( Home )
	Master1.RotateAngle( angle += rate )
	Master2 := New Vector( Master1 )
	Master2.RotateAngle( 45 )
	
	points := ""
	points2 := ""
	points3 := ""
	loop, 4	{
		arm1[ A_Index ] := New Vector( Master1 ,, list[ A_Index ] )
		arm1[ A_Index ].Add( Home )
		arm2[ A_Index ] := New Vector( Master2 ,, list[ A_Index ] )
		arm2[ A_Index ].Add( Home )
		points .= arm1[ A_Index ].X "," arm1[ A_Index ].Y "|" arm2[ A_Index ].X "," arm2[ A_Index ].Y "|"
		points2 .= arm1[ A_Index ].X "," arm1[ A_Index ].Y "|" 
		points3 .= arm2[ A_Index ].X "," arm2[ A_Index ].Y "|"
	}
	points .= arm1[ 1 ].X "," arm1[ 1 ].Y "|" arm2[ 1 ].X "," arm2[ 1 ].Y "|"
	points2 .= arm1[ 1 ].X "," arm1[ 1 ].Y "|" 
	points3 .=  arm2[ 1 ].X "," arm2[ 1 ].Y "|"
	( ( Gui1.X + angle / 30 ) > A_ScreenWidth - 200 ) ? ( na := -350 , angle := 0 ) : ( na := Gui1.X + angle / 30 )
	Gui1.UpdateSettings( { X: na } )
	Gui1.ClearWindow()
	FillPolygon( Gui1.G , Points  , Color := "0xff000000" )
	DrawPolygon( Gui1.G , Points  , Color := "0xFFFF0000" , Thickness := 13 )
	DrawPolygon( Gui1.G , Points  , Color := "0xFF00ffff" , Thickness := 5 )
	DrawPolygon( Gui1.G , Points3  , Color := "0xFFFFff00" , Thickness := 13 )
	DrawPolygon( Gui1.G , Points2  , Color := "0xFF00ff00" , Thickness := 5 )
	Gui1.UpdateWindow()
	
	return








;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;

FillPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFFFF0000" ){
	
	Brush := Gdip_BrushCreateSolid( Color ) , Gdip_FillPolygon( G , Brush , Points ) , Gdip_DeleteBrush( Brush )
}

DrawPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFF000000" , Thickness := 3 ){
	Pen := Gdip_CreatePen( Color , Thickness ) , Gdip_DrawLines( G , Pen , Points ) , Gdip_DeletePen( Pen )
}

;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
;************
;Vector Class
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
Class Vector	{
	;Written By: HB
	;Date: Sept 23rd, 2022
	;Last Edit: Sept 24th, 2022
	;Purpose: Vector math class 
	;Credit: Rohwedder 
	;Resources: 
		;Line intercept concepts and code: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=37175
		;Create an Arrow: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=92039&p=479129#p478944
		;Getting an angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483661#p483678
		;Setting an Angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483786#p483811
		;
		
	static RadToDeg := 45 / ATan( 1 ) 
		, DegToRad := ATan( 1 ) / 45 
		
	__New( x := 0 , y := 0 , rotate := 0 ){ 
		if( IsObject( x ) ){
			if( rotate = 3 ){
				This.X := x.X * -1
				,This.Y := x.Y * -1
			}else if( rotate = 2 ){
				This.X := x.Y 
				,This.Y := x.X * -1
			}else if( rotate = 1 ){
				This.X := x.Y * -1
				,This.Y := x.X 
			}else{
				This.X := x.X
				,This.Y := x.Y
			}
		}else{
			if( rotate = 3 ){
				This.X := X * -1
				,This.Y := Y * -1
			}else if( rotate = 2 ){
				This.X := Y 
				,This.Y := X * -1
			}else if( rotate = 1 ){
				This.X := Y * -1
				,This.Y := X 
			}else{
				This.X := X
				,This.Y := Y
			}
		}
	}
	Add( x , y := "" ){
		if( IsObject( x ) ){
			This.X += x.X
			,This.Y += x.Y
		}else if( y = "" ){
			This.X += x 
			,This.Y += x
		}else{
			This.X += x 
			,This.Y += y 
		}
	}
	Sub( x , y := "" ){
		if( IsObject( x ) ){
			This.X -= x.X
			,This.Y -= x.Y
		}else if( y = "" ){
			This.X -= X
			,This.Y -= X
		}else{
			This.X -= X
			,This.Y -= Y
		}
	}
	Div( x , y := "" ){
		if( IsObject( x ) ){
			This.X /= x.X
			,This.Y /= x.Y
		}else if( x && y = "" ){
			This.X /= x 
			,This.Y /= x 
		}else{
			This.X /= X
			,This.Y /= Y
		}
	}
	Mult( x , y := "" ){
		if( IsObject( x ) ){
			This.X *= x.X
			,This.Y *= x.Y
		}else if( x && y = "" ){
			This.X *= x 
			,This.Y *= x 
		}else{
			This.X *= X
			,This.Y *= Y
		}
	}
	Dist( x , y := "" ){
		if( IsObject( x ) )
			return Sqrt( ( ( This.X - x.X ) **2 ) + ( ( This.Y - x.Y ) **2 ) )
		else 
			return Sqrt( ( ( This.X - X ) **2 ) + ( ( This.Y - Y ) **2 ) )
	}
	GetMag(){
		return Sqrt( This.X * This.X + This.Y * This.Y )
	}
	SetMag( magnitude ){
		local m := This.GetMag()
		This.X := This.X * magnitude / m
		,This.Y := This.Y * magnitude / m
	}
	MagSq(){
		return This.GetMag()**2
	}	
	Dot( x , y := "" ){
		if( IsObject( x ) )
			return ( This.X * x.X ) + ( This.Y * x.Y )
		else
			return ( This.X * X ) + ( This.Y * Y )
	}
	Cross( x , y := "" ){
		if( IsObject( x ) )
			return This.X * x.Y - This.Y * x.X
		else
			return This.X * Y - This.Y * X
		
	}
	Norm(){
		local m := This.GetMag()
		This.X /= m
		This.Y /= m
	}
	GetAngle(){ 
		local angle 
		( (  angle := Vector.RadToDeg * DllCall( "msvcrt\atan2" , "Double" , This.Y , "Double" , This.X , "CDECL Double" ) ) < 0 ) ? ( angle += 360 )
		return angle
	}
	SetAngle( newAngle := 0 , NewVector := 0 ){
		local Angle := This.GetAngle()
		, ChangeAngle := newAngle - Angle 
		, Co := Cos( Vector.DegToRad * ChangeAngle )
		, Si := Sin( Vector.DegToRad * ChangeAngle )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	RotateAngle( rotationAmount := 90 , NewVector := 0 ){
		local Co := Cos( Vector.DegToRad * rotationAmount )
		, Si := Sin( Vector.DegToRad * rotationAmount )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	;********************************************
	;class methods
	TestLineInterceptPoint( interceptPoint , Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } } , interceptPoint = { X: , Y: }
		local
		for k , v in [ "X" , "Y" ]	
			M%v%_Min := min( Line1.Start[ v ] , Line1.End[ v ] )
			,M%v%_Max := max( Line1.Start[ v ] , Line1.End[ v ] )
			,L%v%_Min := min( Line2.Start[ v ] , Line2.End[ v ] )
			,L%v%_Max := max( Line2.Start[ v ] , Line2.End[ v ] )
		if( !( interceptPoint.X < Mx_Min || interceptPoint.X > Mx_Max || interceptPoint.X < Lx_Min || interceptPoint.X > Lx_Max ) && !( interceptPoint.Y < My_Min || interceptPoint.Y > My_Max || interceptPoint.Y < Ly_Min || interceptPoint.Y > Ly_Max ) )
			return 1
		return 0
	}
	GetLineInterceptPoint( Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } }
		local A1 := Line1.End.Y - Line1.Start.Y
		,B1 := Line1.Start.X - Line1.End.X
		,C1 := A1 * Line1.Start.X + B1 * Line1.Start.Y
		,A2 := Line2.End.Y - Line2.Start.Y
		,B2 := Line2.Start.X - Line2.End.X
		,C2 := A2 * Line2.Start.X + B2 * Line2.Start.Y
		,Denominator := A1 * B2 - A2 * B1 
		return New Vector( { X: ( ( B2 * C1 - B1 * C2 ) / Denominator )  , Y: ( ( A1 * C2 - A2 * C1 ) / Denominator ) } )
	}
	;********************************************
}
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************

class PopUpWindow	{
;PopUpWindow v2.2
;Date Written: Oct 28th, 2021
;Last Edit: Feb 7th, 2022 :Changed the trigger method.
;Written By: Hellbent aka CivReborn
;SpcThanks: teadrinker , malcev 
	static Index := 0 , Windows := [] , Handles := [] , EditHwnd , HelperHwnd
	__New( obj := "" ){
		This._SetDefaults()
		This.UpdateSettings( obj )
		This._CreateWindow()
		This._CreateWindowGraphics()
		if( This.AutoShow )
			This.ShowWindow( This.Title )
	}
	_SetDefaults(){
		This.X := 10
		This.Y := 10
		This.W := 10
		This.H := 10
		This.Smoothing := 2
		This.Options := " -DPIScale +AlwaysOnTop "
		This.AutoShow := 0
		This.GdipStartUp := 0
		This.Title := ""
		
		This.Controls := []
		This.Handles := []
		This.Index := 0 
	}
	AddTrigger( obj ){
		local k , v , cc , bd
		
		This.Controls[ ++This.Index ] := { 	X:		10
										,	Y:		10
										,	W:		10
										,	H:		10	}
		for k, v in obj
			This.Controls[ This.Index ][ k ] := obj[ k ] 
		cc := This.Controls[ This.Index ]
		Gui, % This.Hwnd ":Add", Text, % "x" cc.X " y" cc.Y " w" cc.W " h" cc.H " hwndhwnd"
		This.Handles[ hwnd ] := This.Index
		This.Controls[ This.Index ].Hwnd := hwnd
		
		if( IsObject( cc.Label ) ){
			bd := cc.Label
			GuiControl, % This.Hwnd ":+G" , % hwnd , % bd
		}else{
			bd := This._TriggerCall.Bind( This )
			GuiControl, % This.Hwnd ":+G" , % hwnd , % bd
		}
		return hwnd
		
	}
	_TriggerCall(){
		MouseGetPos,,,, ctrl, 2
		Try
			;~ SetTimer, % This.Controls[ This.Handles[ ctrl ] ].Label, -0
			gosub, % This.Controls[ This.Handles[ ctrl ] ].Label
		
				
	}
	DrawTriggers( color := "0xFFFF0000" , AutoUpdate := 0 ){
		local brush , cc 
		Brush := Gdip_BrushCreateSolid( color ) 
		Gdip_SetSmoothingMode( This.G , 3 )
		loop, % This.Controls.Length()	{
			cc := This.Controls[ A_Index ]
			Gdip_FillRectangle( This.G , Brush , cc.x , cc.y , cc.w , cc.h )
		
		}
		Gdip_DeleteBrush( Brush )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	UpdateSettings( obj := "" , UpdateGraphics := 0 ){
		local k , v
		if( IsObject( obj ) )
			for k, v in obj
				This[ k ] := obj[ k ]
		( This.X = "Center" ) ? ( This.X := ( A_ScreenWidth - This.W ) / 2 ) 	
		( This.Y = "Center" ) ? ( This.Y := ( A_ScreenHeight - This.H ) / 2 ) 	
		if( UpdateGraphics ){
			This._DestroyWindowsGraphics()
			This._CreateWindowGraphics()
		}
	}
	_CreateWindow(){
		local hwnd
		Gui , New, % " +LastFound +E0x80000 hwndhwnd -Caption  " This.Options
		PopUpWindow.Index++
		This.Index := PopUpWindow.Index
		PopUpWindow.Windows[ PopUpWindow.Index ] := This
		This.Hwnd := hwnd
		PopUpWindow.Handles[ hwnd ] := PopUpWindow.Index
		if( This.GdipStartUp && !PopUpWindow.pToken )
			PopUpWindow.pToken := GDIP_STARTUP()
	}
	_DestroyWindowsGraphics(){
		Gdip_DeleteGraphics( This.G )
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
	}
	_CreateWindowGraphics(){
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
	}
	ShowWindow( Title := "" ){
		Gui , % This.Hwnd ":Show", % "x" This.X " y" This.Y " w" This.W " h" This.H " NA", % Title
	}
	HideWindow(){
		Gui , % This.Hwnd ":Hide",
	}
	UpdateWindow( alpha := 255 ){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H , alpha )
	}
	ClearWindow( AutoUpdate := 0 ){
		Gdip_GraphicsClear( This.G )
		if( Autoupdate )
			This.UpdateWindow()
	}
	DrawBitmap( pBitmap , obj , dispose := 1 , AutoUpdate := 0 ){
		Gdip_DrawImage( This.G , pBitmap , obj.X , obj.Y , obj.W , obj.H )
		if( dispose )
			Gdip_DisposeImage( pBitmap )
		if( Autoupdate )
			This.UpdateWindow()
	}
	PaintBackground( color := "0xFF000000" , AutoUpdate := 0 ){
		if( isObject( color ) ){
			Brush := Gdip_BrushCreateSolid( ( color.HasKey( "Color" ) ) ? ( color.Color ) : ( "0xFF000000" ) ) 
			if( color.Haskey( "Round" ) )
				Gdip_FillRoundedRectangle( This.G , Brush , color.X , color.Y , color.W , color.H , color.Round )
			else
				Gdip_FillRectangle( This.G , Brush , color.X , color.Y , color.W , color.H ) 
		}else{
			Brush := Gdip_BrushCreateSolid( color ) 
			Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W + 2 , This.H + 2 ) 
		}
		Gdip_DeleteBrush( Brush )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DeleteWindow( GDIPShutdown := 0 ){
		Gui, % This.Hwnd ":Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		hwnd := This.Hwnd
		for k, v in PopUpWindow.Windows[ Hwnd ]
			This[k] := ""
		PopUpWindow.Windows[ Hwnd ] := ""
		if( GDIPShutdown ){
			Gdip_Shutdown( PopUpWindow.pToken )
			PopUpWindow.pToken := ""
		}
	}
	_OnClose( wParam ){
		if( wParam = 0xF060 ){	;SC_CLOSE ;[ clicking on the gui close button ]
			Try{
				Gui, % PopUpWindow.HelperHwnd ":Destroy"
				SoundBeep, 555
			}
		}
	}
	CreateCachedBitmap( pBitmap , Dispose := 0 ){
		local pCachedBitmap
		if( This.CachedBitmap )
			This.DisposeCachedbitmap()
		DllCall( "gdiplus\GdipCreateCachedBitmap" , "Ptr" , pBitmap , "Ptr" , this.G , "PtrP" , pCachedBitmap )
		This.CachedBitmap := pCachedBitmap
		if( Dispose )
			Gdip_DisposeImage( pBitmap )
	}
	DrawCachedBitmap( AutoUpdate := 0 ){
		DllCall( "gdiplus\GdipDrawCachedBitmap" , "Ptr" , this.G , "Ptr" , This.CachedBitmap , "Int" , 0 , "Int" , 0 )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DisposeCachedbitmap(){
		DllCall( "gdiplus\GdipDeleteCachedBitmap" , "Ptr" , This.CachedBitmap )
	}
	Helper(){
		local hwnd , MethodList := ["__New","UpdateSettings","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow" , "AddTrigger" , "DrawTriggers", "CreateCachedBitmap" , "DrawCachedBitmap" , "DisposeCachedbitmap" ]
		Gui, New, +AlwaysOnTop +ToolWindow +HwndHwnd
		PopUpWindow.HelperHwnd := hwnd
		Gui, Add, Edit, xm ym w250 r1 Center hwndhwnd, Gui1
		PopUpWindow.EditHwnd := hwnd
		loop, % MethodList.Length()	
			Gui, Add, Button, xm y+1 w250 r1 gPopUpWindow._HelperClip, % MethodList[ A_Index ]
		Gui, Show,,
		OnMessage( 0x112 , This._OnClose.Bind( hwnd ) )
	}
	_HelperClip(){
		local ClipList 
		
		GuiControlGet, out, % PopUpWindow.HelperHwnd ":", % PopUpWindow.EditHwnd	
		
		ClipList := 		{ 	__New: 					" := New PopUpWindow( { AutoShow: 1 , X: 0 , Y: 0 , W: A_ScreenWidth , H: A_ScreenHeight , Options: "" -DPIScale +AlwaysOnTop "" } )"
							,	UpdateSettings:			".UpdateSettings( { X: """" , Y: """" , W: """" , H: """" } , UpdateGraphics := 0 )"
							,	ShowWindow:				".ShowWindow( Title := """" )"
							,	HideWindow:				".HideWindow()"
							,	UpdateWindow:			".UpdateWindow()"
							,	ClearWindow:			".ClearWindow( AutoUpdate := 0 )"
							,	DrawBitmap:				".DrawBitmap( pBitmap := """" , { X: 0 , Y: 0 , W: " Out ".W , H: " Out ".H } , dispose := 1 , AutoUpdate := 0 )"
							,	PaintBackground:		".PaintBackground( color := ""0xFF000000"" , AutoUpdate := 0 )  "  ";{ Color: ""0xFF000000"" , X: 2 , Y: 2 , W: " Out ".W - 4 , H: " Out ".H - 4 , Round: 10 }"
							,	DeleteWindow:			".DeleteWindow( GDIPShutdown := 0 )"
							,	AddTrigger:				".AddTrigger( { X: """" , Y: """" , W: """" , H: """" , Value: """" , Label: """" } )"	
							,	DrawTriggers:			".DrawTriggers( color := ""0xFFFF0000"" , AutoUpdate := 0 )"	
							,	CreateCachedBitmap:		".CreateCachedBitmap( pBitmap , Dispose := 0 )"	
							,	DrawCachedBitmap: 		".DrawCachedBitmap( AutoUpdate := 0 )"	
							,	DisposeCachedbitmap:	".DisposeCachedbitmap()"	}
							
		clipboard := Out ClipList[ A_GuiControl ]
		
	}
}
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

16 Jan 2023, 04:52

Dual Sided Vector Gauge.
20230116045023.png
20230116045023.png (73.52 KiB) Viewed 3454 times
gauge.gif
gauge.gif (528.51 KiB) Viewed 3454 times

Code: Select all

;****************************************************************************************************************************************************************************
#Include gdip.ahk 	;<<<<<<<<<<<<<<<<<<---------------------------      ;https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6517
;#Include <PopUpWindow_V2>	 ; Can be found in the post above this one. ;https://www.autohotkey.com/boards/posting.php?mode=reply&f=76&t=92039#pr502025
;****************************************************************************************************************************************************************************
#SingleInstance, Force
SetBatchLines, -1
Gdip_Startup()

Main := {}

Main.Parent := New PopUpWindow( { AutoShow: 1 , X: 500 , Y: 130 , W: 600 , H: 600 , Options: " -DPIScale +AlwaysOnTop " } )
Main.Parent.PaintBackground( { Color: "0x66000000" , X: 2 , Y: 2 , W: Main.Parent.W - 4 , H: Main.Parent.H - 4 , Round: 10 } , AutoUpdate := 1 )

Main.IntervalCount := 11


;~ Main.IntervalSpacing := 20
Main.IntervalSpacing := 15
;~ Main.IntervalSpacing := 12


;~ Main.PipWidth := 50
;~ Main.PipWidth := 20
;~ Main.PipWidth := 70
Main.PipWidth := 30


;~ Main.PipSize := 11
Main.PipSize := 13

Main.Value := 6
Main.Side := 0
Main.StartGap := 40
Main.HomeVector := { X: 300 , Y: 300 }

Main.IconVector := { X: 50 , Y: 50 }
;~ Main.IconVector := { X: 100 , Y: 450 }
;~ Main.IconVector := { X: 50 , Y: 300 }
;~ Main.IconVector := { X: 550 , Y: 250 }


Main.IconColor := "3399FF"

MyGauge := New GaugeClass( Main )

MyGauge._DrawLayer1()

return
GuiClose:
GuiContextMenu:
*ESC::ExitApp

RALT::PopUpWindow.Helper()


class GaugeClass	{

	__New( obj ){
		
		This._SetDefaults( obj )
		This._CreateWindows()
		This._CreateSegments()
		This._CreatePips()
		This._CreateMarkers()
		This._CreateValueDisplayVectors()
		
		This._SetValueTimer( 30 )
		
		
	}
	_SetDefaults( obj ){
		
		for k, v in obj
			This[ k ] := obj[ k ]
		
		This.Segments := []
		This.RedPips := []
		This.GreenPips := []
		This.RedMarkers := []
		This.GreenMarkers := []
		This.GreenValues := []
		This.RedValues := []
		This.PipThickness := []
		
		This.MasterLineVector := This._CopyVector( This.IconVector )
		This.MasterLineVector.Sub( This.HomeVector )
		
		
		This.RedRotatedVector := This._CopyVector( This.MasterLineVector , 1 , 0 )
		This.GreenRotatedVector := This._CopyVector( This.MasterLineVector , 1 , 1 )
		
		This.LastValue := This.Value
		This.LastSide := This.Side
		
		
		
		
		This.ValueTimer := This._CheckValue.Bind( This )
		
	}
	_CreateValueDisplayVectors(){
		This.RedRotatedVector.SetMag( This.PipWidth + This.PipWidth * 2 )
		This.GreenRotatedVector.SetMag( This.PipWidth + This.PipWidth * 2 )
		Loop, % This.IntervalCount	{
			;~ if( A_Index = 1 || !Mod( A_Index - 1 , 5 ) ){
				;~ This.RedRotatedVector.SetMag( This.PipWidth + This.PipWidth * 2 )
				;~ This.GreenRotatedVector.SetMag( This.PipWidth + This.PipWidth * 2 )
				
			;~ }else{
				;~ This.RedRotatedVector.SetMag( This.PipWidth * 0.7 + This.PipWidth * 2 )
				;~ This.GreenRotatedVector.SetMag( This.PipWidth * 0.7 + This.PipWidth * 2 )
			;~ }
			This.RedValues[ A_Index ] := This._CopyVector( This.Segments[ A_Index ] )
			This.RedValues[ A_Index ].Add( This.RedRotatedVector )
			
			This.GreenValues[ A_Index ] := This._CopyVector( This.Segments[ A_Index ] )
			This.GreenValues[ A_Index ].Add( This.GreenRotatedVector )
		}
		
	}
	_CreateSegments(){
		This.MasterLineVector.SetMag( This.StartGap )
		This.CurrentVector := This._CopyVector( This.HomeVector )
		This.CurrentVector.Add( This.MasterLineVector )
		This.Segments[ 1 ] := This._CopyVector( This.CurrentVector )
		This.MasterLineVector.SetMag( This.IntervalSpacing )
		Loop, % This.IntervalCount	{
			
			This.CurrentVector.Add( This.MasterLineVector )
			This.Segments[ A_Index + 1 ] := This._CopyVector( This.CurrentVector )
		}
	}
	_CreatePips(){
		
		local Index := 0
		
		This.RedRotatedVector.SetMag( This.PipWidth )
		This.GreenRotatedVector := This._CopyVector( This.MasterLineVector , 1 , 1 )
		
		Loop, % This.IntervalCount	{
			
		
		
			if( A_Index = 1 || !Mod( A_Index - 1 , 5 ) ){
				This.RedRotatedVector.SetMag( This.PipWidth )
				This.GreenRotatedVector.SetMag( This.PipWidth )
				This.PipThickness[ A_Index ] := This.PipSize
				
			}else{
				
				This.RedRotatedVector.SetMag( This.PipWidth * 0.7 )
				This.GreenRotatedVector.SetMag( This.PipWidth * 0.7 )
				This.PipThickness[ A_Index ] := This.PipSize - 2
			}
			This.RedPips[ A_index ] := This._CopyVector( This.Segments[ A_Index ] )
			This.RedPips[ A_Index ].Add( This.RedRotatedVector ) 
			
			This.GreenPips[ A_index ] := This._CopyVector( This.Segments[ A_Index ] )
			This.GreenPips[ A_Index ].Add( This.GreenRotatedVector )
		}
		
	}
	_CreateMarkers(){
		
		
		Loop, % This.IntervalCount	{
			
			if( A_Index = 1 || !Mod( A_Index - 1 , 5 ) ){
				
				This.RedRotatedVector.SetMag( This.PipWidth * 2 )
				This.GreenRotatedVector.SetMag( This.PipWidth * 2 )
				
			}else{
				This.RedRotatedVector.SetMag( ( This.PipWidth * 0.7 ) + This.PipWidth )
				This.GreenRotatedVector.SetMag( ( This.PipWidth * 0.7 ) + This.PipWidth )
			
			}
			
			This.RedMarkers[ A_Index ] := This._CopyVector( This.Segments[ A_Index ] )
			This.RedMarkers[ A_Index ].Add( This.RedRotatedVector )
			
			This.GreenMarkers[ A_Index ] := This._CopyVector( This.Segments[ A_Index ] )
			This.GreenMarkers[ A_Index ].Add( This.GreenRotatedVector )
			
		}
		
	}
	_CreateWindows(){
		This.Layer1 := New PopUpWindow( { AutoShow: 1 , X: 0 , Y: 0 , W: This.Parent.W , H: This.Parent.H , Options: " -DPIScale +AlwaysOnTop +Parent" This.Parent.Hwnd } )
		This.Layer2 := New PopUpWindow( { AutoShow: 1 , X: 1000 , Y: 730 , W: 800 , H: 150 , Options: " -DPIScale +AlwaysOnTop +Owner" This.Parent.Hwnd } )
	}
	_CopyVector( vector , rotate := 0 , direction := 0 ){
		if( !Rotate ){
			return New HB_Vector( vector.X , vector.Y )
		}else if( rotate && !direction ){
			return New HB_Vector( vector.Y * -1 , vector.X )
		}else{
			return New HB_Vector( vector.Y , vector.X * -1 )
		}
	}
	_DrawLayer1(){
		local Red := "FF0000" , Green := "00FF00" , width , height
		This.Layer1.ClearWindow()
		;~ This._DrawLine( This.Layer1.G , This.HomeVector , This.IconVector , "0xFFFFFF00" , 3 )
		
		;Draw Icons	
		This._FillCircle( This.Layer1.G , This.HomeVector.X - 32 , This.HomeVector.Y - 32 , color := "0x99" This.IconColor , width := 64 , height := 62 )
		This._FillCircle( This.Layer1.G , This.HomeVector.X - 30 , This.HomeVector.Y - 30 , color := "0x9922262a" , width := 60 , height := 60 )
		
		This._FillCircle( This.Layer1.G , This.IconVector.X - 32 , This.IconVector.Y - 32 , color := "0x99" This.IconColor , width := 64 , height := 62 )
		This._FillCircle( This.Layer1.G , This.IconVector.X - 30 , This.IconVector.Y - 30 , color := "0x9922262a" , width := 60 , height := 60 )
		
		
		;Draw Ticks
		Loop, % This.IntervalCount	{
			if( This.Value >= A_Index ){
				This._DrawLine( This.Layer1.G , This.RedPips[ A_index ] , This.Segments[ A_Index ] , ( This.Side ) ? ( "0xFF" Red ) : ( "0xFF" Green ) , This.PipThickness[ A_Index ] )
				
				This._DrawLine( This.Layer1.G , This.RedPips[ A_index ] , This.Segments[ A_Index ] , ( This.Side ) ? ( "0x99FFFFFF" ) : ( "0x99000000" ) , 1 )
				This._FillCircle( This.Layer1.G , This.RedPips[ A_index ].X - This.PipThickness[ A_Index ] / 2 , This.RedPips[ A_index ].Y - This.PipThickness[ A_Index ] / 2 , ( This.Side ) ? ( "0xFF" Red ) : ( "0xFF" Green ) , width := This.PipThickness[ A_Index ] , height := This.PipThickness[ A_Index ] )
				
				This._DrawLine( This.Layer1.G , This.GreenPips[ A_index ] , This.Segments[ A_Index ] , ( This.Side ) ? ( "0xFF" Red ) : ( "0xFF" Green )  , This.PipThickness[ A_Index ] )
				This._DrawLine( This.Layer1.G , This.GreenPips[ A_index ] , This.Segments[ A_Index ] , ( This.Side ) ? ( "0x99FFFFFF" ) : ( "0x99000000" ) , 1 )
				
				This._FillCircle( This.Layer1.G , This.GreenPips[ A_index ].X - This.PipThickness[ A_Index ] / 2 , This.GreenPips[ A_index ].Y - This.PipThickness[ A_Index ] / 2 , ( This.Side ) ? ( "0xFF" Red ) : ( "0xFF" Green ) , width := This.PipThickness[ A_Index ] , height := This.PipThickness[ A_Index ] )
			}else{
				
				This._DrawLine( This.Layer1.G , This.RedPips[ A_index ] , This.Segments[ A_Index ] , "0x9932363a" , This.PipThickness[ A_Index ] )
				This._DrawLine( This.Layer1.G , This.GreenPips[ A_index ] , This.Segments[ A_Index ] , "0x9932363a"  , This.PipThickness[ A_Index ] )
				
			}
		}
		;Draw markers
		Loop, % This.IntervalCount	{
			
			This._FillCircle( This.Layer1.G , This.RedMarkers[ A_Index ].X - This.PipThickness[ A_Index ] / 2 -2 , This.RedMarkers[ A_Index ].Y - This.PipThickness[ A_Index ] / 2 -2 , color := "0xFF" This.IconColor , width := This.PipThickness[ A_Index ] + 4 , height := This.PipThickness[ A_Index ] + 4 )
			This._FillCircle( This.Layer1.G , This.RedMarkers[ A_Index ].X - This.PipThickness[ A_Index ] / 2 , This.RedMarkers[ A_Index ].Y - This.PipThickness[ A_Index ] / 2 , color := "0xFF" Red , width := This.PipThickness[ A_Index ] , height := This.PipThickness[ A_Index ] )
			
			This._FillCircle( This.Layer1.G , This.GreenMarkers[ A_Index ].X - This.PipThickness[ A_Index ] / 2 -2 , This.GreenMarkers[ A_Index ].Y - This.PipThickness[ A_Index ] / 2 -2 , color := "0xFF" This.IconColor , width := This.PipThickness[ A_Index ] + 4 , height := This.PipThickness[ A_Index ] + 4 )
			This._FillCircle( This.Layer1.G , This.GreenMarkers[ A_Index ].X - This.PipThickness[ A_Index ] / 2 , This.GreenMarkers[ A_Index ].Y - This.PipThickness[ A_Index ] / 2 , color := "0xFF" Green , width := This.PipThickness[ A_Index ] , height := This.PipThickness[ A_Index ] )
		}
		
		if( This.Side && This.Value != 1 ){
			This._FillCircle( This.Layer1.G , This.RedValues[ This.Value ].X - 15 - 2 , This.RedValues[ This.Value ].Y - 15 - 2 , "0xFF" This.IconColor , 30 + 4 , 30 + 4 )
			This._FillCircle( This.Layer1.G , This.RedValues[ This.Value ].X - 15 , This.RedValues[ This.Value ].Y - 15 , "0xFF" Red , 30 , 30 )
			
			This._DrawText( This.Layer1.G , This.RedValues[ This.Value ].X - 15 + 2 , This.RedValues[ This.Value ].Y - 15 + 2 , This.Value - 1 ,  "0xFF000000" , 30 , 30 , options := " Center vCenter s22 " , type := "Impact" )
			This._DrawText( This.Layer1.G , This.RedValues[ This.Value ].X - 15 + 1 , This.RedValues[ This.Value ].Y - 15 + 1 , This.Value - 1 ,  "0xFFFFFFFF" , 30 , 30 , options := " Center vCenter s22 " , type := "Impact" )
		
			
		}else if( This.Value != 1 ){
			This._FillCircle( This.Layer1.G , This.GreenValues[ This.Value ].X - 15 - 2 , This.GreenValues[ This.Value ].Y - 15 - 2 , "0xFF" This.IconColor , 30 + 4 , 30 + 4 )
			This._FillCircle( This.Layer1.G , This.GreenValues[ This.Value ].X - 15 , This.GreenValues[ This.Value ].Y - 15 , "0xFF" Green , 30 , 30 )
			
			This._DrawText( This.Layer1.G , This.GreenValues[ This.Value ].X - 15 + 2 , This.GreenValues[ This.Value ].Y - 15 + 2 , This.Value - 1 ,  "0xFF000000" , 30 , 30 , options := " Center vCenter s22 " , type := "Impact" )
			This._DrawText( This.Layer1.G , This.GreenValues[ This.Value ].X - 15 + 1 , This.GreenValues[ This.Value ].Y - 15 + 1 , This.Value - 1 ,  "0xFFFFFFFF" , 30 , 30 , options := " Center vCenter s22 " , type := "Impact" )
		
		}else{
			
			This._FillCircle( This.Layer1.G , This.HomeVector.X - 15 - 2 , This.HomeVector.Y - 15 - 2 , "0xFF" This.IconColor , 30 + 4 , 30 + 4 )
			This._FillCircle( This.Layer1.G , This.HomeVector.X - 15 , This.HomeVector.Y - 15 , "0xFF" Red , 30 , 30 )
			This._DrawText( This.Layer1.G , This.HomeVector.X - 15 + 2 , This.HomeVector.Y - 15 + 2 , "X" ,  "0xFF000000" , 30 , 30 , options := " Center vCenter s22 " , type := "Impact" )
			This._DrawText( This.Layer1.G , This.HomeVector.X - 15 + 1 , This.HomeVector.Y - 15 + 1 , "X" ,  "0xFFFFFFFF" , 30 , 30 , options := " Center vCenter s22 " , type := "Impact" )
		}
		
		This.Layer1.UpdateWindow()
	}
	_DrawLine( G , vector1 , vector2 , Color := "0xFFFF0000" , Thickness := 3 ){
		Pen := Gdip_CreatePen( color , thickness ) , Gdip_DrawLine( G , Pen , vector1.x , vector1.y , vector2.x , vector2.y ) , Gdip_DeletePen( Pen )
	}
	_FillCircle( G , x , y , color := "0xFFFF0000" , width := 30 , height := 30 ){
		Brush := Gdip_BrushCreateSolid( color ) , Gdip_FillEllipse( G , Brush , x , y , width , height ) , Gdip_DeleteBrush( Brush )
	}
	_DrawText( G , x , y , text ,  color , width , height , options := " Center vCenter Bold s12 " , type := "comic Sans MS" ){
		Brush := Gdip_BrushCreateSolid( color ) , Gdip_TextToGraphics( G , text , options " c" brush " x" x " y" y  , type , width , height ) , Gdip_DeleteBrush( Brush )
	}
	_SetValueTimer( value := "Off" ){
		local timer := This.ValueTimer
		SetTimer, % timer , % value
	}
	_CheckValue(){
		local CT := 1000
		CoordMode, Mouse , Screen
		MouseGetPos, x , y
		
		This.CurrentVector := New HB_Vector( x - This.Parent.X , y - This.Parent.Y )
		
		Loop, % This.IntervalCount	{
			
			if( ( dist := This.CurrentVector.Dist( This.Segments[ A_Index ] ) ) < 80 && dist < ct ){
				ct := dist
				This.Value := A_Index 
			}
		}
		if( ct > 80 )
			This.Value := 1
		if( This.CurrentVector.Dist( This.RedMarkers[ This.Value ] ) <= This.CurrentVector.Dist( This.GreenMarkers[ This.Value ] ) )
			This.Side := 1
		else
			This.Side := 0
		This._DrawLayer1()
	}
}
;****************************************************************
Class HB_Vector	{
	__New( x := 0 , y := 0 ){
		This.X := x
		This.Y := y
	}
	Add( Other_HB_Vector ){
		This.X += Other_HB_Vector.X
		This.Y += Other_HB_Vector.Y
	}
	Sub( Other_HB_Vector ){
		This.X -= Other_HB_Vector.X
		This.Y -= Other_HB_Vector.Y
	}
	mag(){
		return Sqrt( This.X * This.X + This.Y * This.Y )
	}
	magsq(){
		return This.Mag()**2
	}	
	setMag(in1){
		local m := This.Mag()
		This.X := This.X * in1 / m
		This.Y := This.Y * in1 / m
		return This
	}
	mult( in1 , in2 := "" , in3 := "" , in4 := "" , in5 := "" ){
		if( IsObject( in1 ) && in2 = "" ){
			This.X *= In1.X 
			This.Y *= In1.Y 
		}else if( !IsObject( In1 ) && In2 = "" ){
			This.X *= In1
			This.Y *= In1
		}else if( !IsObject( In1 ) && IsObject( In2 ) ){
			This.X *= In1 * In2.X
			This.Y *= In1 * In2.Y
		}else if( IsObject( In1 ) && IsObject( In2 ) ){
			This.X *= In1.X * In2.X
			This.Y *= In1.Y * In2.Y
		}	
	}
	div( in1 , in2 := "" , in3 := "" , in4 := "" , in5 := "" ){
		if( IsObject( in1 ) && in2 = "" ){
			This.X /= In1.X 
			This.Y /= In1.Y 
		}else if( !IsObject( In1 ) && In2 = "" ){
			This.X /= In1
			This.Y /= In1
		}else if( !IsObject( In1 ) && IsObject( In2 ) ){
			This.X /= In1 / In2.X
			This.Y /= In1 / In2.Y
		}else if( IsObject( In1 ) && IsObject( In2 ) ){
			This.X /= In1.X / In2.X
			This.Y /= In1.Y / In2.Y
		}	
	}
	dist( in1 ){
		return Sqrt( ( ( This.X - In1.X ) **2 ) + ( ( This.Y - In1.Y ) **2 ) )
	}
	dot( in1 ){
		return ( This.X * in1.X ) + ( This.Y * In1.Y )
	}
	cross( in1 ){
		return This.X * In1.Y - This.Y * In1.X
	}
	Norm(){
		local m := This.Mag()
		This.X /= m
		This.Y /= m
	}
}
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

16 Jan 2023, 09:00

Simple Polygon function.
polygon function 1.gif
polygon function 1.gif (576.65 KiB) Viewed 3439 times

Code: Select all

;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;Function: PolygonShapes 
;Written By: Hellbent
;Date: Jan 16th, 2023
;Last Edit: Jan 18th, 2023 
;Changes:
;Can now set it so that the return string has an extra wrap to close the shape. ( used for "DRAWLINES" or "DRAWPOLYGON" )
;Requires: Vectors class ( #Include <HB Vectors v2> )
;Returns a string or an array of points for a simple closed polygon shape. 
;HomeVector: { X: x position , Y: y position } give an obj with x and y keys. 
;			This is the center of your shape.
;Radius: The radius to use for the shape. How big the shape will be
;StartAngle: The point for the first side of the shape. The rotaion of the shape.
;Sides: The number of sides the shape should have. 3 or more sides
;returnString: Set the fuction to return a "string" of points or an [ array ] of points 
PolygonShapes( HomeVector , Radius := 100 , StartAngle := 0 , Sides := 4 , returnString := 1 , AddExtraWrapArm := 0 ){
	local StartVector , points , SpacingAngle , OutputString
	if( sides < 3 ){
		MsgBox, 262192, Error , A shape requires 3 or more sides.`nWhat you're thinking of is a line or a point.
		return
	}
	StartVector := New Vector( HomeVector )
	StartVector.SetMag( Radius )
	StartVector.SetAngle( StartAngle )
	SpacingAngle := 360 / Sides
	Points := []
	Points[ 1 ] := New Vector( StartVector )
	Points[ 1 ].Add( HomeVector )
	if( returnString )
		OutputString := Points[ 1 ].X "," Points[ 1 ].Y "|"
	Loop, % Sides - 1	{
		StartVector := StartVector.RotateAngle( SpacingAngle , 1 )
		Points[ A_Index + 1 ] := New Vector( StartVector )
		Points[ A_Index + 1 ].Add( HomeVector )
		if( returnString )
			OutputString .= Points[ A_Index + 1 ].X "," Points[ A_Index + 1 ].Y "|"
	}
	if( returnString ){
		OutputString .= Points[ 1 ].X "," Points[ 1 ].Y "|"
		if( AddExtraWrapArm ) ;Adds an extra overlap so that when you use "DrawLines" the shape fully closes regardless of the thickness of the lines.
			OutputString .= Points[ 2 ].X "," Points[ 2 ].Y "|"
		return OutputString
	}
	return Points
}
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
working example

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib> ;<<<<<<<<<<<<<<<<<<---------------------------     gdip.ahk
#Include <PopUpWindow_V2> ; in a previous post
#Include <HB Vectors v2>  ; in a previous post
;****************************************************************************************************************************************************************************
#SingleInstance, force
SetBatchLines, -1
Gdip_Startup()

Gui1 := New PopUpWindow( { AutoShow: 1 , X: 350 , Y: 200 , W: 500 , H: 500 , Options: " -DPIScale +AlwaysOnTop " } )

MyShape := PolygonShapes( New Vector( 250 , 250 ) , Gui1.Radius := 100 , Gui1.angle := 90 , Gui1.Sides := 3 )

FillPolygon( Gui1.G , MyShape , Color := "0xFFFFFF00" )
DrawPolygon( Gui1.G , MyShape , Color := "0xFF000000" , 3 )

Gui1.UpdateWindow()

Gui1.angleRate := 1
Sleep, 1000
SetTimer, Rotate , 10
return
GuiContextMenu:
*ESC::ExitApp

Rotate:
	if( GetKeyState( "Shift" ) ){
		MouseGetPos sx , sy 
		Gui1.angle := 0
		While( GetKeyState( "Shift" ) ){
			MouseGetPos nx , ny 
			Gui1.Sides := floor( abs( sx - nx ) / 10 ) + 3
			ToolTip, % "Sides: " Gui1.Sides
			gosub, DrawWindow
			sleep, 10
		}
		ToolTip,
		return
	}else if( GetKeyState( "ctrl" ) ){
		MouseGetPos sx , sy 
		While( GetKeyState( "ctrl" ) ){
			MouseGetPos nx , ny 
			Gui1.angleRate := floor( ( sx - nx ) / 10 ) + 1
			Gui1.angle += Gui1.angleRate
			ToolTip, % "Rotation Rate: " Gui1.angleRate " Deg"
			gosub, DrawWindow
			sleep, 10
		}
		ToolTip,
		return
	}
	Gui1.angle += Gui1.angleRate
	gosub, DrawWindow
	return
	
DrawWindow:
	MyShape := PolygonShapes( New Vector( 250 , 250 ) , Gui1.Radius , Gui1.angle , Gui1.Sides )
	Gui1.ClearWindow()
	FillPolygon( Gui1.G , MyShape , Color := "0xFFFF0000" )
	DrawPolygon( Gui1.G , MyShape , Color := "0xFF000000" , 3 )
	Gui1.UpdateWindow()
	return
	
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
FillPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFFFF0000" ){
	Brush := Gdip_BrushCreateSolid( Color ) , Gdip_FillPolygon( G , Brush , Points ) , Gdip_DeleteBrush( Brush )
}
DrawPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFF000000" , Thickness := 3 ){
	Pen := Gdip_CreatePen( Color , Thickness ) , Gdip_DrawLines( G , Pen , Points ) , Gdip_DeletePen( Pen )
}
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;
;| ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) | ((((()))))***^|^***((((())))) |;


;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;Function: PolygonShapes 
;Written By: Hellbent
;Date: Jan 16th, 2023
;Last Edit: Jan 18th, 2023 
;Changes:
;Can now set it so that the return string has an extra wrap to close the shape. ( used for "DRAWLINES" or "DRAWPOLYGON" )
;Requires: Vectors class ( #Include <HB Vectors v2> )
;Returns a string or an array of points for a simple closed polygon shape. 
;HomeVector: { X: x position , Y: y position } give an obj with x and y keys. 
;			This is the center of your shape.
;Radius: The radius to use for the shape. How big the shape will be
;StartAngle: The point for the first side of the shape. The rotaion of the shape.
;Sides: The number of sides the shape should have. 3 or more sides
;returnString: Set the fuction to return a "string" of points or an [ array ] of points 
PolygonShapes( HomeVector , Radius := 100 , StartAngle := 0 , Sides := 4 , returnString := 1 , AddExtraWrapArm := 0 ){
	local StartVector , points , SpacingAngle , OutputString
	if( sides < 3 ){
		MsgBox, 262192, Error , A shape requires 3 or more sides.`nWhat you're thinking of is a line or a point.
		return
	}
	StartVector := New Vector( HomeVector )
	StartVector.SetMag( Radius )
	StartVector.SetAngle( StartAngle )
	SpacingAngle := 360 / Sides
	Points := []
	Points[ 1 ] := New Vector( StartVector )
	Points[ 1 ].Add( HomeVector )
	if( returnString )
		OutputString := Points[ 1 ].X "," Points[ 1 ].Y "|"
	Loop, % Sides - 1	{
		StartVector := StartVector.RotateAngle( SpacingAngle , 1 )
		Points[ A_Index + 1 ] := New Vector( StartVector )
		Points[ A_Index + 1 ].Add( HomeVector )
		if( returnString )
			OutputString .= Points[ A_Index + 1 ].X "," Points[ A_Index + 1 ].Y "|"
	}
	if( returnString ){
		OutputString .= Points[ 1 ].X "," Points[ 1 ].Y "|"
		if( AddExtraWrapArm ) ;Adds an extra overlap so that when you use "DrawLines" the shape fully closes regardless of the thickness of the lines.
			OutputString .= Points[ 2 ].X "," Points[ 2 ].Y "|"
		return OutputString
	}
	return Points
}
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
;|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|<( )>|
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

20 Jan 2023, 23:50

I made a little tool to use to get the values for this arrow class: viewtopic.php?f=76&t=92039#p479129

.
ArrowHead 2 Editor.gif
ArrowHead 2 Editor.gif (430.18 KiB) Viewed 3370 times

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib> ;<<<-------------- gdip.ahk
#Include <PopUpWindow_V2> ; In a prv post in this thread.
#Include <ArrowHead_2> ; In a prv post in this thread.
;****************************************************************************************************************************************************************************
#SingleInstance, Force
SetBatchLines, -1
global gdiplus := LoadLibrary("gdiplus")
Gdip_Startup()
Gui1 := New PopUpWindow( { AutoShow: 1 , X: 1100 , Y: 220 , W: 410 , H: 310 , Options: " -DPIScale +AlwaysOnTop " } )
Gui1.Controls := {}
Gui1.Controls.Head := { X: 340 , Y: 80 , W: 50 , H: 30 , Value: 25 }
Gui1.Controls.Neck := { X: 340 , Y: 140 , W: 50 , H: 30 , Value: 7 }
Gui1.Controls.Arm := { X: 340 , Y: 200 , W: 50 , H: 30 , Value: 15 }
Gui1.Controls.Elbow := { X: 340 , Y: 260 , W: 50 , H: 30 , Value: 5 }
Gui1.Controls.Arrow := { X: 15 , Y: 75 , W: 310 , H: 220 , BGColor: "0xaa004444" , ArrowColor: "0xFF22262a" , ArrowBorderColor: "0xFF62666a" }
Gui1.Controls.Move := { X: 15 , Y: 15 , W: 340 , H: 60 }
Gui1.Controls.Close := { X: 364 , Y: 15 , W: 30 , H: 30 }
blackAndWhite := [ "0x33004444" , "0x44FFFFFF" , "0x33aaaaaa" , "0x6622262a"  ]
BAndWSize := [ 9 , 6 , 5 , 3 ]
Gui1.MyString := New BubbleText( { Text: "ArrowHead 2" , FontColor: "0xFF009999" , FontSize: 39 , FontType: "Ink Free" , FullWrap: 0 } , blackAndWhite , BAndWsize )
DrawWindow( Gui1 )
OnMessage( 0x201 , func( "WindowClick" ).Bind( Gui1 ) )
OnMessage( 0x020A , func( "WheelChange" ).bind( Gui1 ) )
return
GuiClose:
GuiContextMenu:
*ESC::ExitApp
RALT::PopUpWindow.Helper()
WindowClick( Gui1 , l , w , msg , hwnd ){
	if( Gui1.Hwnd != hwnd )
		return 1
	CoordMode, Mouse, Screen 
	MouseGetPos, x, y
	x -= Gui1.X
	y -= Gui1.Y
	for k , v in [ "Arrow" , "Move" , "Close" ] {
		cc := Gui1.Controls[ v ]
		if( x >= cc.X && x <= cc.X + cc.W && y >= cc.Y && y <= cc.Y + cc.H ){
			if( k = 1 ){
				if( GetKeyState( "Shift" ) && GetKeyState( "Ctrl" ) ){
					Gui1.Controls.Arrow.BGColor := GetColor()
				}else if( GetKeyState( "Shift" ) ){
					Gui1.Controls.Arrow.ArrowColor := GetColor()
				}else if( GetKeyState( "Ctrl" ) ){
					Gui1.Controls.Arrow.ArrowBorderColor := GetColor()
				}else{
					return
				}
				DrawWindow( Gui1 )
			}else if( k = 2 ){
				MoveWindow( Gui1 )
			}else if( k = 3 ){
				ExitApp
			}
		}
	}
}
MoveWindow( Gui1 ){
	PostMessage, 0xA1, 2
	While( GetKeyState( "LButton" , "P" ) )
		Sleep, 30
	WinGetPos, x, y,,, % "ahk_id " Gui1.Hwnd
	Gui1.UpdateSettings( { X: x , Y: y } )
}
GetColor(){
	CoordMode, Mouse, Screen
	CoordMode, Pixel, Screen
	While( GetKeyState( "Shift" ) || GetKeyState( "ctrl" ) )
		Sleep, 30
	ColorGui := New PopUpWindow( { AutoShow: 1 , X: 0 , Y: 0 , W: 40 , H: 40 , Options: " -DPIScale +AlwaysOnTop +ToolWindow" } )
	While( !GetKeyState( "ctrl" ) ){
		ToolTip, Move your cursor over a color and then press "ctrl".
		MouseGetPos, x , y
		PixelGetColor, color , x , y , RGB 
		ColorGui.UpdateSettings( { X: x + 40 , Y: y - 60 } )
		ColorGui.ClearWindow()
		ColorGui.PaintBackground( { Color: "0xFF000000" , X: 1 , Y: 1 , W: ColorGui.W - 2 , H: ColorGui.H - 2 , Round: 10 } , 1 )
		ColorGui.PaintBackground( { Color: "0xFF" SubStr( color , 3 ) , X: 2 , Y: 2 , W: ColorGui.W - 4 , H: ColorGui.H - 4 , Round: 10 } , 1 )
	}
	ColorGui.DeleteWindow()
	ToolTip,
	return "0xFF" SubStr( color , 3 )
}
WheelChange( Gui1 , input , l , msg , hwnd ){
	if( Gui1.Hwnd != hwnd )
		return 1
	CoordMode, Mouse, Screen 
	MouseGetPos, x, y
	x -= Gui1.X
	y -= Gui1.Y
	Dir := ( ( input >> 16 ) > 0x7FFF ) || ( ( input < 0 ) ? ( 1 ) : ( 0 ) )
	change := 0
	for k , v in Gui1.Controls	{
		cc := Gui1.Controls[ k ]
		if( x >= cc.X && x <= cc.X + cc.W && y >= cc.Y && y <= cc.Y + cc.H ){
			if( Dir ){
				if( GetKeyState( "Shift" ) ){
					cc.Value -= 10
						
				}else{
						--cc.Value
				}
			}else if( !Dir ){
				if( GetKeyState( "Shift" ) )
					cc.Value += 10
				else
					cc.Value += 1
			}
			Sleep, 30
			DrawWindow( Gui1 )
			return -1
		}
	}
}
DrawWindow( Gui1 ){
	Gui1.ClearWindow()
	Gui1.DrawBitmap( ArrowHeadEditor( Gui1 ) , { X: 0 , Y: 0 , W: Gui1.W , H: Gui1.H } , dispose := 1 )
	MyArrow := New ArrowHead_2( { X: 30 , Y: 280 } , { X: 300 , Y: 100 } , Gui1.Controls.Head.Value , Gui1.Controls.Neck.Value , Gui1.Controls.Arm.Value , Gui1.Controls.Elbow.Value )
	_FillPolygon( Gui1.G , MyArrow , Gui1.Controls.Arrow.ArrowColor )
	_DrawPolygon( Gui1.G , MyArrow , Gui1.Controls.Arrow.ArrowBorderColor , Thickness := 3 )
	Gui1.UpdateWindow()
}
_FillPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFFFF0000" ){
	Brush := Gdip_BrushCreateSolid( Color ) , Gdip_FillPolygon( G , Brush , Points ) , Gdip_DeleteBrush( Brush )
}
_DrawPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFF000000" , Thickness := 3 ){
	Pen := Gdip_CreatePen( Color , Thickness ) , Gdip_DrawLines( G , Pen , Points ) , Gdip_DeletePen( Pen )
}
ArrowHeadEditor( Gui1 , ScaleFactor := 1 ){
	;Bitmap Created Using: HB Bitmap Maker
	pBitmap := Gdip_CreateBitmap( 410 * ScaleFactor , 310 * ScaleFactor ) , G := Gdip_GraphicsFromImage( pBitmap ) , Gdip_SetSmoothingMode( G , 2 )
	Brush := Gdip_CreateLineBrushFromRect( 1 * ScaleFactor , 4 * ScaleFactor , 403 * ScaleFactor , 300 * ScaleFactor , "0x99F0F0F0" , "0x99000000" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 5 * ScaleFactor , 5 * ScaleFactor , 400 * ScaleFactor , 300 * ScaleFactor , 15 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 6 * ScaleFactor , 7 * ScaleFactor , 399 * ScaleFactor , 298 * ScaleFactor , "0x66F0F0F0" , "0x66000000" , 2 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 5 * ScaleFactor , 5 * ScaleFactor , 400 * ScaleFactor , 300 * ScaleFactor , 15 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 6 * ScaleFactor , 7 * ScaleFactor , 399 * ScaleFactor , 298 * ScaleFactor , "0x33F0F0F0" , "0x33000000" , 3 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 5 * ScaleFactor , 5 * ScaleFactor , 400 * ScaleFactor , 300 * ScaleFactor , 15 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 7 * ScaleFactor , 7 * ScaleFactor , 397 * ScaleFactor , 294 * ScaleFactor , "0x99FFFFFF" , "0x99000000" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 3 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawRoundedRectangle( G , Pen , 5 * ScaleFactor , 5 * ScaleFactor , 400 * ScaleFactor , 300 * ScaleFactor , 15 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Gdip_DrawImage( G , Gui1.MyString.Bitmap, 40 , 5 , Gui1.MyString.Width , Gui1.MyString.Height )
	Brush := Gdip_BrushCreateSolid( "0xFF444444" ) , Gdip_FillRoundedRectangle( G , Brush , 364 * ScaleFactor , 15 * ScaleFactor , 30 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x99F0F0F0" ) , Gdip_TextToGraphics( G , "x" , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 355 * ScaleFactor " y" 5 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 50 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( Gui1.Controls.Arrow.BGColor ) , Gdip_FillRoundedRectangle( G , Brush , 15 * ScaleFactor , 75 * ScaleFactor , 310 * ScaleFactor , 220 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF444444" ) , Gdip_FillRoundedRectangle( G , Brush , 335 * ScaleFactor , 55 * ScaleFactor , 60 * ScaleFactor , 240 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x99333333" ) , Gdip_TextToGraphics( G , "Head" , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 342 * ScaleFactor " y" 54 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x99F0F0F0" ) , Gdip_TextToGraphics( G , "Head" , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 341 * ScaleFactor " y" 53 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF333333" ) , Gdip_FillRoundedRectangle( G , Brush , 340 * ScaleFactor , 80 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_TextToGraphics( G , Gui1.Controls.Head.Value , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 340 * ScaleFactor " y" 80 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x99333333" ) , Gdip_TextToGraphics( G , "Neck" , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 342 * ScaleFactor " y" 114 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x99F0F0F0" ) , Gdip_TextToGraphics( G , "Neck" , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 341 * ScaleFactor " y" 113 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF333333" ) , Gdip_FillRoundedRectangle( G , Brush , 340 * ScaleFactor , 140 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_TextToGraphics( G , Gui1.Controls.Neck.Value , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 340 * ScaleFactor " y" 140 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x99333333" ) , Gdip_TextToGraphics( G , "Arm" , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 342 * ScaleFactor " y" 174 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x99F0F0F0" ) , Gdip_TextToGraphics( G , "Arm" , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 341 * ScaleFactor " y" 173 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF333333" ) , Gdip_FillRoundedRectangle( G , Brush , 340 * ScaleFactor , 200 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_TextToGraphics( G , Gui1.Controls.Arm.Value , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 340 * ScaleFactor " y" 200 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x99333333" ) , Gdip_TextToGraphics( G , "Elbow" , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 336 * ScaleFactor " y" 234 * ScaleFactor  , "Segoe UI" , 60 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x99F0F0F0" ) , Gdip_TextToGraphics( G , "Elbow" , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 336 * ScaleFactor " y" 233 * ScaleFactor  , "Segoe UI" , 60 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF333333" ) , Gdip_FillRoundedRectangle( G , Brush , 340 * ScaleFactor , 260 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_TextToGraphics( G , Gui1.Controls.Elbow.Value , "s" 16 * ScaleFactor " Center vCenter Bold c" Brush " x" 340 * ScaleFactor " y" 260 * ScaleFactor  , "Segoe UI" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Gdip_DeleteGraphics( G )
	return pBitmap
}
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;Color Text class
;Written By: Hellbent
;Date: Jan 18th , 2023
;Last Edit: Jan 20th , 2023
;Change: Can now set to use a pie shape to do a drop shadow. [ Key: FullWrap | Values: 0/1 ]
;Thanks To: jNizM (  https://www.autohotkey.com/boards/viewtopic.php?f=76&t=112861#p502745 )
class BubbleText	{
	__New( obj := "" , Colors := "0xFF000000" , Sizes := 2 ){
		This._SetDefaults()
		This._UpdateDefaults( obj , Colors , Sizes )
		This._CreateBitmaps()
		This._LiquidatePixels()
		return This.Output
	}
	
	_SetDefaults(){
		This.Text := "Hello World"
		This.FontType := "Comic Sans MS"
		This.FontSize := 16
		This.FontColor := "0xFFFFFFFF"
		This.FontOptions := " Center vCenter "
		This.BackgroundColor := ""
		This.StringHeight := ""
		This.StringWidth := ""
		This.TextBitmap := ""
		This.Bitmaps := []
		This.Colors := []
		This.SizeInterval := 1
		This.Smoothing := 4
		This.RedRange := 128
		This.GreenRange := 128
		This.BlueRange := 128
		This.FullWrap := 1
	}
	
	_UpdateDefaults( obj := "" , Colors := "0xFF000000" , Sizes := 2 ){ 
		for k , v in obj	
			This[ k ] := obj[ k ]
		if( IsObject( Colors ) ){
			for k , v in Colors
				This.Colors[ A_Index ] := Colors[ A_Index ]
		}else if( colors != "" ){
			This.Colors[ 1 ] := colors
		}
		if( IsObject( Sizes ) ){
			for k , v in Sizes
				This.Sizes[ A_Index ] := Sizes[ A_Index ]
		}else if( Sizes != "" ){
			This.Sizes[ 1 ] := Sizes
		}
		if( ( dif := This.Sizes.Length() - This.Colors.Length() ) < 0 ){
			index := This.Sizes.Length()
			loop, % dif	{
				This.Sizes[ index + A_Index ] := This.Sizes[ index + A_Index - 1 ] - This.SizeInterval
			}
		}else if( ( dif := This.Colors.Length() - This.Sizes.Length() ) < 0 ){
			index := This.Colors.Length()
			loop, % dif	{
				This.Colors[ index + A_Index ] := This.Colors[ index + A_Index - 1 ] 
			}
		}
	}
	
	_CreateBitmaps(){
		This.StringWidth := This._GetTextSize( 1 , This.Text ) 
		This.StringHeight := This._GetTextSize( 2 , This.Text ) / 1.05
		This.TextBitmap := Gdip_CreateBitmap( This.StringWidth , This.StringHeight )
		This.TextBitmapGraphics := Gdip_GraphicsFromImage( This.TextBitmap )
		Gdip_SetSmoothingMode( This.TextBitmapGraphics , This.Smoothing )
		if( This.BackgroundColor != ""){
			Brush := Gdip_BrushCreateSolid( This.BackgroundColor )
			Gdip_FillRectangle( This.TextBitmapGraphics , Brush, -10 , -10 , This.StringWidth + 20 , This.StringHeight + 20 )
			Gdip_DeleteBrush( Brush )
		}
		Brush := Gdip_BrushCreateSolid( This.FontColor )
		Gdip_TextToGraphics( This.TextBitmapGraphics , This.Text , " s" This.Fontsize " c" Brush " " This.FontOptions " x" 0 " y" 0 , This.FontType , This.StringWidth, This.StringHeight  )
		Gdip_DeleteBrush( Brush )
		This.MaxSize := 0
		Loop, % This.Sizes.Length()	{
			if( This.Sizes[ A_Index ] > This.MaxSize ){
				This.MaxSize := This.Sizes[ A_Index ]
			}
		}
		Loop, % This.Colors.Length()	{
			This.Bitmaps[ A_Index ] := {}
			This.Bitmaps[ A_Index ].Bitmap := Gdip_CreateBitmap( This.StringWidth + 2 * This.MaxSize + 4 , This.StringHeight + 2 * This.MaxSize + 4 )
			This.Bitmaps[ A_Index ].Graphics := Gdip_GraphicsFromImage( This.Bitmaps[ A_Index ].Bitmap )
			Gdip_SetSmoothingMode( This.Bitmaps[ A_Index ].Graphics , This.Smoothing )
		}
		This.Output := {}
		This.Output.Width := This.StringWidth + 2 * This.MaxSize + 4
		This.Output.Height := This.StringHeight + 2 * This.MaxSize + 4
		This.Output.Bitmap := Gdip_CreateBitmap( This.Output.Width , This.Output.Height )
		This.Output.Graphics := Gdip_GraphicsFromImage( This.Output.Bitmap )
	}
	
	_GetTextSize( outputType := 0 , String := "" ){ ; 0 = all , 1 = width , 2 = height 
		local pBitmap, G, Brush, temparr 
		pBitmap := Gdip_CreateBitmap( 10,10), G := Gdip_GraphicsFromImage( pBitmap ), Gdip_SetSmoothingMode( G , 2 )
		Brush := Gdip_BrushCreateSolid( "0xFF000000")
		temparr := StrSplit( Gdip_TextToGraphics( G , ( String != "" ) ? ( String ) : ( "T" ) , " s" This.Fontsize " c" Brush " " This.FontOptions " x" 0 " y" 0 , This.FontType , 10000, 10000  ),"|","|"  )
		Gdip_DeleteBrush( Brush ), Gdip_DeleteGraphics( G ), Gdip_DisposeImage( pBitmap )
		if( outputType = 0 )
			return temparr
		else if( outputType = 1 )
			return temparr[ 3 ]
		else if( outputType = 2 )
			return temparr[ 4 ]
	}
	
	_GetGray( OUTPUTCOLOR ){ ;From HB color picker v2
		StringTrimLeft,OUTPUTCOLOR,OUTPUTCOLOR,2
		StringLeft , r ,  OUTPUTCOLOR , 2
		StringTrimLeft,OUTPUTCOLOR,OUTPUTCOLOR,2
		StringLeft , g ,  OUTPUTCOLOR , 2
		StringTrimLeft,OUTPUTCOLOR,OUTPUTCOLOR,2
		StringLeft , b ,  OUTPUTCOLOR , 2
		r := "0x" r , g := "0x" g , b := "0x" b
		REDSLIDERVALUE:=r+0,GreenSLIDERVALUE:=g+0,BlueSLIDERVALUE:=b+0
		GreyScaleSLIDERVALUE:=Round((REDSLIDERVALUE+GreenSLIDERVALUE+BlueSLIDERVALUE)/3)
		return GreyScaleSLIDERVALUE
	}
	_LiquidatePixels(){
		local x , y , brushes := [] , Ptr := A_PtrSize ? "UPtr" : "UInt" 
		Loop, % This.Colors.Length()	
			Brushes[ A_Index ] := Gdip_BrushCreateSolid( This.Colors[ A_Index ] )
		y := 0
		Loop, % This.StringHeight 	{
			x := 0
			Loop, % This.StringWidth	{
				SetFormat, IntegerFast, hex
				DllCall( gdiplus.GdipBitmapGetPixel , Ptr , This.TextBitmap, "int", x, "int", y, "uint*", col )
				if( col != 0x0 ){
					Loop, % This.Bitmaps.Length()	{
						if( This.FullWrap ){
							DllCall( gdiplus.GdipFillEllipse , Ptr, This.Bitmaps[ A_Index ].Graphics, Ptr, Brushes[ A_Index ] , "float", x + This.MaxSize + 2 - This.Sizes[ A_Index ] , "float", y + This.MaxSize + 2 - This.Sizes[ A_Index ] , "float", 2 * This.Sizes[ A_Index ] , "float", 2 * This.Sizes[ A_Index ] )
						}else{
							DllCall( gdiplus.GdipFillPie , Ptr, This.Bitmaps[ A_Index ].Graphics , Ptr, Brushes[ A_Index ] , "float", x + This.MaxSize + 2 - This.Sizes[ A_Index ] , "float", y + This.MaxSize + 2 - This.Sizes[ A_Index ] , "float", 2 * This.Sizes[ A_Index ] , "float", 2 * This.Sizes[ A_Index ] , "float", 0 , "float", 90)
						}
					}
				}
				SetFormat, IntegerFast, dec
				x++
			}
			y++
		}
		Loop, % This.Bitmaps.Length()	{
			Gdip_DeleteGraphics( This.Bitmaps[ A_Index ].Graphics )
			Gdip_DrawImage( This.Output.Graphics , This.Bitmaps[ A_Index ].Bitmap , 0 , 0 , This.Output.Width , This.Output.Height )
		}
		if( This.BackgroundColor = "" )
			Gdip_DrawImage( This.Output.Graphics , This.TextBitmap , This.MaxSize + 2 , This.MaxSize + 2 , This.StringWidth , This.StringHeight )
		else{
			Gdip_DeleteGraphics( This.TextBitmapGraphics )
			Gdip_DisposeImage( This.TextBitmap )
			This.TextBitmap := Gdip_CreateBitmap( This.StringWidth , This.StringHeight )
			This.TextBitmapGraphics := Gdip_GraphicsFromImage( This.TextBitmap )
			Gdip_SetSmoothingMode( This.TextBitmapGraphics , This.Smoothing )
			Brush := Gdip_BrushCreateSolid( This.FontColor )
			Gdip_TextToGraphics( This.TextBitmapGraphics , This.Text , " s" This.Fontsize " c" Brush " " This.FontOptions " x" 0 " y" 0 , This.FontType , This.StringWidth, This.StringHeight  )
			Gdip_DeleteBrush( Brush )
			Gdip_DrawImage( This.Output.Graphics , This.TextBitmap , This.MaxSize + 2 , This.MaxSize + 2 , This.StringWidth , This.StringHeight )
		}
		Gdip_DeleteGraphics( This.Output.Graphics )
		Loop, % This.Colors.Length()	{
			Gdip_DeleteBrush( Brushes[ A_Index ] )
		}
		Gdip_DeleteGraphics( This.TextBitmapGraphics )
	}
	_hex2rgb( CR , ByRef R , ByRef G , ByRef B , ByRef A := "NA" ){ ;https://www.autohotkey.com/boards/viewtopic.php?t=3925&p=312862
		H := InStr(CR, "0x") ? CR : ( InStr(CR, "#" ) ? "0x" SubStr( CR , 2 ) : "0x" CR )
		R := (H & 0xFF0000) >> 16 , G := (H & 0xFF00) >> 8 , B := (H & 0xFF) , ( A != "NA" ) ? ( A := (H & 0xFF000000) >> 24 ) 
	}
}

LoadLibrary(filename){ ;https://www.autohotkey.com/boards/viewtopic.php?p=48392#p48392
    static ref := {}
    if (!(ptr := p := DllCall("LoadLibrary", "str", filename, "ptr")))
        return 0
    ref[ptr,"count"] := (ref[ptr]) ? ref[ptr,"count"]+1 : 1
    p += NumGet(p+0, 0x3c, "int")+24
    o := {_ptr:ptr, __delete:func("FreeLibrary"), _ref:ref[ptr]}
    if (NumGet(p+0, (A_PtrSize=4) ? 92 : 108, "uint")<1 || (ts := NumGet(p+0, (A_PtrSize=4) ? 96 : 112, "uint")+ptr)=ptr || (te := NumGet(p+0, (A_PtrSize=4) ? 100 : 116, "uint")+ts)=ts)
        return o
    n := ptr+NumGet(ts+0, 32, "uint")
    loop % NumGet(ts+0, 24, "uint"){
        if (p := NumGet(n+0, (A_Index-1)*4, "uint")){
            o[f := StrGet(ptr+p, "cp0")] := DllCall("GetProcAddress", "ptr", ptr, "astr", f, "ptr")
            if (Substr(f, 0)==((A_IsUnicode) ? "W" : "A"))
                o[Substr(f, 1, -1)] := o[f]
        }
    }
    return o
}

FreeLibrary(lib){
    if (lib._ref.count>=1)
        lib._ref.count -= 1
    if (lib._ref.count<1)
        DllCall("FreeLibrary", "ptr", lib._ptr)
}
xlt
Posts: 1
Joined: 17 Mar 2023, 16:58

Re: Calculating the ( Angles / Points ) // DRAW ARROW

17 Mar 2023, 17:00

Thank you very much for this. This is just awesome!
User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Rotate Text

29 Aug 2023, 22:38

Rotatable text.



This class returns a pBitmap which can be saved as a .png or used directly in a gui. ( obj.Bitmap | obj.Width |||| )
It is important to note that you will need to dispose of the pbitmap after drawing it if you intend to animate the text in some way.
Use Gdip_DisposeImage( obj.Bitmap ) or its equivalent to free the memory before creating the new rotated text.

***Required***
GDIP: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6517

Code: Select all

;************
;Rotate Text Class
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
class RotatableText	{
	;Written By: Hellbent
	;Date: Aug 27th 2023
	;Create a bitmap of rotated text
	static init := RotatableText._SetClassDefaults()
	_SetClassDefaults(){
		This.String := "Test String"
		This.Bitmap := ""
		This.FontType := "Segoe UI"
		This.FontSize := 32
		This.FontColor := "0xFF000000"
		This.Scale := 1
		This.Width := ""
		This.Height := ""
		This.FontOptions := " Center vCenter Bold NoWrap "
		This.Angle := 225
	}
	__New( obj := "" ){
		This._SetDefaults()
		This._UpdateDefaults( obj )
	}
	_SetDefaults(){
		for k , v in RotatableText	{
			This[ k ] := v
		}
	}
	_UpdateDefaults( obj ){
		if( This.Bitmap != "" ){
			Gdip_DisposeImage( This.Bitmap )
			This.Bitmap := ""
		}
		for k , v in obj
			This[ k ] := v
		w := floor( This._GetTextSize( 3 ) ) + 1 
		h := floor( This._GetTextSize( 4 ) ) + 1 
		tw := New Vector( w / 2 , h / 2 )
		mag := tw.GetMag()
		This.Width := This.Height := mag * 2
		if( w >= h ){
			y := ( w - h ) / 2
		}else{
			x := ( h - w ) / 2 
		}
		pBitmap := Gdip_CreateBitmap( w , h )
		G := Gdip_GraphicsFromImage( pBitmap )
		Gdip_SetSmoothingMode( G , 2 )
		;Debug testing
		if( This.DebugMode ){
			Brush := Gdip_BrushCreateSolid( "0xFFF00000")
			Gdip_FillRectangle( G , Brush, 0, 0, w, h)
			Gdip_DeleteBrush( Brush )
		}
		Brush := Gdip_BrushCreateSolid( This.Color )
		Gdip_TextToGraphics( G , This.String , " s" This.Fontsize * This.Scale " c" Brush " " This.FontOptions " x" 0 " y" 0 , This.FontType , w , h  )
		Gdip_DeleteBrush( Brush )
		Gdip_DeleteGraphics( G ) 
		nBitmap := Gdip_CreateBitmap( This.Width , This.Height )
		G := Gdip_GraphicsFromImage( nBitmap )
		Gdip_SetSmoothingMode( G , 2 )
		Gdip_DrawImage( G , pBitmap , ( This.Width - w ) / 2 , ( This.Height - h ) / 2 , w , h )
		Gdip_DisposeImage( pBitmap )
		Gdip_DeleteGraphics( G ) 
		Center := New Vector( This.Width / 2 , This.Height / 2 )
		tt := New Vector( 0 , 0 )
		tt.Sub( Center )
		TopLeft := New Vector( 10 , 10 )
		TopLeft.SetMag( tt.GetMag() )
		TopLeft.SetAngle( This.Angle )
		TopRight := New Vector( TopLeft )
		TopRight.SetAngle( This.Angle + 90 )
		BottomLeft := New Vector( TopLeft )
		BottomLeft.SetAngle( This.Angle - 90 )
		BottomLeft.Add( Center )
		TopRight.Add( Center )
		TopLeft.Add( Center )
		This.Bitmap := Gdip_CreateBitmap( This.Width , This.Height )
		G := Gdip_GraphicsFromImage( This.Bitmap )
		Gdip_SetSmoothingMode( G , 2 )
		;Debug testing
		if( This.DebugMode ){
			Brush := Gdip_BrushCreateSolid( "0xFF000000")
			Gdip_FillRectangle( G , Brush, 0, 0, This.Width , This.Height )
			Gdip_DeleteBrush( Brush )
		}
		points := TopLeft.X " , " TopLeft.Y " | " TopRight.X " , " TopRight.Y " | " BottomLeft.X " , " BottomLeft.Y
		Gdip_DrawImagePointsRect( G , nBitmap , points )
		Gdip_DisposeImage( nBitmap )
		Gdip_DeleteGraphics( G )
	}
	_GetTextSize( Index := 4 ){
		local pBitmap, G, Brush, temparr
		pBitmap := Gdip_CreateBitmap( 10 , 10 ) , G := Gdip_GraphicsFromImage( pBitmap ), Gdip_SetSmoothingMode( G , 2 )
		Brush := Gdip_BrushCreateSolid( "0xFF000000")
		temparr := StrSplit( Gdip_TextToGraphics( G , ( This.String ) ? ( This.String ) : ( "Error`nNo String`nWas Used" ), " s" This.Fontsize * This.Scale " c" Brush " " This.FontOptions " x" 0 " y" 0 , This.FontType , 10000, 10000  ),"|","|"  ) , Gdip_DeleteBrush( Brush )
		Gdip_DeleteGraphics( G ) , Gdip_DisposeImage( pBitmap )
		return temparr[ index ]
	}
}
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
;************
;Vector Class
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
Class Vector	{
	;Written By: HB
	;Date: Sept 23rd, 2022
	;Last Edit: Sept 24th, 2022
	;Purpose: Vector math class 
	;Credit: Rohwedder 
	;Resources: 
		;Line intercept concepts and code: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=37175
		;Create an Arrow: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=92039&p=479129#p478944
		;Getting an angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483661#p483678
		;Setting an Angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483786#p483811
		;
		
	static RadToDeg := 45 / ATan( 1 ) 
		, DegToRad := ATan( 1 ) / 45 
		
	__New( x := 0 , y := 0 , rotate := 0 ){ 
		if( IsObject( x ) ){
			if( rotate = 3 ){
				This.X := x.X * -1
				,This.Y := x.Y * -1
			}else if( rotate = 2 ){
				This.X := x.Y 
				,This.Y := x.X * -1
			}else if( rotate = 1 ){
				This.X := x.Y * -1
				,This.Y := x.X 
			}else{
				This.X := x.X
				,This.Y := x.Y
			}
		}else{
			if( rotate = 3 ){
				This.X := X * -1
				,This.Y := Y * -1
			}else if( rotate = 2 ){
				This.X := Y 
				,This.Y := X * -1
			}else if( rotate = 1 ){
				This.X := Y * -1
				,This.Y := X 
			}else{
				This.X := X
				,This.Y := Y
			}
		}
	}
	Add( x , y := "" ){
		if( IsObject( x ) ){
			This.X += x.X
			,This.Y += x.Y
		}else if( y = "" ){
			This.X += x 
			,This.Y += x
		}else{
			This.X += x 
			,This.Y += y 
		}
	}
	Sub( x , y := "" ){
		if( IsObject( x ) ){
			This.X -= x.X
			,This.Y -= x.Y
		}else if( y = "" ){
			This.X -= X
			,This.Y -= X
		}else{
			This.X -= X
			,This.Y -= Y
		}
	}
	Div( x , y := "" ){
		if( IsObject( x ) ){
			This.X /= x.X
			,This.Y /= x.Y
		}else if( x && y = "" ){
			This.X /= x 
			,This.Y /= x 
		}else{
			This.X /= X
			,This.Y /= Y
		}
	}
	Mult( x , y := "" ){
		if( IsObject( x ) ){
			This.X *= x.X
			,This.Y *= x.Y
		}else if( x && y = "" ){
			This.X *= x 
			,This.Y *= x 
		}else{
			This.X *= X
			,This.Y *= Y
		}
	}
	Dist( x , y := "" ){
		if( IsObject( x ) )
			return Sqrt( ( ( This.X - x.X ) **2 ) + ( ( This.Y - x.Y ) **2 ) )
		else 
			return Sqrt( ( ( This.X - X ) **2 ) + ( ( This.Y - Y ) **2 ) )
	}
	GetMag(){
		return Sqrt( This.X * This.X + This.Y * This.Y )
	}
	SetMag( magnitude ){
		local m := This.GetMag()
		This.X := This.X * magnitude / m
		,This.Y := This.Y * magnitude / m
	}
	MagSq(){
		return This.GetMag()**2
	}	
	Dot( x , y := "" ){
		if( IsObject( x ) )
			return ( This.X * x.X ) + ( This.Y * x.Y )
		else
			return ( This.X * X ) + ( This.Y * Y )
	}
	Cross( x , y := "" ){
		if( IsObject( x ) )
			return This.X * x.Y - This.Y * x.X
		else
			return This.X * Y - This.Y * X
		
	}
	Norm(){
		local m := This.GetMag()
		This.X /= m
		This.Y /= m
	}
	GetAngle(){ 
		local angle 
		( (  angle := Vector.RadToDeg * DllCall( "msvcrt\atan2" , "Double" , This.Y , "Double" , This.X , "CDECL Double" ) ) < 0 ) ? ( angle += 360 )
		return angle
	}
	SetAngle( newAngle := 0 , NewVector := 0 ){
		local Angle := This.GetAngle()
		, ChangeAngle := newAngle - Angle 
		, Co := Cos( Vector.DegToRad * ChangeAngle )
		, Si := Sin( Vector.DegToRad * ChangeAngle )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	RotateAngle( rotationAmount := 90 , NewVector := 0 ){
		local Co := Cos( Vector.DegToRad * rotationAmount )
		, Si := Sin( Vector.DegToRad * rotationAmount )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	;********************************************
	;class methods
	TestLineInterceptPoint( interceptPoint , Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } } , interceptPoint = { X: , Y: }
		local
		for k , v in [ "X" , "Y" ]	
			M%v%_Min := min( Line1.Start[ v ] , Line1.End[ v ] )
			,M%v%_Max := max( Line1.Start[ v ] , Line1.End[ v ] )
			,L%v%_Min := min( Line2.Start[ v ] , Line2.End[ v ] )
			,L%v%_Max := max( Line2.Start[ v ] , Line2.End[ v ] )
		if( !( interceptPoint.X < Mx_Min || interceptPoint.X > Mx_Max || interceptPoint.X < Lx_Min || interceptPoint.X > Lx_Max ) && !( interceptPoint.Y < My_Min || interceptPoint.Y > My_Max || interceptPoint.Y < Ly_Min || interceptPoint.Y > Ly_Max ) )
			return 1
		return 0
	}
	GetLineInterceptPoint( Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } }
		local A1 := Line1.End.Y - Line1.Start.Y
		,B1 := Line1.Start.X - Line1.End.X
		,C1 := A1 * Line1.Start.X + B1 * Line1.Start.Y
		,A2 := Line2.End.Y - Line2.Start.Y
		,B2 := Line2.Start.X - Line2.End.X
		,C2 := A2 * Line2.Start.X + B2 * Line2.Start.Y
		,Denominator := A1 * B2 - A2 * B1 
		return New Vector( { X: ( ( B2 * C1 - B1 * C2 ) / Denominator )  , Y: ( ( A1 * C2 - A2 * C1 ) / Denominator ) } )
	}
	;********************************************
}
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************

Working Example.

.
Rotate Text 1.gif
Rotate Text 1.gif (842.25 KiB) Viewed 2206 times
.

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib> ;GDIP:  https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6517
;~ #Include <PopUpWindow_V2> ; At the bottom of the script 
;~ #Include <HB Vectors v2>  ; At the bottom of the script
;****************************************************************************************************************************************************************************
#SingleInstance, Force
SetBatchLines, -1
Gdip_Startup()


;********************************************************************************
;********************************************************************************
myString = 
( 
		AutoHotkey
)

obj := {}  ;<<<<----    Set the options/values to pass.
obj.FontType := "Comic Sans MS"
obj.FontSize := 64
;~ obj.Color := "0xFF336699"
obj.Color := "0xFF00FF00"
obj.FOntOptions := "Center vCenter Bold "
obj.String := myString
obj.Angle := 200
;********************************************************************************
;********************************************************************************
bob := New RotatableText( obj ) ;<<<<-----   Create a new text bitmap. 
;********************************************************************************
;********************************************************************************
Gui1 := New PopUpWindow( { AutoShow: 1 , X: "Center" , Y: "Center" , W: bob.Width , H: bob.Height , Options: " +AlwaysOnTop -DPIScale " } ) 
Gui1.DrawBitmap( bob.Bitmap , { X: 0 , Y: 0 , W: Gui1.W , H: Gui1.H } , dispose := 1 , AutoUpdate := 1 )
;********************************************************************************
;********************************************************************************
; ToolTip, % "Tip:`n" bob.Width
SetTimer, RotateIt, 30
return
GuiClose:
GuiContextMenu:
*ESC::ExitApp

RALT::PopUpWindow.Helper()

RotateIt:
	obj := {}
	;~ obj.FontType := "Comic Sans MS"
	;~ obj.FontSize := 16
	;~ obj.String := "Comic Sans MS"
	;~ obj.Color := "0xFF000000"
	;~ obj.Color := "0xFFFF0000"
	obj.Angle := bob.Angle + 18

	bob._UpdateDefaults( obj )
	Gui1.ClearWindow( AutoUpdate := 0 )
	;~ Gui1.PaintBackground( color := "0xFF000000" , AutoUpdate := 0 ) ;{ Color: "0xFF000000" , X: 2 , Y: 2 , W: Gui1.W - 4 , H: Gui1.H - 4 , Round: 10 }
	Gui1.DrawBitmap( bob.Bitmap , { X: 0 , Y: 0 , W: Gui1.W , H: Gui1.H } , dispose := 1 , AutoUpdate := 1 )
	return

;************
;Rotate Text Class
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
class RotatableText	{
	;Written By: Hellbent
	;Date: Aug 27th 2023
	;Create a bitmap of rotated text
	static init := RotatableText._SetClassDefaults()
	_SetClassDefaults(){
		This.String := "Test String"
		This.Bitmap := ""
		This.FontType := "Segoe UI"
		This.FontSize := 32
		This.FontColor := "0xFF000000"
		This.Scale := 1
		This.Width := ""
		This.Height := ""
		This.FontOptions := " Center vCenter Bold NoWrap "
		This.Angle := 225
	}
	__New( obj := "" ){
		This._SetDefaults()
		This._UpdateDefaults( obj )
	}
	_SetDefaults(){
		for k , v in RotatableText	{
			This[ k ] := v
		}
	}
	_UpdateDefaults( obj ){
		if( This.Bitmap != "" ){
			Gdip_DisposeImage( This.Bitmap )
			This.Bitmap := ""
		}
		for k , v in obj
			This[ k ] := v
		w := floor( This._GetTextSize( 3 ) ) + 1 
		h := floor( This._GetTextSize( 4 ) ) + 1 
		tw := New Vector( w / 2 , h / 2 )
		mag := tw.GetMag()
		This.Width := This.Height := mag * 2
		if( w >= h ){
			y := ( w - h ) / 2
		}else{
			x := ( h - w ) / 2 
		}
		pBitmap := Gdip_CreateBitmap( w , h )
		G := Gdip_GraphicsFromImage( pBitmap )
		Gdip_SetSmoothingMode( G , 2 )
		;Debug testing
		if( This.DebugMode ){
			Brush := Gdip_BrushCreateSolid( "0xFFF00000")
			Gdip_FillRectangle( G , Brush, 0, 0, w, h)
			Gdip_DeleteBrush( Brush )
		}
		Brush := Gdip_BrushCreateSolid( This.Color )
		Gdip_TextToGraphics( G , This.String , " s" This.Fontsize * This.Scale " c" Brush " " This.FontOptions " x" 0 " y" 0 , This.FontType , w , h  )
		Gdip_DeleteBrush( Brush )
		Gdip_DeleteGraphics( G ) 
		nBitmap := Gdip_CreateBitmap( This.Width , This.Height )
		G := Gdip_GraphicsFromImage( nBitmap )
		Gdip_SetSmoothingMode( G , 2 )
		Gdip_DrawImage( G , pBitmap , ( This.Width - w ) / 2 , ( This.Height - h ) / 2 , w , h )
		Gdip_DisposeImage( pBitmap )
		Gdip_DeleteGraphics( G ) 
		Center := New Vector( This.Width / 2 , This.Height / 2 )
		tt := New Vector( 0 , 0 )
		tt.Sub( Center )
		TopLeft := New Vector( 10 , 10 )
		TopLeft.SetMag( tt.GetMag() )
		TopLeft.SetAngle( This.Angle )
		TopRight := New Vector( TopLeft )
		TopRight.SetAngle( This.Angle + 90 )
		BottomLeft := New Vector( TopLeft )
		BottomLeft.SetAngle( This.Angle - 90 )
		BottomLeft.Add( Center )
		TopRight.Add( Center )
		TopLeft.Add( Center )
		This.Bitmap := Gdip_CreateBitmap( This.Width , This.Height )
		G := Gdip_GraphicsFromImage( This.Bitmap )
		Gdip_SetSmoothingMode( G , 2 )
		;Debug testing
		if( This.DebugMode ){
			Brush := Gdip_BrushCreateSolid( "0xFF000000")
			Gdip_FillRectangle( G , Brush, 0, 0, This.Width , This.Height )
			Gdip_DeleteBrush( Brush )
		}
		points := TopLeft.X " , " TopLeft.Y " | " TopRight.X " , " TopRight.Y " | " BottomLeft.X " , " BottomLeft.Y
		Gdip_DrawImagePointsRect( G , nBitmap , points )
		Gdip_DisposeImage( nBitmap )
		Gdip_DeleteGraphics( G )
	}
	_GetTextSize( Index := 4 ){
		local pBitmap, G, Brush, temparr
		pBitmap := Gdip_CreateBitmap( 10 , 10 ) , G := Gdip_GraphicsFromImage( pBitmap ), Gdip_SetSmoothingMode( G , 2 )
		Brush := Gdip_BrushCreateSolid( "0xFF000000")
		temparr := StrSplit( Gdip_TextToGraphics( G , ( This.String ) ? ( This.String ) : ( "Error`nNo String`nWas Used" ), " s" This.Fontsize * This.Scale " c" Brush " " This.FontOptions " x" 0 " y" 0 , This.FontType , 10000, 10000  ),"|","|"  ) , Gdip_DeleteBrush( Brush )
		Gdip_DeleteGraphics( G ) , Gdip_DisposeImage( pBitmap )
		return temparr[ index ]
	}
}
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
;************
;Vector Class
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
Class Vector	{
	;Written By: HB
	;Date: Sept 23rd, 2022
	;Last Edit: Sept 24th, 2022
	;Purpose: Vector math class 
	;Credit: Rohwedder 
	;Resources: 
		;Line intercept concepts and code: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=37175
		;Create an Arrow: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=92039&p=479129#p478944
		;Getting an angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483661#p483678
		;Setting an Angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483786#p483811
		;
		
	static RadToDeg := 45 / ATan( 1 ) 
		, DegToRad := ATan( 1 ) / 45 
		
	__New( x := 0 , y := 0 , rotate := 0 ){ 
		if( IsObject( x ) ){
			if( rotate = 3 ){
				This.X := x.X * -1
				,This.Y := x.Y * -1
			}else if( rotate = 2 ){
				This.X := x.Y 
				,This.Y := x.X * -1
			}else if( rotate = 1 ){
				This.X := x.Y * -1
				,This.Y := x.X 
			}else{
				This.X := x.X
				,This.Y := x.Y
			}
		}else{
			if( rotate = 3 ){
				This.X := X * -1
				,This.Y := Y * -1
			}else if( rotate = 2 ){
				This.X := Y 
				,This.Y := X * -1
			}else if( rotate = 1 ){
				This.X := Y * -1
				,This.Y := X 
			}else{
				This.X := X
				,This.Y := Y
			}
		}
	}
	Add( x , y := "" ){
		if( IsObject( x ) ){
			This.X += x.X
			,This.Y += x.Y
		}else if( y = "" ){
			This.X += x 
			,This.Y += x
		}else{
			This.X += x 
			,This.Y += y 
		}
	}
	Sub( x , y := "" ){
		if( IsObject( x ) ){
			This.X -= x.X
			,This.Y -= x.Y
		}else if( y = "" ){
			This.X -= X
			,This.Y -= X
		}else{
			This.X -= X
			,This.Y -= Y
		}
	}
	Div( x , y := "" ){
		if( IsObject( x ) ){
			This.X /= x.X
			,This.Y /= x.Y
		}else if( x && y = "" ){
			This.X /= x 
			,This.Y /= x 
		}else{
			This.X /= X
			,This.Y /= Y
		}
	}
	Mult( x , y := "" ){
		if( IsObject( x ) ){
			This.X *= x.X
			,This.Y *= x.Y
		}else if( x && y = "" ){
			This.X *= x 
			,This.Y *= x 
		}else{
			This.X *= X
			,This.Y *= Y
		}
	}
	Dist( x , y := "" ){
		if( IsObject( x ) )
			return Sqrt( ( ( This.X - x.X ) **2 ) + ( ( This.Y - x.Y ) **2 ) )
		else 
			return Sqrt( ( ( This.X - X ) **2 ) + ( ( This.Y - Y ) **2 ) )
	}
	GetMag(){
		return Sqrt( This.X * This.X + This.Y * This.Y )
	}
	SetMag( magnitude ){
		local m := This.GetMag()
		This.X := This.X * magnitude / m
		,This.Y := This.Y * magnitude / m
	}
	MagSq(){
		return This.GetMag()**2
	}	
	Dot( x , y := "" ){
		if( IsObject( x ) )
			return ( This.X * x.X ) + ( This.Y * x.Y )
		else
			return ( This.X * X ) + ( This.Y * Y )
	}
	Cross( x , y := "" ){
		if( IsObject( x ) )
			return This.X * x.Y - This.Y * x.X
		else
			return This.X * Y - This.Y * X
		
	}
	Norm(){
		local m := This.GetMag()
		This.X /= m
		This.Y /= m
	}
	GetAngle(){ 
		local angle 
		( (  angle := Vector.RadToDeg * DllCall( "msvcrt\atan2" , "Double" , This.Y , "Double" , This.X , "CDECL Double" ) ) < 0 ) ? ( angle += 360 )
		return angle
	}
	SetAngle( newAngle := 0 , NewVector := 0 ){
		local Angle := This.GetAngle()
		, ChangeAngle := newAngle - Angle 
		, Co := Cos( Vector.DegToRad * ChangeAngle )
		, Si := Sin( Vector.DegToRad * ChangeAngle )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	RotateAngle( rotationAmount := 90 , NewVector := 0 ){
		local Co := Cos( Vector.DegToRad * rotationAmount )
		, Si := Sin( Vector.DegToRad * rotationAmount )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	;********************************************
	;class methods
	TestLineInterceptPoint( interceptPoint , Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } } , interceptPoint = { X: , Y: }
		local
		for k , v in [ "X" , "Y" ]	
			M%v%_Min := min( Line1.Start[ v ] , Line1.End[ v ] )
			,M%v%_Max := max( Line1.Start[ v ] , Line1.End[ v ] )
			,L%v%_Min := min( Line2.Start[ v ] , Line2.End[ v ] )
			,L%v%_Max := max( Line2.Start[ v ] , Line2.End[ v ] )
		if( !( interceptPoint.X < Mx_Min || interceptPoint.X > Mx_Max || interceptPoint.X < Lx_Min || interceptPoint.X > Lx_Max ) && !( interceptPoint.Y < My_Min || interceptPoint.Y > My_Max || interceptPoint.Y < Ly_Min || interceptPoint.Y > Ly_Max ) )
			return 1
		return 0
	}
	GetLineInterceptPoint( Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } }
		local A1 := Line1.End.Y - Line1.Start.Y
		,B1 := Line1.Start.X - Line1.End.X
		,C1 := A1 * Line1.Start.X + B1 * Line1.Start.Y
		,A2 := Line2.End.Y - Line2.Start.Y
		,B2 := Line2.Start.X - Line2.End.X
		,C2 := A2 * Line2.Start.X + B2 * Line2.Start.Y
		,Denominator := A1 * B2 - A2 * B1 
		return New Vector( { X: ( ( B2 * C1 - B1 * C2 ) / Denominator )  , Y: ( ( A1 * C2 - A2 * C1 ) / Denominator ) } )
	}
	;********************************************
}
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
class PopUpWindow	{
;PopUpWindow v2.2
;Date Written: Oct 28th, 2021
;Last Edit: Feb 7th, 2022 :Changed the trigger method.
;Written By: Hellbent aka CivReborn
;SpcThanks: teadrinker , malcev 
	static Index := 0 , Windows := [] , Handles := [] , EditHwnd , HelperHwnd
	__New( obj := "" ){
		This._SetDefaults()
		This.UpdateSettings( obj )
		This._CreateWindow()
		This._CreateWindowGraphics()
		if( This.AutoShow )
			This.ShowWindow( This.Title )
	}
	_SetDefaults(){
		This.X := 10
		This.Y := 10
		This.W := 10
		This.H := 10
		This.Smoothing := 2
		This.Options := " -DPIScale +AlwaysOnTop "
		This.AutoShow := 0
		This.GdipStartUp := 0
		This.Title := ""
		
		This.Controls := []
		This.Handles := []
		This.Index := 0 
	}
	AddTrigger( obj ){
		local k , v , cc , bd
		
		This.Controls[ ++This.Index ] := { 	X:		10
										,	Y:		10
										,	W:		10
										,	H:		10	}
		for k, v in obj
			This.Controls[ This.Index ][ k ] := obj[ k ] 
		cc := This.Controls[ This.Index ]
		Gui, % This.Hwnd ":Add", Text, % "x" cc.X " y" cc.Y " w" cc.W " h" cc.H " hwndhwnd"
		This.Handles[ hwnd ] := This.Index
		This.Controls[ This.Index ].Hwnd := hwnd
		
		if( IsObject( cc.Label ) ){
			bd := cc.Label
			GuiControl, % This.Hwnd ":+G" , % hwnd , % bd
		}else{
			bd := This._TriggerCall.Bind( This )
			GuiControl, % This.Hwnd ":+G" , % hwnd , % bd
		}
		return hwnd
		
	}
	_TriggerCall(){
		MouseGetPos,,,, ctrl, 2
		Try
			;~ SetTimer, % This.Controls[ This.Handles[ ctrl ] ].Label, -0
			gosub, % This.Controls[ This.Handles[ ctrl ] ].Label
		
				
	}
	DrawTriggers( color := "0xFFFF0000" , AutoUpdate := 0 ){
		local brush , cc 
		Brush := Gdip_BrushCreateSolid( color ) 
		Gdip_SetSmoothingMode( This.G , 3 )
		loop, % This.Controls.Length()	{
			cc := This.Controls[ A_Index ]
			Gdip_FillRectangle( This.G , Brush , cc.x , cc.y , cc.w , cc.h )
		
		}
		Gdip_DeleteBrush( Brush )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	UpdateSettings( obj := "" , UpdateGraphics := 0 ){
		local k , v
		if( IsObject( obj ) )
			for k, v in obj
				This[ k ] := obj[ k ]
		( This.X = "Center" ) ? ( This.X := ( A_ScreenWidth - This.W ) / 2 ) 	
		( This.Y = "Center" ) ? ( This.Y := ( A_ScreenHeight - This.H ) / 2 ) 	
		if( UpdateGraphics ){
			This._DestroyWindowsGraphics()
			This._CreateWindowGraphics()
		}
	}
	_CreateWindow(){
		local hwnd
		Gui , New, % " +LastFound +E0x80000 hwndhwnd -Caption  " This.Options
		PopUpWindow.Index++
		This.Index := PopUpWindow.Index
		PopUpWindow.Windows[ PopUpWindow.Index ] := This
		This.Hwnd := hwnd
		PopUpWindow.Handles[ hwnd ] := PopUpWindow.Index
		if( This.GdipStartUp && !PopUpWindow.pToken )
			PopUpWindow.pToken := GDIP_STARTUP()
	}
	_DestroyWindowsGraphics(){
		Gdip_DeleteGraphics( This.G )
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
	}
	_CreateWindowGraphics(){
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
	}
	ShowWindow( Title := "" ){
		Gui , % This.Hwnd ":Show", % "x" This.X " y" This.Y " w" This.W " h" This.H " NA", % Title
	}
	HideWindow(){
		Gui , % This.Hwnd ":Hide",
	}
	UpdateWindow( alpha := 255 ){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H , alpha )
	}
	ClearWindow( AutoUpdate := 0 , Color := "" ){
		if( color != "" )
			Gdip_GraphicsClear( This.G , color )
		else
			Gdip_GraphicsClear( This.G )
		if( Autoupdate )
			This.UpdateWindow()
	}
	DrawBitmap( pBitmap , obj , dispose := 1 , AutoUpdate := 0 ){
		Gdip_DrawImage( This.G , pBitmap , obj.X , obj.Y , obj.W , obj.H )
		if( dispose )
			Gdip_DisposeImage( pBitmap )
		if( Autoupdate )
			This.UpdateWindow()
	}
	PaintBackground( color := "0xFF000000" , AutoUpdate := 0 ){
		if( isObject( color ) ){
			Brush := Gdip_BrushCreateSolid( ( color.HasKey( "Color" ) ) ? ( color.Color ) : ( "0xFF000000" ) ) 
			if( color.Haskey( "Round" ) )
				Gdip_FillRoundedRectangle( This.G , Brush , color.X , color.Y , color.W , color.H , color.Round )
			else
				Gdip_FillRectangle( This.G , Brush , color.X , color.Y , color.W , color.H ) 
		}else{
			Brush := Gdip_BrushCreateSolid( color ) 
			Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W + 2 , This.H + 2 ) 
		}
		Gdip_DeleteBrush( Brush )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DeleteWindow( GDIPShutdown := 0 ){
		Gui, % This.Hwnd ":Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		hwnd := This.Hwnd
		for k, v in PopUpWindow.Windows[ Hwnd ]
			This[k] := ""
		PopUpWindow.Windows[ Hwnd ] := ""
		if( GDIPShutdown ){
			Gdip_Shutdown( PopUpWindow.pToken )
			PopUpWindow.pToken := ""
		}
	}
	_OnClose( wParam ){
		if( wParam = 0xF060 ){	;SC_CLOSE ;[ clicking on the gui close button ]
			Try{
				Gui, % PopUpWindow.HelperHwnd ":Destroy"
				SoundBeep, 555
			}
		}
	}
	CreateCachedBitmap( pBitmap , Dispose := 0 ){
		local pCachedBitmap
		if( This.CachedBitmap )
			This.DisposeCachedbitmap()
		DllCall( "gdiplus\GdipCreateCachedBitmap" , "Ptr" , pBitmap , "Ptr" , this.G , "PtrP" , pCachedBitmap )
		This.CachedBitmap := pCachedBitmap
		if( Dispose )
			Gdip_DisposeImage( pBitmap )
	}
	DrawCachedBitmap( AutoUpdate := 0 ){
		DllCall( "gdiplus\GdipDrawCachedBitmap" , "Ptr" , this.G , "Ptr" , This.CachedBitmap , "Int" , 0 , "Int" , 0 )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DisposeCachedbitmap(){
		DllCall( "gdiplus\GdipDeleteCachedBitmap" , "Ptr" , This.CachedBitmap )
	}
	Helper(){
		local hwnd , MethodList := ["__New","UpdateSettings","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow" , "AddTrigger" , "DrawTriggers", "CreateCachedBitmap" , "DrawCachedBitmap" , "DisposeCachedbitmap" ]
		Gui, New, +AlwaysOnTop +ToolWindow +HwndHwnd
		PopUpWindow.HelperHwnd := hwnd
		Gui, Add, Edit, xm ym w250 r1 Center hwndhwnd, Gui1
		PopUpWindow.EditHwnd := hwnd
		loop, % MethodList.Length()	
			Gui, Add, Button, xm y+1 w250 r1 gPopUpWindow._HelperClip, % MethodList[ A_Index ]
		Gui, Show,,
		OnMessage( 0x112 , This._OnClose.Bind( hwnd ) )
	}
	_HelperClip(){
		local ClipList 
		
		GuiControlGet, out, % PopUpWindow.HelperHwnd ":", % PopUpWindow.EditHwnd	
		
		ClipList := 		{ 	__New: 					" := New PopUpWindow( { AutoShow: 1 , X: 0 , Y: 0 , W: A_ScreenWidth , H: A_ScreenHeight , Options: "" -DPIScale +AlwaysOnTop "" } )"
							,	UpdateSettings:			".UpdateSettings( { X: """" , Y: """" , W: """" , H: """" } , UpdateGraphics := 0 )"
							,	ShowWindow:				".ShowWindow( Title := """" )"
							,	HideWindow:				".HideWindow()"
							,	UpdateWindow:			".UpdateWindow()"
							,	ClearWindow:			".ClearWindow( AutoUpdate := 0 )"
							,	DrawBitmap:				".DrawBitmap( pBitmap := """" , { X: 0 , Y: 0 , W: " Out ".W , H: " Out ".H } , dispose := 1 , AutoUpdate := 0 )"
							,	PaintBackground:		".PaintBackground( color := ""0xFF000000"" , AutoUpdate := 0 )  "  ";{ Color: ""0xFF000000"" , X: 2 , Y: 2 , W: " Out ".W - 4 , H: " Out ".H - 4 , Round: 10 }"
							,	DeleteWindow:			".DeleteWindow( GDIPShutdown := 0 )"
							,	AddTrigger:				".AddTrigger( { X: """" , Y: """" , W: """" , H: """" , Value: """" , Label: """" } )"	
							,	DrawTriggers:			".DrawTriggers( color := ""0xFFFF0000"" , AutoUpdate := 0 )"	
							,	CreateCachedBitmap:		".CreateCachedBitmap( pBitmap , Dispose := 0 )"	
							,	DrawCachedBitmap: 		".DrawCachedBitmap( AutoUpdate := 0 )"	
							,	DisposeCachedbitmap:	".DisposeCachedbitmap()"	}
							
		clipboard := Out ClipList[ A_GuiControl ]
		
	}
}




User avatar
Hellbent
Posts: 2114
Joined: 23 Sep 2017, 13:34

Re: Calculating the ( Angles / Points ) // DRAW ARROW

04 Oct 2023, 01:09

Point of focus.

Requires GDIP: viewtopic.php?f=6&t=6517

F1 Hotkey:
.
Arrow focus.gif
Arrow focus.gif (364.26 KiB) Viewed 1669 times
.

F2 Hotkey:
.
circle focus.gif
circle focus.gif (517.36 KiB) Viewed 1669 times
.

Simple Rotation
F3 Hotkey:
.
arrow rotation.gif
arrow rotation.gif (317.81 KiB) Viewed 1669 times
.

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib> ;GDIP:  https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6517
;~ #Include <PopUpWindow_V2> ; At the bottom of the script 
;~ #Include <HB Vectors v2>  ; At the bottom of the script
;****************************************************************************************************************************************************************************
#SingleInstance, Force
SetBatchLines, -1
Gdip_Startup()

Gui1 := New PopUpWindow( { AutoShow: 1 , X: "Center" , Y: "Center" , W: A_ScreenWidth , H: A_ScreenHeight , Options: " +AlwaysOnTop -DPIScale +ToolWindow " } ) 

return
GuiClose:
GuiContextMenu:
*ESC::ExitApp
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;Comments added by ChatGPT
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
; Function to handle F1 key press
F1::
    ; Set the coordinate mode to screen
    CoordMode, Mouse, Screen
    
    ; Get the current mouse position
    MouseGetPos, x, y 
    
    ; Create a vector for the home position
    HomeVector := New Vector(x, y)
    
    ; Set the initial value for the ring size
    value := 110
    
    ; Loop 10 times to draw the arrows
    Loop, 10 {
        ; Clear the window before drawing the arrows
        Gui1.ClearWindow()
        
        ; Set the ring vectors based on the home position and value
        Sides := SetRingVectors(HomeVector, value)
        
        ; Loop through the arrow directions
        for k, v in ["T", "R", "B", "L"] {
            ; Create a new arrow head object
            MyArrow := New ArrowHead_2(Sides[v "2"], Sides[v "1"], HeadLength := 20, NeckLength := 2, ArmLength := 11, ElbowLength := 4, Scale := 1)
            
            ; Fill the arrow head polygon with a semi-transparent green color
            FillPolygon(Gui1.G, MyArrow, "0x9900ff00")
            
            ; Draw the outline of the arrow head with a black color and thickness of 3
            DrawPolygon(Gui1.G, MyArrow, "0xFF000000", Thickness := 3)
        }
        
        ; Decrease the value for the next ring size
        value -= 10 
        
        ; Pause for 30 milliseconds
        sleep, 30
        
        ; Update the window to show the changes
        Gui1.UpdateWIndow()
    }
    
    ; Set the initial alpha value
    alpha := 225
    
    ; Loop 10 times to update the window with decreasing alpha values
    Loop, 10 {
        Gui1.UpdateWIndow(alpha)
        alpha -= 25
        sleep, 30
    }
    
    ; Clear the window with a color index of 1
    Gui1.ClearWindow(1)
    
    ; Return from the function
    return

;***************************************************
;***************************************************
;***************************************************
; Function to handle F2 key press
F2::
    ; Set the coordinate mode to screen
    CoordMode, Mouse, Screen
    
    ; Get the current mouse position
    MouseGetPos, x, y 
    
    ; Create a vector for the home position
    HomeVector := New Vector(x, y)
    
    ; Create a master vector with initial values
    master := New Vector(10, 10)
    
    ; Set the magnitude of the master vector
    master.SetMag(50)
    
    ; Set the angle of the master vector to 270 degrees
    master.SetAngle(270)
    
    ; Create a temporary vector for calculations
    st := New Vector(master)
    
    ; Add the home vector to the temporary vector
    st.Add(HomeVector)
    
    ; Create a string to store the polygon coordinates
    polygon := st.X "," st.Y
    
    ; Clear the window before drawing the polygons
    Gui1.ClearWindow()
    
    ; Set the increment value for the loop
    increment := 5
    
    ; Loop through 360 degrees with the specified increment
    Loop, % 360 / increment + 1 {
        ; Create a new vector based on the master vector
        cV := New Vector(master)
        
        ; Add the home vector to the new vector
        cV.Add(HomeVector)
        
        ; Append the coordinates to the polygon string
        polygon .= "|" cV.X "," cV.Y
        
        ; Draw the outer polygon with a thickness of 17 and black color
        DrawPolygon(Gui1.G, polygon, "0xFF000000", Thickness := 17)
        
        ; Draw the inner polygon with a thickness of 13 and red color
        DrawPolygon(Gui1.G, polygon, "0xFFFF0000", Thickness := 13)
        
        ; Update the window to show the changes
        Gui1.UpdateWIndow()
        
        ; Rotate the master vector by the specified increment
        master.RotateAngle(increment)
    }
    
    ; Append the starting coordinates to the polygon string
    polygon .= "|" st.X "," st.Y
    
    ; Draw the final polygon with a thickness of 17 and black color
    DrawPolygon(Gui1.G, polygon, "0xFF000000", Thickness := 17)
    
    ; Draw the final polygon with a thickness of 13 and green color
    DrawPolygon(Gui1.G, polygon, "0xFF00FF00", Thickness := 13)
    
    ; Update the window to show the changes
    Gui1.UpdateWIndow()
    
    ; Set the initial alpha value
    alpha := 225
    
    ; Loop 20 times to update the window with decreasing alpha values
    Loop, 20 {
        Gui1.UpdateWIndow(alpha)
        alpha -= 10
        sleep, 30
    }
    
    ; Clear the window with a color index of 1
    Gui1.ClearWindow(1)
    
    ; Return from the function
    return

;***************************************************
;***************************************************
;***************************************************
; Function to handle F3 key press
F3::
    ; Set the coordinate mode to screen
    CoordMode, Mouse, Screen
    
    ; Get the current mouse position
    MouseGetPos, x, y 
    
    ; Set the scale factor
    Scale := .5
    
    ; Calculate the scaled home vector
    HomeVector := New Vector(x /= Scale, y /= Scale)
    
    ; Call the function to animate arrows
    AnimateArrows(Gui1, HomeVector, Scale)
    
    ; Set the initial alpha value
    alpha := 225
    
    ; Loop 20 times to update the window with decreasing alpha values
    Loop, 20 {
        Gui1.UpdateWIndow(alpha)
        alpha -= 10
        sleep, 30
    }
    
    ; Clear the window with a color index of 1
    Gui1.ClearWindow(1)
    
    ; Return from the function
    return

;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
; Function to animate arrows
AnimateArrows(Gui1, HomeVector, Scale) {
    Loop, 2 {
        cycle := A_Index
        
        ; Loop through the angles
        Loop, % 360 / 5 {
            ; Determine the arrow lengths based on the cycle
            if (cycle = 1) {
                endLength := 160 - A_Index * 2
                startLength := 160 - A_Index * 2
            } else if (cycle = 2) {
                endLength := 0 + A_Index * 5
                startLength := 0 + A_Index * 5
            }
            
            ; Clear the window before drawing the arrows
            Gui1.ClearWindow()
            
            ; Set the display vectors based on the home position and arrow lengths
            Sides := SetDisplayVectors(HomeVector, start := startLength, End := endLength, A_Index * 5)
            
            ; Loop through the sides: "U", "UR", "R", "LR", "Lo", "LL", "Le", "UL"
            for k, v in ["U", "UR", "R", "LR", "Lo", "LL", "Le", "UL"] {
                ; Create a new arrow head object based on the display vectors and arrow dimensions
                MyArrow := New ArrowHead_2(Sides[v ((cycle = 1) ? (2) : (1))], Sides[v ((cycle = 1) ? (1) : (2))], HeadLength := 20 * cycle, NeckLength := 2 * cycle, ArmLength := 11 * cycle, ElbowLength := 4 * cycle, Scale)
                
                ; Fill the arrow head with a color based on the index value
                if (A_Index = 1) {
                    FillPolygon(Gui1.G, MyArrow, "0x99FF0000")
                } else {
                    FillPolygon(Gui1.G, MyArrow, "0x6600FF00")
                }
                
                ; Draw the outline of the arrow head
                DrawPolygon(Gui1.G, MyArrow, "0xFF000000", Thickness := 3)
            }
            
            sleep, 30
            Gui1.UpdateWindow()
        }
    }
}
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################

SetDisplayVectors(HomeVector, Start := 100, End := 100, rotation := 0) {
; Create a new vector object called "Master" with initial coordinates (10, 10)
Master := New Vector(10, 10)

; Set the magnitude of the Master vector to the specified "Start" value
Master.SetMag(Start)

; Set the angle of the Master vector to 270 degrees plus the specified "rotation" value
Master.SetAngle(270 + rotation)

; Initialize the angle variable to 0
Angle := 0

; Create an empty dictionary called "Sides" to store the vectors for each side
Sides := {}

; Loop through the sides: "U", "UR", "R", "LR", "Lo", "LL", "Le", "UL"
for k, v in ["U", "UR", "R", "LR", "Lo", "LL", "Le", "UL"] {
; Set the magnitude of the Master vector to the specified "Start" value
Master.SetMag(Start)

; Set the angle of the Master vector to 270 degrees plus the specified "rotation" value plus the current angle
Master.SetAngle(270 + rotation + Angle)

; Create a new vector for the first point of the side and assign it to Sides[v "1"]
Sides[v "1"] := New Vector(Master)

; Add the HomeVector to the first point of the side
Sides[v "1"].Add(HomeVector)

; Set the magnitude of the Master vector to the specified "End" value
Master.SetMag(End)

; Create a new vector for the second point of the side and assign it to Sides[v "2"]
Sides[v "2"] := New Vector(Master)

; Add the first point of the side to the second point of the side
Sides[v "2"].Add(Sides[v "1"])

; Increment the angle by 45 degrees for the next side
Angle += 45
}

; Return the dictionary containing the vectors for each side
return Sides
}

;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################

SetRingVectors(HomeVector, mag := 100) {
; Create a new vector object called "master" with initial coordinates (10, 10)
master := New Vector(10, 10)

; Set the magnitude of the master vector to the specified "mag" value
master.SetMag(mag)

; Set the angle of the master vector to 270 degrees
master.SetAngle(270)

; Create an empty dictionary called "Sides" to store the vectors for each side
Sides := {}

; Loop through the sides: "T", "R", "B", "L"
for k, v in ["T", "R", "B", "L"] {
; Create a new vector for the first point of the side and assign it to Sides[v "1"]
Sides[v "1"] := New Vector(master)

; Create a new vector for the second point of the side and assign it to Sides[v "2"]
Sides[v "2"] := New Vector(master)

; Add the HomeVector to the first point of the side
Sides[v "1"].Add(HomeVector)

; Add the first point of the side to the second point of the side
Sides[v "2"].Add(Sides[v "1"])

; Rotate the master vector by 90 degrees for the next side
master.RotateAngle(90)
}

; Return the dictionary containing the vectors for each side
return Sides
}

;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
class ArrowHead_2	{
	__New( Start , End , HeadLength := 30 , NeckLength := 10 , ArmLength := 30 , ElbowLength := 15 , Scale := 1 ){
		
		Master := This._NewVector( Start )
		This._SubVector( Master , End )
		
		Head := This._NewVector( Master )
		This._SetVectorMag( Head , HeadLength )
		This._AddVector( Head , End )
		
		Neck := This._NewVector( Master )
		This._SetVectorMag( Neck , NeckLength )
		This._AddVector( Neck , Head )
		
		RightArm := This._NewVector( Master , , 1 )
		This._SetVectorMag( RightArm , ArmLength )
		This._AddVector( RightArm , Neck )
		
		RightElbow := This._NewVector( Master , , 1 )
		This._SetVectorMag( RightElbow , ElbowLength )
		This._AddVector( RightElbow , Head )
		
		LeftArm := This._NewVector( Master , , 2 )
		This._SetVectorMag( LeftArm , ArmLength )
		This._AddVector( LeftArm , Neck )
		
		LeftElbow := This._NewVector( Master , , 2 )
		This._SetVectorMag( LeftElbow , ElbowLength )
		This._AddVector( LeftElbow , Head )
		
		OutputString := ""
		for k , v in [ "Start" , "RightElbow" , "RightArm" , "End" , "LeftArm" , "LeftElbow" , "Start" ]	
			OutputString .= %v%.X * Scale "," %v%.Y * Scale "|"
		return OutputString 
	}
	_NewVector( x , y := "" , rotate := 0 ){
		if( IsObject( x ) ){
			if( !rotate )
				return { X: x.X , Y: x.Y }
			else if( rotate = 1 )
				return { X: x.Y * -1 , Y: x.X }
			else if( rotate = 2 )
				return { X: x.Y , Y: x.X * -1 }
		}else{
			if( !rotate )
				return { X: x , Y: x }
			else if( rotate = 1 )
				return { X: y * -1 , Y: x }
			else if( rotate = 2 )
				return { X: y , Y: x * -1 }
		}
	}
	_SubVector( vector1 , vector2 ){
		vector1.X -= vector2.X
		vector1.Y -= vector2.Y
	}
	_AddVector( vector1 , vector2 ){
		vector1.X += vector2.X
		vector1.Y += vector2.Y
	}
	_SetVectorMag( vector , mag ){
		local m := This._GetVectorMag( vector )
		vector.X := vector.X * mag / m
		vector.Y := vector.Y * mag / m
	}
	_GetVectorMag( vector ){
		return Sqrt( vector.X * vector.X + vector.Y * vector.Y )
		
	}
}
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
FillPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFFFF0000" ){
	Brush := Gdip_BrushCreateSolid( Color ) , Gdip_FillPolygon( G , Brush , Points ) , Gdip_DeleteBrush( Brush )
}
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
DrawPolygon( G , Points := "50 , 50 | 100 , 100 | 150 , 50 | 50 , 50 " , Color := "0xFF000000" , Thickness := 3 ){
	Pen := Gdip_CreatePen( Color , Thickness ) , Gdip_DrawLines( G , Pen , Points ) , Gdip_DeletePen( Pen )
}
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################
;############################;############################;############################;############################;############################;############################;############################


;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
class PopUpWindow	{
;PopUpWindow v2.2
;Date Written: Oct 28th, 2021
;Last Edit: Feb 7th, 2022 :Changed the trigger method.
;Written By: Hellbent aka CivReborn
;SpcThanks: teadrinker , malcev 
	static Index := 0 , Windows := [] , Handles := [] , EditHwnd , HelperHwnd
	__New( obj := "" ){
		This._SetDefaults()
		This.UpdateSettings( obj )
		This._CreateWindow()
		This._CreateWindowGraphics()
		if( This.AutoShow )
			This.ShowWindow( This.Title )
	}
	_SetDefaults(){
		This.X := 10
		This.Y := 10
		This.W := 10
		This.H := 10
		This.Smoothing := 2
		This.Options := " -DPIScale +AlwaysOnTop "
		This.AutoShow := 0
		This.GdipStartUp := 0
		This.Title := ""
		
		This.Controls := []
		This.Handles := []
		This.Index := 0 
	}
	AddTrigger( obj ){
		local k , v , cc , bd
		
		This.Controls[ ++This.Index ] := { 	X:		10
										,	Y:		10
										,	W:		10
										,	H:		10	}
		for k, v in obj
			This.Controls[ This.Index ][ k ] := obj[ k ] 
		cc := This.Controls[ This.Index ]
		Gui, % This.Hwnd ":Add", Text, % "x" cc.X " y" cc.Y " w" cc.W " h" cc.H " hwndhwnd"
		This.Handles[ hwnd ] := This.Index
		This.Controls[ This.Index ].Hwnd := hwnd
		
		if( IsObject( cc.Label ) ){
			bd := cc.Label
			GuiControl, % This.Hwnd ":+G" , % hwnd , % bd
		}else{
			bd := This._TriggerCall.Bind( This )
			GuiControl, % This.Hwnd ":+G" , % hwnd , % bd
		}
		return hwnd
		
	}
	_TriggerCall(){
		MouseGetPos,,,, ctrl, 2
		Try
			;~ SetTimer, % This.Controls[ This.Handles[ ctrl ] ].Label, -0
			gosub, % This.Controls[ This.Handles[ ctrl ] ].Label
		
				
	}
	DrawTriggers( color := "0xFFFF0000" , AutoUpdate := 0 ){
		local brush , cc 
		Brush := Gdip_BrushCreateSolid( color ) 
		Gdip_SetSmoothingMode( This.G , 3 )
		loop, % This.Controls.Length()	{
			cc := This.Controls[ A_Index ]
			Gdip_FillRectangle( This.G , Brush , cc.x , cc.y , cc.w , cc.h )
		
		}
		Gdip_DeleteBrush( Brush )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	UpdateSettings( obj := "" , UpdateGraphics := 0 ){
		local k , v
		if( IsObject( obj ) )
			for k, v in obj
				This[ k ] := obj[ k ]
		( This.X = "Center" ) ? ( This.X := ( A_ScreenWidth - This.W ) / 2 ) 	
		( This.Y = "Center" ) ? ( This.Y := ( A_ScreenHeight - This.H ) / 2 ) 	
		if( UpdateGraphics ){
			This._DestroyWindowsGraphics()
			This._CreateWindowGraphics()
		}
	}
	_CreateWindow(){
		local hwnd
		Gui , New, % " +LastFound +E0x80000 hwndhwnd -Caption  " This.Options
		PopUpWindow.Index++
		This.Index := PopUpWindow.Index
		PopUpWindow.Windows[ PopUpWindow.Index ] := This
		This.Hwnd := hwnd
		PopUpWindow.Handles[ hwnd ] := PopUpWindow.Index
		if( This.GdipStartUp && !PopUpWindow.pToken )
			PopUpWindow.pToken := GDIP_STARTUP()
	}
	_DestroyWindowsGraphics(){
		Gdip_DeleteGraphics( This.G )
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
	}
	_CreateWindowGraphics(){
		This.hbm := CreateDIBSection( This.W , This.H )
		This.hdc := CreateCompatibleDC()
		This.obm := SelectObject( This.hdc , This.hbm )
		This.G := Gdip_GraphicsFromHDC( This.hdc )
		Gdip_SetSmoothingMode( This.G , This.Smoothing )
	}
	ShowWindow( Title := "" ){
		Gui , % This.Hwnd ":Show", % "x" This.X " y" This.Y " w" This.W " h" This.H " NA", % Title
	}
	HideWindow(){
		Gui , % This.Hwnd ":Hide",
	}
	UpdateWindow( alpha := 255 ){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H , alpha )
	}
	ClearWindow( AutoUpdate := 0 , Color := "" ){
		if( color != "" )
			Gdip_GraphicsClear( This.G , color )
		else
			Gdip_GraphicsClear( This.G )
		if( Autoupdate )
			This.UpdateWindow()
	}
	DrawBitmap( pBitmap , obj , dispose := 1 , AutoUpdate := 0 ){
		Gdip_DrawImage( This.G , pBitmap , obj.X , obj.Y , obj.W , obj.H )
		if( dispose )
			Gdip_DisposeImage( pBitmap )
		if( Autoupdate )
			This.UpdateWindow()
	}
	PaintBackground( color := "0xFF000000" , AutoUpdate := 0 ){
		if( isObject( color ) ){
			Brush := Gdip_BrushCreateSolid( ( color.HasKey( "Color" ) ) ? ( color.Color ) : ( "0xFF000000" ) ) 
			if( color.Haskey( "Round" ) )
				Gdip_FillRoundedRectangle( This.G , Brush , color.X , color.Y , color.W , color.H , color.Round )
			else
				Gdip_FillRectangle( This.G , Brush , color.X , color.Y , color.W , color.H ) 
		}else{
			Brush := Gdip_BrushCreateSolid( color ) 
			Gdip_FillRectangle( This.G , Brush , -1 , -1 , This.W + 2 , This.H + 2 ) 
		}
		Gdip_DeleteBrush( Brush )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DeleteWindow( GDIPShutdown := 0 ){
		Gui, % This.Hwnd ":Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		hwnd := This.Hwnd
		for k, v in PopUpWindow.Windows[ Hwnd ]
			This[k] := ""
		PopUpWindow.Windows[ Hwnd ] := ""
		if( GDIPShutdown ){
			Gdip_Shutdown( PopUpWindow.pToken )
			PopUpWindow.pToken := ""
		}
	}
	_OnClose( wParam ){
		if( wParam = 0xF060 ){	;SC_CLOSE ;[ clicking on the gui close button ]
			Try{
				Gui, % PopUpWindow.HelperHwnd ":Destroy"
				SoundBeep, 555
			}
		}
	}
	CreateCachedBitmap( pBitmap , Dispose := 0 ){
		local pCachedBitmap
		if( This.CachedBitmap )
			This.DisposeCachedbitmap()
		DllCall( "gdiplus\GdipCreateCachedBitmap" , "Ptr" , pBitmap , "Ptr" , this.G , "PtrP" , pCachedBitmap )
		This.CachedBitmap := pCachedBitmap
		if( Dispose )
			Gdip_DisposeImage( pBitmap )
	}
	DrawCachedBitmap( AutoUpdate := 0 ){
		DllCall( "gdiplus\GdipDrawCachedBitmap" , "Ptr" , this.G , "Ptr" , This.CachedBitmap , "Int" , 0 , "Int" , 0 )
		if( AutoUpdate )
			This.UpdateWindow()
	}
	DisposeCachedbitmap(){
		DllCall( "gdiplus\GdipDeleteCachedBitmap" , "Ptr" , This.CachedBitmap )
	}
	Helper(){
		local hwnd , MethodList := ["__New","UpdateSettings","ShowWindow","HideWindow","UpdateWindow","ClearWindow","DrawBitmap","PaintBackground","DeleteWindow" , "AddTrigger" , "DrawTriggers", "CreateCachedBitmap" , "DrawCachedBitmap" , "DisposeCachedbitmap" ]
		Gui, New, +AlwaysOnTop +ToolWindow +HwndHwnd
		PopUpWindow.HelperHwnd := hwnd
		Gui, Add, Edit, xm ym w250 r1 Center hwndhwnd, Gui1
		PopUpWindow.EditHwnd := hwnd
		loop, % MethodList.Length()	
			Gui, Add, Button, xm y+1 w250 r1 gPopUpWindow._HelperClip, % MethodList[ A_Index ]
		Gui, Show,,
		OnMessage( 0x112 , This._OnClose.Bind( hwnd ) )
	}
	_HelperClip(){
		local ClipList 
		
		GuiControlGet, out, % PopUpWindow.HelperHwnd ":", % PopUpWindow.EditHwnd	
		
		ClipList := 		{ 	__New: 					" := New PopUpWindow( { AutoShow: 1 , X: 0 , Y: 0 , W: A_ScreenWidth , H: A_ScreenHeight , Options: "" -DPIScale +AlwaysOnTop "" } )"
							,	UpdateSettings:			".UpdateSettings( { X: """" , Y: """" , W: """" , H: """" } , UpdateGraphics := 0 )"
							,	ShowWindow:				".ShowWindow( Title := """" )"
							,	HideWindow:				".HideWindow()"
							,	UpdateWindow:			".UpdateWindow()"
							,	ClearWindow:			".ClearWindow( AutoUpdate := 0 )"
							,	DrawBitmap:				".DrawBitmap( pBitmap := """" , { X: 0 , Y: 0 , W: " Out ".W , H: " Out ".H } , dispose := 1 , AutoUpdate := 0 )"
							,	PaintBackground:		".PaintBackground( color := ""0xFF000000"" , AutoUpdate := 0 )  "  ";{ Color: ""0xFF000000"" , X: 2 , Y: 2 , W: " Out ".W - 4 , H: " Out ".H - 4 , Round: 10 }"
							,	DeleteWindow:			".DeleteWindow( GDIPShutdown := 0 )"
							,	AddTrigger:				".AddTrigger( { X: """" , Y: """" , W: """" , H: """" , Value: """" , Label: """" } )"	
							,	DrawTriggers:			".DrawTriggers( color := ""0xFFFF0000"" , AutoUpdate := 0 )"	
							,	CreateCachedBitmap:		".CreateCachedBitmap( pBitmap , Dispose := 0 )"	
							,	DrawCachedBitmap: 		".DrawCachedBitmap( AutoUpdate := 0 )"	
							,	DisposeCachedbitmap:	".DisposeCachedbitmap()"	}
							
		clipboard := Out ClipList[ A_GuiControl ]
		
	}
}
;************
;Vector Class
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************
Class Vector	{
	;Written By: HB
	;Date: Sept 23rd, 2022
	;Last Edit: Sept 24th, 2022
	;Purpose: Vector math class 
	;Credit: Rohwedder 
	;Resources: 
		;Line intercept concepts and code: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=37175
		;Create an Arrow: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=92039&p=479129#p478944
		;Getting an angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483661#p483678
		;Setting an Angle: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=108760&p=483786#p483811
		;
		
	static RadToDeg := 45 / ATan( 1 ) 
		, DegToRad := ATan( 1 ) / 45 
		
	__New( x := 0 , y := 0 , rotate := 0 ){ 
		if( IsObject( x ) ){
			if( rotate = 3 ){
				This.X := x.X * -1
				,This.Y := x.Y * -1
			}else if( rotate = 2 ){
				This.X := x.Y 
				,This.Y := x.X * -1
			}else if( rotate = 1 ){
				This.X := x.Y * -1
				,This.Y := x.X 
			}else{
				This.X := x.X
				,This.Y := x.Y
			}
		}else{
			if( rotate = 3 ){
				This.X := X * -1
				,This.Y := Y * -1
			}else if( rotate = 2 ){
				This.X := Y 
				,This.Y := X * -1
			}else if( rotate = 1 ){
				This.X := Y * -1
				,This.Y := X 
			}else{
				This.X := X
				,This.Y := Y
			}
		}
	}
	Add( x , y := "" ){
		if( IsObject( x ) ){
			This.X += x.X
			,This.Y += x.Y
		}else if( y = "" ){
			This.X += x 
			,This.Y += x
		}else{
			This.X += x 
			,This.Y += y 
		}
	}
	Sub( x , y := "" ){
		if( IsObject( x ) ){
			This.X -= x.X
			,This.Y -= x.Y
		}else if( y = "" ){
			This.X -= X
			,This.Y -= X
		}else{
			This.X -= X
			,This.Y -= Y
		}
	}
	Div( x , y := "" ){
		if( IsObject( x ) ){
			This.X /= x.X
			,This.Y /= x.Y
		}else if( x && y = "" ){
			This.X /= x 
			,This.Y /= x 
		}else{
			This.X /= X
			,This.Y /= Y
		}
	}
	Mult( x , y := "" ){
		if( IsObject( x ) ){
			This.X *= x.X
			,This.Y *= x.Y
		}else if( x && y = "" ){
			This.X *= x 
			,This.Y *= x 
		}else{
			This.X *= X
			,This.Y *= Y
		}
	}
	Dist( x , y := "" ){
		if( IsObject( x ) )
			return Sqrt( ( ( This.X - x.X ) **2 ) + ( ( This.Y - x.Y ) **2 ) )
		else 
			return Sqrt( ( ( This.X - X ) **2 ) + ( ( This.Y - Y ) **2 ) )
	}
	GetMag(){
		return Sqrt( This.X * This.X + This.Y * This.Y )
	}
	SetMag( magnitude ){
		local m := This.GetMag()
		This.X := This.X * magnitude / m
		,This.Y := This.Y * magnitude / m
	}
	MagSq(){
		return This.GetMag()**2
	}	
	Dot( x , y := "" ){
		if( IsObject( x ) )
			return ( This.X * x.X ) + ( This.Y * x.Y )
		else
			return ( This.X * X ) + ( This.Y * Y )
	}
	Cross( x , y := "" ){
		if( IsObject( x ) )
			return This.X * x.Y - This.Y * x.X
		else
			return This.X * Y - This.Y * X
		
	}
	Norm(){
		local m := This.GetMag()
		This.X /= m
		This.Y /= m
	}
	GetAngle(){ 
		local angle 
		( (  angle := Vector.RadToDeg * DllCall( "msvcrt\atan2" , "Double" , This.Y , "Double" , This.X , "CDECL Double" ) ) < 0 ) ? ( angle += 360 )
		return angle
	}
	SetAngle( newAngle := 0 , NewVector := 0 ){
		local Angle := This.GetAngle()
		, ChangeAngle := newAngle - Angle 
		, Co := Cos( Vector.DegToRad * ChangeAngle )
		, Si := Sin( Vector.DegToRad * ChangeAngle )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	RotateAngle( rotationAmount := 90 , NewVector := 0 ){
		local Co := Cos( Vector.DegToRad * rotationAmount )
		, Si := Sin( Vector.DegToRad * rotationAmount )
		, X := This.X 
		, Y := This.Y
		, X2 := X * Co - Y * Si 
		, Y2 := X * Si + Y * Co 
		
		if( !NewVector )
			This.X := X2 , This.Y := Y2
		else 
			return New Vector( X2 , Y2 )
	}
	;********************************************
	;class methods
	TestLineInterceptPoint( interceptPoint , Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } } , interceptPoint = { X: , Y: }
		local
		for k , v in [ "X" , "Y" ]	
			M%v%_Min := min( Line1.Start[ v ] , Line1.End[ v ] )
			,M%v%_Max := max( Line1.Start[ v ] , Line1.End[ v ] )
			,L%v%_Min := min( Line2.Start[ v ] , Line2.End[ v ] )
			,L%v%_Max := max( Line2.Start[ v ] , Line2.End[ v ] )
		if( !( interceptPoint.X < Mx_Min || interceptPoint.X > Mx_Max || interceptPoint.X < Lx_Min || interceptPoint.X > Lx_Max ) && !( interceptPoint.Y < My_Min || interceptPoint.Y > My_Max || interceptPoint.Y < Ly_Min || interceptPoint.Y > Ly_Max ) )
			return 1
		return 0
	}
	GetLineInterceptPoint( Line1 , Line2 ){ ; Line = { Start: { X: , Y: } , End: { X: , Y: } }
		local A1 := Line1.End.Y - Line1.Start.Y
		,B1 := Line1.Start.X - Line1.End.X
		,C1 := A1 * Line1.Start.X + B1 * Line1.Start.Y
		,A2 := Line2.End.Y - Line2.Start.Y
		,B2 := Line2.Start.X - Line2.End.X
		,C2 := A2 * Line2.Start.X + B2 * Line2.Start.Y
		,Denominator := A1 * B2 - A2 * B1 
		return New Vector( { X: ( ( B2 * C1 - B1 * C2 ) / Denominator )  , Y: ( ( A1 * C2 - A2 * C1 ) / Denominator ) } )
	}
	;********************************************
}
;**************************************************************************************************************************************************************************
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 00000 <<<>>> 00000 
;**************************************************************************************************************************************************************************



Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Bing [Bot], Chunjee, fertalizer, Pianist, pond_pop and 184 guests