Need help with GDI button and Layered Window

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Need help with GDI button and Layered Window

Post by doubledave22 » 06 Feb 2022, 13:11

I am trying to design a layered window gui that will display a few buttons.

After a lot of testing I know it has to be a layered window because
1) The text will display much better at smaller sizes
2) The rounded edges will remain crisp
3) I won't have to worry about transcolor and winset which leave artifacts

My question is... why can't I get the layered window to show once I uncomment line 22: ;+E0x80000?

I think I am missing something somewhat core to layered windows here. I've used them in the past for single image GUI's but having trouble when adding additional buttons.

Once I get this working I will try to build it into a class and clean it up. i know @Hellbent has done something similar and I am basing a decent bit off his work and example 8 of the gdip library.

Here's the full script: try to uncomment line 22 -> ; +E0x80000 to make it a layered window and try to help me understand why it's not showing up.

Code: Select all

; gdi+ ahk tutorial 8 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Tutorial to write text onto a gui

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip_All.ahk

; Start gdi+
If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}
OnExit, Exit

; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption
Gui, 1: -Caption +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs ;+E0x80000 

Btn_Width := 160
Btn_Height := Btn_Width/2
Offset := round(Btn_Width/15)

; Default Button
pBitmap := Create_Button(Btn_Width)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)

; Pressed Button
pBitmap2 := Create_Button(Btn_Width, 0)
hBitmap2 := Gdip_CreateHBITMAPFromBitmap(pBitmap2)

Gui, 1: margin, 0, 0
Gui, 1: Add, Picture,% " x0 y0 0xE w" Btn_Width " h" Btn_Height " gClickedButton vMainButton1 hwndMainButton1"
Gui, 1: Add, Picture,% " x" Btn_Width + 10 " y0 0xE w" Btn_Width " h" Btn_Height " gClickedButton vMainButton2 hwndMainButton2"
Gui, 1: Show, NA, My Window
hwnd1 := Winexist()

SetImage(MainButton1, hBitmap)
SetImage(MainButton2, hBitmap)

; get whole GUI width in case we add extra buttons
Wingetpos, , , Width, Height

hbm := CreateDIBSection(Width, Height)

; Get a device context compatible with the screen
hdc := CreateCompatibleDC()

; Select the bitmap into the device context
obm := SelectObject(hdc, hbm)

; Get a pointer to the graphics of the bitmap, for use with drawing functions
G := Gdip_GraphicsFromHDC(hdc)

; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling)
Gdip_SetSmoothingMode(G, 4)

UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height)

SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)

Gdip_DisposeImage(pBitmap)
Gdip_DisposeImage(pBitmap2)
Return

ClickedButton:
RegExMatch(a_guicontrol,"\d",Num)
guicontrol, 1: movedraw,% MainButton%Num%, y%Offset%
SetImage(MainButton%Num%, hBitmap2) " and " hBitmap2 " and " MainButton

while GetKeyState("LButton","P")
	sleep, 10

guicontrol, 1: movedraw, % MainButton%Num%, y0
SetImage(MainButton%Num%, hBitmap)
return

Create_Button(Width, ShowBG := 1)
{
	Height := Width/2
	Offset := round(Width/15)
	Rounding := (Width/10)
	Font_Size := (Width/5)
	Font := "Arial"
	
	pBitmap := Gdip_CreateBitmap(Width, Height)
	
	G := Gdip_GraphicsFromImage(pBitmap)
	Gdip_SetSmoothingMode(G, 2)
	
	if (ShowBG)
	{
		pBrush1 := Gdip_BrushCreateSolid(0xFFbc8282)
		Gdip_FillRoundedRectangle(G, pBrush1, 0, 0, Width, Height, Rounding)
		Gdip_DeleteBrush(pBrush1)
	}
	
	pBrush2 := Gdip_BrushCreateSolid(0xFFa15656)
	Gdip_FillRoundedRectangle(G, pBrush2, 0, 0, Width, Height-(Offset), Rounding)
	Gdip_DeleteBrush(pBrush2)
	
	If !Gdip_FontFamilyCreate(Font)
	{
	   MsgBox, 48, Font error!, The font you have specified does not exist on the system
	   ExitApp
	}

	Options = vCenter Centre cFFffffff r4 s%Font_Size% Bold
	Gdip_TextToGraphics(G, "Button", Options, Font, Width, Height-Offset/2)
	Gdip_DeleteGraphics(G)
	return pBitmap
}


Exit:
; gdi+ may now be shutdown on exiting the program
DeleteObject(hBitmap)
DeleteObject(hBitmap2)
Gdip_Shutdown(pToken)
ExitApp
Return

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Need help with GDI button and Layered Window

Post by doubledave22 » 06 Feb 2022, 15:41

Starting to make some progress. Using hellbents layered window class. Had to add vName to Add_Trigger and make it static to get control names of triggers.

What I can't seem to understand is how to update a single bitmap in the ClickedButton() glabel. If i call ClearWindow() it will clear all buttons and I'd have to rebuild the all the controls again. I need the original bitmap to be deleted (or hidden?), show the pressed button bitmap, then return to start state when released.

How do I update a single control I've drawn on the layered window? Or do I have to clear the whole window whenever I want to remove a control?

Code: Select all

; gdi+ ahk tutorial 8 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Tutorial to write text onto a gui

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip_All.ahk
;~ #Include, LayeredWindow.ahk

; Start gdi+
If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}
OnExit, Exit

Btn_Width := 150
Btn_Height := Btn_Width/2

NLW := new LayeredWindow( (A_ScreenWidth-Btn_Width)//2		; x
						, (A_ScreenHeight-Btn_Height)//2 	; y
						, 1920 								; w
						, 1080 								; h
						, 1 								; window 
						, "" 								; title
						, 4 								; smoothing
						, "" 								; options ; "+Owner" Winexist("A") 
						, 1 								; autoShow
						, 0 								; GdipStart
						, 									; WinMover := {x:0,y:0,w:200,h:200}	
						, "" )								; BackgroundColor


OffsetX := round(Btn_Width/15)
OffsetY := round(Btn_Width/15)

pBitmap := Create_Button(Btn_Width, OffsetX, OffsetY)

Btn_1 := {x: 0, y: 0, w: Btn_Width, h: Btn_Height, v: "Button1"}
Btn_2 := {x: Btn_Width+10, y: 0, w: Btn_Width, h: Btn_Height, v: "Button2"}

pBitmap2 := Create_Button(Btn_Width, OffsetX, OffsetY)
NLW.Draw(pBitmap,Btn_1)
NLW.Draw(pBitmap,Btn_2)

NLW.Add_Trigger(Btn_1,"ClickedButton")
NLW.Add_Trigger(Btn_2,"ClickedButton")
return

ClickedButton()
{
	global
	
	local Num
	
	RegExMatch(a_guicontrol,"\d+",Num)

	 ;~ NLW.ClearWindow()
	pBitmap := Create_Button(Btn_Width, OffsetX, OffsetY, 0)

	Btn_%Num%.x += OffsetX
	Btn_%Num%.y += OffsetY
	NLW.Draw(pBitmap,Btn_%Num%)

	;~ NLW.UpdateWindow()

	while GetKeyState("LButton","P")
		sleep, 10

	;~ NLW.ClearWindow()
	pBitmap := Create_Button(Btn_Width, OffsetX, OffsetY)
	Btn_%Num%.x -= OffsetX
	Btn_%Num%.y -= OffsetY
	NLW.Draw(pBitmap,Btn_%Num%)
}

Create_Button(Width, OffsetX, OffsetY, ShowBG := 1)
{
	Height := Width/2
	Rounding := (Width/10)
	Font_Size := (Width/5)
	Font := "Arial"
	
	pBitmap := Gdip_CreateBitmap(Width, Height)
	
	G := Gdip_GraphicsFromImage(pBitmap)
	Gdip_SetSmoothingMode(G, 2)
	
	if (ShowBG)
	{
		pBrush1 := Gdip_BrushCreateSolid(0xFFa15656)
		Gdip_FillRoundedRectangle(G, pBrush1, 0, 0, Width, Height, Rounding)
		Gdip_DeleteBrush(pBrush1)
	}
	
	pBrush2 := Gdip_BrushCreateSolid(0xFFbc8282)
	Gdip_FillRoundedRectangle(G, pBrush2, 0, 0, Width-(OffsetX), Height-(OffsetY), Rounding)
	Gdip_DeleteBrush(pBrush2)
	
	If !Gdip_FontFamilyCreate(Font)
	{
	   MsgBox, 48, Font error!, The font you have specified does not exist on the system
	   ExitApp
	}

	Options = vCenter Centre cFFffffff r4 s%Font_Size% Bold
	Gdip_TextToGraphics(G, "Button", Options, Font, Width, Height-OffsetY/2)
	Gdip_DeleteGraphics(G)
	return pBitmap
}


Exit:
; gdi+ may now be shutdown on exiting the program
Gdip_Shutdown(pToken)
ExitApp
Return




class LayeredWindow	{
;LayeredWindow class By: Hellbent
	__New( x := 0 , y := 0 , w := 100 , h := 100 , window := 1 , title := " " , smoothing := 4 , options := "" , autoShow := 1 , GdipStart := 0 , WinMover := "" , BackgroundColor := "" ){
		This.X := x , This.Y := y , This.W := w , This.H := h 
		This.Window := window , This.Title := title
		This.Options := options , This.Smoothing := smoothing
		( GdipStart ) ? ( This.Token := Gdip_Startup() )
		This._CreateWindow()
		( autoShow ) ? ( This.ShowWindow() )
		This._SetUpdateLayeredWindow()
		( WinMover ) ? ( This._AddMoveTrigger( WinMover ) )
		( BackgroundColor ) ? ( This.PaintBackground( BackgroundColor , 1 ) )
	}
	_CreateWindow(){
		Gui , % This.Window ": New" , % " +E0x80000 +LastFound -Caption " This.Options 
		This.Hwnd := WinExist()
		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 )
	}
	_SetUpdateLayeredWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc )
	}
	ShowWindow( update := 1 , Position := "" ){ 
		if( !Position )
			Gui , % This.Window ": Show" , % "w" This.W " h" This.H  , % ( This.Title ) ? ( This.Title ) : ( "" )
		else
			Gui , % This.Window ": Show" , % "x" Position.X " y" Position.Y "w" Position.W " h" Position.H  , % ( This.Title ) ? ( This.Title )  : ( "" )
		( update ) ? ( This.UpdateWindow() )
	}
	_AddMoveTrigger( positons ){ 
		local hwnd , bd
		Gui , % This.Window " : Add" , Text , % "x" positons.x " y" positons.y " w" positons.w " h" positons.h " hwndhwnd"
		This.MoveHwnd := hwnd
		bd := This._WindowMover.Bind( This )
		GuiControl , % This.Window ": +G" , % This.MoveHwnd , % bd
	}
	_WindowMover(){ 
		PostMessage, 0xA1 , 2
	}
	PaintBackground( BackgroundColor := "0xFF000000" , update := 0){ 
		local Brush
		This.BackgroundColor := BackgroundColor
		Brush := Gdip_BrushCreateSolid( BackgroundColor )
		Gdip_FillRectangle( This.G , Brush , 0 , 0 , This.W , This.H )
		Gdip_DeleteBrush( Brush )
		( update ) ? ( This.UpdateWindow() )
	}
	Draw( pBitmap , Positions := "" , update := 1 , disposeBitmap := 0  , PaintBackground := 0){ 
	(PaintBackground) ? ( This.PaintBackground( This.BackgroundColor ) )	
		Gdip_DrawImage( This.G 
						, pBitmap 
						, ( Positions.X1 ) ? ( Positions.X1 ) : ( Positions.X ) ? ( Positions.X ) : ( "" )
						, ( Positions.Y1 ) ? ( Positions.Y1 ) : ( Positions.Y ) ? ( Positions.Y ) : ( "" ) 
						, ( Positions.W1 ) ? ( Positions.W1 ) : ( Positions.W ) ? ( Positions.W ) : ( "" ) 
						, ( Positions.H1 ) ? ( Positions.H1 ) : ( Positions.H ) ? ( Positions.H ) : ( "" ) 
						, ( Positions.X2 ) ? ( Positions.X2 ) : ( Positions.SX ) ? ( Positions.SX ) : ( "" )
						, ( Positions.Y2 ) ? ( Positions.Y2 ) : ( Positions.SY ) ? ( Positions.SY ) : ( "" )
						, ( Positions.W2 ) ? ( Positions.W2 ) : ( Positions.SW ) ? ( Positions.SW ) : ( "" )
						, ( Positions.H2 ) ? ( Positions.H2 ) : ( Positions.SH ) ? ( Positions.SH ) : ( "" ) )
		( update ) ? ( This.UpdateWindow() )
		( disposeBitmap ) ? ( Gdip_DisposeImage( pBitmap ) )
	}
	ClearWindow( update := "" ){ 
		Gdip_GraphicsClear( This.G )
		( update ) ? ( This.UpdateWindow() )
	}
	Add_Trigger(PositionObject,Label:="GuiClose"){
		static
		Gui, % This.Window ": Add", Text, % "x" PositionObject.X " y" PositionObject.Y " w" PositionObject.W " h" PositionObject.H " v" PositionObject.V " g" Label " BackgroundTrans"
	}
	Draw_Text(PosObj,Text,Font:="Arial",FontSize:="12",Color1:="0xFFFFFFFF",Color2:="",PosObj2:="",update:=0){
		local Brush
		(!color2&&color2!="000000")?(Color2:=Color1)
		(StrLen(Color1)=6)?( Color1 := "0xFF" Color1 )
		(StrLen(Color2)=6)?( Color2 := "0xFF" Color2 )
		(PosObj2="")?(PosObj2:=PosObj)
		Brush := Gdip_CreateLineBrushFromRect( 0 , 0 , PosObj2.W , PosObj2.H , Color1 , Color2 , 1 , 1 )
		Gdip_TextToGraphics(This.G, Text, "s" FontSize " c" Brush " Center vCenter Bold x" PosObj.X " y" PosObj.Y, Font , PosObj.W, PosObj.H)
		Gdip_DeleteBrush( Brush )
		( update ) ? ( This.UpdateWindow() )
	}
	Draw_Rectangle(Thickness:="5",PosObj:="",Color1:=0xFFFFFFFF,Color2:="",PosObj2:="",update:=0){
		local Brush, pPen
		(!color2)?(Color2:=Color1)
		(StrLen(Color1)=6)?( Color1 := "0xFF" Color1 )
		(StrLen(Color2)=6)?( Color2 := "0xFF" Color2 )
		(PosObj2="")?(PosObj2:=PosObj)
		Brush := Gdip_CreateLineBrushFromRect( 0 , 0 , PosObj2.W , PosObj2.H , Color1 , Color2 , 1 , 1 )
		pPen := Gdip_CreatePenFromBrush(Brush, Thickness)
		Gdip_DrawRectangle( This.G, pPen, PosObj.X , PosObj.Y , PosObj.W , PosObj.H )
		Gdip_DeleteBrush( Brush )
		Gdip_DeletePen(pPen)
		( update ) ? ( This.UpdateWindow() )
	}
	DeleteWindow( TurnOffGdip := 0 ){
		Gui, % This.Window " : Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		( TurnOffGdip && This.Token ) ? ( Gdip_Shutdown( This.Token ) )
	}
}


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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 06 Feb 2022, 15:45

You don't use normal controls like that when you are using a layered window.
You just draw to the graphics and then update the window.

Code: Select all

;******************************************************************************************************************************************************************************************
;******************************************************************************************************************************************************************************************
Gdip_DrawImage( G , pBitmap , 0 , 0 , Btn_Width , Btn_Height )
Gdip_DrawImage( G , pBitmap , Btn_Width + 10 , 0 , Btn_Width , Btn_Height )
;******************************************************************************************************************************************************************************************
;******************************************************************************************************************************************************************************************
I have made a quick edit to your code ( seen above ) to get it to work.
If you are writing this for windows 8+ you can keep the picture controls there to act as click triggers and to use the controls hwnd in a hover function.

Code: Select all

; gdi+ ahk tutorial 8 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Tutorial to write text onto a gui

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

; Uncomment if Gdip.ahk is not in your standard library
#Include <My Altered GDIP lib>

; Start gdi+
If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}
OnExit, Exit

; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption
Gui, 1: -Caption +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs +E0x80000 

Btn_Width := 160
Btn_Height := Btn_Width/2
Offset := round(Btn_Width/15)

; Default Button
pBitmap := Create_Button(Btn_Width)
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)

; Pressed Button
pBitmap2 := Create_Button(Btn_Width, 0)
hBitmap2 := Gdip_CreateHBITMAPFromBitmap(pBitmap2)

Gui, 1: margin, 0, 0
Gui, 1: Add, Picture,% " x0 y0 0xE w" Btn_Width " h" Btn_Height " gClickedButton vMainButton1 hwndMainButton1"
Gui, 1: Add, Picture,% " x" Btn_Width + 10 " y0 0xE w" Btn_Width " h" Btn_Height " gClickedButton vMainButton2 hwndMainButton2"
Gui, 1: Show, NA, My Window
hwnd1 := Winexist()

SetImage(MainButton1, hBitmap)
SetImage(MainButton2, hBitmap)

; get whole GUI width in case we add extra buttons
Wingetpos, , , Width, Height

hbm := CreateDIBSection(Width, Height)

; Get a device context compatible with the screen
hdc := CreateCompatibleDC()

; Select the bitmap into the device context
obm := SelectObject(hdc, hbm)

; Get a pointer to the graphics of the bitmap, for use with drawing functions
G := Gdip_GraphicsFromHDC(hdc)

; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling)
Gdip_SetSmoothingMode(G, 4)


;******************************************************************************************************************************************************************************************
;******************************************************************************************************************************************************************************************
Gdip_DrawImage( G , pBitmap , 0 , 0 , Btn_Width , Btn_Height )
Gdip_DrawImage( G , pBitmap , Btn_Width + 10 , 0 , Btn_Width , Btn_Height )
;******************************************************************************************************************************************************************************************
;******************************************************************************************************************************************************************************************

UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height)

SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)

Gdip_DisposeImage(pBitmap)
Gdip_DisposeImage(pBitmap2)
Return

ClickedButton:
RegExMatch(a_guicontrol,"\d",Num)
guicontrol, 1: movedraw,% MainButton%Num%, y%Offset%
SetImage(MainButton%Num%, hBitmap2) " and " hBitmap2 " and " MainButton

while GetKeyState("LButton","P")
	sleep, 10

guicontrol, 1: movedraw, % MainButton%Num%, y0
SetImage(MainButton%Num%, hBitmap)
return

Create_Button(Width, ShowBG := 1)
{
	Height := Width/2
	Offset := round(Width/15)
	Rounding := (Width/10)
	Font_Size := (Width/5)
	Font := "Arial"
	
	pBitmap := Gdip_CreateBitmap(Width, Height)
	
	G := Gdip_GraphicsFromImage(pBitmap)
	Gdip_SetSmoothingMode(G, 2)
	
	if (ShowBG)
	{
		pBrush1 := Gdip_BrushCreateSolid(0xFFbc8282)
		Gdip_FillRoundedRectangle(G, pBrush1, 0, 0, Width, Height, Rounding)
		Gdip_DeleteBrush(pBrush1)
	}
	
	pBrush2 := Gdip_BrushCreateSolid(0xFFa15656)
	Gdip_FillRoundedRectangle(G, pBrush2, 0, 0, Width, Height-(Offset), Rounding)
	Gdip_DeleteBrush(pBrush2)
	
	If !Gdip_FontFamilyCreate(Font)
	{
	   MsgBox, 48, Font error!, The font you have specified does not exist on the system
	   ExitApp
	}

	Options = vCenter Centre cFFffffff r4 s%Font_Size% Bold
	Gdip_TextToGraphics(G, "Button", Options, Font, Width, Height-Offset/2)
	Gdip_DeleteGraphics(G)
	return pBitmap
}


Exit:
; gdi+ may now be shutdown on exiting the program
DeleteObject(hBitmap)
DeleteObject(hBitmap2)
Gdip_Shutdown(pToken)
ExitApp
Return


Seeing as you are just starting out with layered windows I might be worth it for you to have a look at this class I made to simplify working with them.

Here is an example of how to use the class to create the window and draw a button on it.
There is a tool that you can access by adding a hotkey and calling "PopupWindow.Helper()". The tool has a button that will put a example call for that method into your clipboard.

I recently added a few params that don't show up in the tool output yet, they are typically autoupdate (the last param in "Gui1.DrawBitmap") or autoshow as seen in "Gui1 := New Popupwindow( ..." below.

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib>  ;<---Gdip.ahk lib
;#Include <PopUpWindow Class> 	;Located at the bottom of this script
;****************************************************************************************************************************************************************************
#SingleInstance, Force
Gdip_Startup()

Btn_Width := 160
Btn_Height := Btn_Width/2

Gui1 := New PopUpWindow( { AutoShow: 1 , X: "Center" , Y: "Center" , W: Btn_Width , H: Btn_Height , Options: " -DPIScale +AlwaysOnTop " } ) 
Gui1.DrawBitmap( Create_Button( Btn_Width ) , { X: 0 , Y: 0 , W: Btn_Width , H: Btn_Height } , dispose := 1 , 1 )

return
*ESC::ExitApp

F1::PopUpWindow.Helper()




Create_Button(Width, ShowBG := 1)
{
	Height := Width/2
	Offset := round(Width/15)
	Rounding := (Width/10)
	Font_Size := (Width/5)
	Font := "Arial"
	
	pBitmap := Gdip_CreateBitmap(Width, Height)
	
	G := Gdip_GraphicsFromImage(pBitmap)
	Gdip_SetSmoothingMode(G, 2)
	
	if (ShowBG)
	{
		pBrush1 := Gdip_BrushCreateSolid(0xFFbc8282)
		Gdip_FillRoundedRectangle(G, pBrush1, 0, 0, Width, Height, Rounding)
		Gdip_DeleteBrush(pBrush1)
	}
	
	pBrush2 := Gdip_BrushCreateSolid(0xFFa15656)
	Gdip_FillRoundedRectangle(G, pBrush2, 0, 0, Width, Height-(Offset), Rounding)
	Gdip_DeleteBrush(pBrush2)
	
	If !Gdip_FontFamilyCreate(Font)
	{
	   MsgBox, 48, Font error!, The font you have specified does not exist on the system
	   ExitApp
	}

	Options = vCenter Centre cFFffffff r4 s%Font_Size% Bold
	Gdip_TextToGraphics(G, "Button", Options, Font, Width, Height-Offset/2)
	Gdip_DeleteGraphics(G)
	return pBitmap
}



;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
class PopUpWindow	{
;PopUpWindow v2
;Date Written: Oct 28th, 2021
;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
		return hwnd
		
	}
	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(){
		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( { 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 )"
							,	PaintBackground:		".PaintBackground( color := ""0xFF000000"" )  "  ";{ 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: """" , BoundClass: """" , BoundMethod: """" } )"	
							,	DrawTriggers:			".DrawTriggers( color := ""0xFFFF0000"" , AutoUpdate := 0 )"	
							,	CreateCachedBitmap:		".CreateCachedBitmap( pBitmap , Dispose := 0 )"	
							,	DrawCachedBitmap: 		".DrawCachedBitmap( AutoUpdate := 0 )"	
							,	DisposeCachedbitmap:	".DisposeCachedbitmap()"	}
							
		clipboard := Out ClipList[ A_GuiControl ]
		
	}
}

***EDIT*** Just saw your new post.

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Need help with GDI button and Layered Window

Post by doubledave22 » 06 Feb 2022, 15:48

shoot @Hellbent I just posted a revised version with your layered windows class. I will study your response but take a look at my second example above if you can!

Can't thank you enough... I am beginning the journey of learning about layered windows since it's the only way I can get things to look how I want.

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Need help with GDI button and Layered Window

Post by doubledave22 » 06 Feb 2022, 16:10

I guess I have to do something like this... just seems ineffecient. Also I notice with updating all controls each time there's some flickering. Check out the gif:
https://gyazo.com/d39783ca8e4f9b389fa3f053009b9886

Code: Select all

; gdi+ ahk tutorial 8 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Tutorial to write text onto a gui

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip_All.ahk
;~ #Include, LayeredWindow.ahk

; Start gdi+
If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}
OnExit, Exit

Btn_Width := 150
Btn_Height := Btn_Width/2
Button_Count := 5

NLW := new LayeredWindow( (A_ScreenWidth-Btn_Width)//2		; x
						, (A_ScreenHeight-Btn_Height)//2 	; y
						, 1920 								; w
						, 1080 								; h
						, 1 								; window 
						, "" 								; title
						, 4 								; smoothing
						, "" 								; options ; "+Owner" Winexist("A") 
						, 1 								; autoShow
						, 0 								; GdipStart
						, 									; WinMover := {x:0,y:0,w:200,h:200}	
						, "" )								; BackgroundColor

OffsetX := round(Btn_Width/15)
OffsetY := round(Btn_Width/15)

Button_Default := Create_Button(Btn_Width, OffsetX, OffsetY)
Button_Pressed := Create_Button(Btn_Width, OffsetX, OffsetY,0)

loop, % Button_Count
{
	Btn_%a_index% := {x: (a_index - 1) * Btn_Width + 10*(a_index - 1), y: 0, w: Btn_Width, h: Btn_Height, v: "Button" a_index}
	NLW.Draw(Button_Default,Btn_%a_index%)
	NLW.Add_Trigger(Btn_%a_index%,"ClickedButton")
}

return

ClickedButton()
{
	global
	
	local Num
	
	RegExMatch(a_guicontrol,"\d+",Num)

	NLW.ClearWindow()
	
	Btn_%Num%.x += OffsetX
	Btn_%Num%.y += OffsetY
	
	loop, % Button_Count
	{
		if (a_index = Num)
			NLW.Draw(Button_Pressed,Btn_%a_index%)
		else
			NLW.Draw(Button_Default,Btn_%a_index%)
	}
	
	while GetKeyState("LButton","P")
		sleep, 10

	NLW.ClearWindow()
	Btn_%Num%.x -= OffsetX
	Btn_%Num%.y -= OffsetY
	
	loop, % Button_Count
		NLW.Draw(Button_Default,Btn_%a_index%)
}

Create_Button(Width, OffsetX, OffsetY, ShowBG := 1)
{
	Height := Width/2
	Rounding := (Width/10)
	Font_Size := (Width/5)
	Font := "Arial"
	
	pBitmap := Gdip_CreateBitmap(Width, Height)
	
	G := Gdip_GraphicsFromImage(pBitmap)
	Gdip_SetSmoothingMode(G, 2)
	
	if (ShowBG)
	{
		pBrush1 := Gdip_BrushCreateSolid(0xFFa15656)
		Gdip_FillRoundedRectangle(G, pBrush1, 0, 0, Width, Height, Rounding)
		Gdip_DeleteBrush(pBrush1)
	}
	
	pBrush2 := Gdip_BrushCreateSolid(0xFFbc8282)
	Gdip_FillRoundedRectangle(G, pBrush2, 0, 0, Width-(OffsetX), Height-(OffsetY), Rounding)
	Gdip_DeleteBrush(pBrush2)
	
	If !Gdip_FontFamilyCreate(Font)
	{
	   MsgBox, 48, Font error!, The font you have specified does not exist on the system
	   ExitApp
	}

	Options = vCenter Centre cFFffffff r4 s%Font_Size% Bold
	Gdip_TextToGraphics(G, "Button", Options, Font, Width, Height-OffsetY/2)
	Gdip_DeleteGraphics(G)
	return pBitmap
}


Exit:
Gdip_DisposeImage( Button_Default )
Gdip_DisposeImage( Button_Pressed )
; gdi+ may now be shutdown on exiting the program
Gdip_Shutdown(pToken)
ExitApp
Return




class LayeredWindow	{
;LayeredWindow class By: Hellbent
	__New( x := 0 , y := 0 , w := 100 , h := 100 , window := 1 , title := " " , smoothing := 4 , options := "" , autoShow := 1 , GdipStart := 0 , WinMover := "" , BackgroundColor := "" ){
		This.X := x , This.Y := y , This.W := w , This.H := h 
		This.Window := window , This.Title := title
		This.Options := options , This.Smoothing := smoothing
		( GdipStart ) ? ( This.Token := Gdip_Startup() )
		This._CreateWindow()
		( autoShow ) ? ( This.ShowWindow() )
		This._SetUpdateLayeredWindow()
		( WinMover ) ? ( This._AddMoveTrigger( WinMover ) )
		( BackgroundColor ) ? ( This.PaintBackground( BackgroundColor , 1 ) )
	}
	_CreateWindow(){
		Gui , % This.Window ": New" , % " +E0x80000 +LastFound -Caption " This.Options 
		This.Hwnd := WinExist()
		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 )
	}
	_SetUpdateLayeredWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc )
	}
	ShowWindow( update := 1 , Position := "" ){ 
		if( !Position )
			Gui , % This.Window ": Show" , % "w" This.W " h" This.H  , % ( This.Title ) ? ( This.Title ) : ( "" )
		else
			Gui , % This.Window ": Show" , % "x" Position.X " y" Position.Y "w" Position.W " h" Position.H  , % ( This.Title ) ? ( This.Title )  : ( "" )
		( update ) ? ( This.UpdateWindow() )
	}
	_AddMoveTrigger( positons ){ 
		local hwnd , bd
		Gui , % This.Window " : Add" , Text , % "x" positons.x " y" positons.y " w" positons.w " h" positons.h " hwndhwnd"
		This.MoveHwnd := hwnd
		bd := This._WindowMover.Bind( This )
		GuiControl , % This.Window ": +G" , % This.MoveHwnd , % bd
	}
	_WindowMover(){ 
		PostMessage, 0xA1 , 2
	}
	PaintBackground( BackgroundColor := "0xFF000000" , update := 0){ 
		local Brush
		This.BackgroundColor := BackgroundColor
		Brush := Gdip_BrushCreateSolid( BackgroundColor )
		Gdip_FillRectangle( This.G , Brush , 0 , 0 , This.W , This.H )
		Gdip_DeleteBrush( Brush )
		( update ) ? ( This.UpdateWindow() )
	}
	Draw( pBitmap , Positions := "" , update := 1 , disposeBitmap := 0  , PaintBackground := 0){ 
	(PaintBackground) ? ( This.PaintBackground( This.BackgroundColor ) )	
		Gdip_DrawImage( This.G 
						, pBitmap 
						, ( Positions.X1 ) ? ( Positions.X1 ) : ( Positions.X ) ? ( Positions.X ) : ( "" )
						, ( Positions.Y1 ) ? ( Positions.Y1 ) : ( Positions.Y ) ? ( Positions.Y ) : ( "" ) 
						, ( Positions.W1 ) ? ( Positions.W1 ) : ( Positions.W ) ? ( Positions.W ) : ( "" ) 
						, ( Positions.H1 ) ? ( Positions.H1 ) : ( Positions.H ) ? ( Positions.H ) : ( "" ) 
						, ( Positions.X2 ) ? ( Positions.X2 ) : ( Positions.SX ) ? ( Positions.SX ) : ( "" )
						, ( Positions.Y2 ) ? ( Positions.Y2 ) : ( Positions.SY ) ? ( Positions.SY ) : ( "" )
						, ( Positions.W2 ) ? ( Positions.W2 ) : ( Positions.SW ) ? ( Positions.SW ) : ( "" )
						, ( Positions.H2 ) ? ( Positions.H2 ) : ( Positions.SH ) ? ( Positions.SH ) : ( "" ) )
		( update ) ? ( This.UpdateWindow() )
		( disposeBitmap ) ? ( Gdip_DisposeImage( pBitmap ) )
	}
	ClearWindow( update := "" ){ 
		Gdip_GraphicsClear( This.G )
		( update ) ? ( This.UpdateWindow() )
	}
	Add_Trigger(PositionObject,Label:="GuiClose"){
		static
		Gui, % This.Window ": Add", Text, % "x" PositionObject.X " y" PositionObject.Y " w" PositionObject.W " h" PositionObject.H " v" PositionObject.V " g" Label " BackgroundTrans"
	}
	Draw_Text(PosObj,Text,Font:="Arial",FontSize:="12",Color1:="0xFFFFFFFF",Color2:="",PosObj2:="",update:=0){
		local Brush
		(!color2&&color2!="000000")?(Color2:=Color1)
		(StrLen(Color1)=6)?( Color1 := "0xFF" Color1 )
		(StrLen(Color2)=6)?( Color2 := "0xFF" Color2 )
		(PosObj2="")?(PosObj2:=PosObj)
		Brush := Gdip_CreateLineBrushFromRect( 0 , 0 , PosObj2.W , PosObj2.H , Color1 , Color2 , 1 , 1 )
		Gdip_TextToGraphics(This.G, Text, "s" FontSize " c" Brush " Center vCenter Bold x" PosObj.X " y" PosObj.Y, Font , PosObj.W, PosObj.H)
		Gdip_DeleteBrush( Brush )
		( update ) ? ( This.UpdateWindow() )
	}
	Draw_Rectangle(Thickness:="5",PosObj:="",Color1:=0xFFFFFFFF,Color2:="",PosObj2:="",update:=0){
		local Brush, pPen
		(!color2)?(Color2:=Color1)
		(StrLen(Color1)=6)?( Color1 := "0xFF" Color1 )
		(StrLen(Color2)=6)?( Color2 := "0xFF" Color2 )
		(PosObj2="")?(PosObj2:=PosObj)
		Brush := Gdip_CreateLineBrushFromRect( 0 , 0 , PosObj2.W , PosObj2.H , Color1 , Color2 , 1 , 1 )
		pPen := Gdip_CreatePenFromBrush(Brush, Thickness)
		Gdip_DrawRectangle( This.G, pPen, PosObj.X , PosObj.Y , PosObj.W , PosObj.H )
		Gdip_DeleteBrush( Brush )
		Gdip_DeletePen(pPen)
		( update ) ? ( This.UpdateWindow() )
	}
	DeleteWindow( TurnOffGdip := 0 ){
		Gui, % This.Window " : Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		( TurnOffGdip && This.Token ) ? ( Gdip_Shutdown( This.Token ) )
	}
}








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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 06 Feb 2022, 16:11

doubledave22 wrote:
06 Feb 2022, 15:48
shoot @Hellbent I just posted a revised version with your layered windows class. I will study your response but take a look at my second example above if you can!

Can't thank you enough... I am beginning the journey of learning about layered windows since it's the only way I can get things to look how I want.
I'll have a look at your update. Be sure to check out the updated layered window class ( PopUpWindow [ v2 ] ), it doesn't have every feature the old class had, but it has a few improvements and is IMO much simpler to use.

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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 06 Feb 2022, 16:24

doubledave22 wrote:
06 Feb 2022, 16:10
I guess I have to do something like this... just seems ineffecient. Also I notice with updating all controls each time there's some flickering. Check out the gif:
https://gyazo.com/d39783ca8e4f9b389fa3f053009b9886

Code: Select all

; gdi+ ahk tutorial 8 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Tutorial to write text onto a gui

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip_All.ahk
;~ #Include, LayeredWindow.ahk

; Start gdi+
If !pToken := Gdip_Startup()
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}
OnExit, Exit

Btn_Width := 150
Btn_Height := Btn_Width/2
Button_Count := 5

NLW := new LayeredWindow( (A_ScreenWidth-Btn_Width)//2		; x
						, (A_ScreenHeight-Btn_Height)//2 	; y
						, 1920 								; w
						, 1080 								; h
						, 1 								; window 
						, "" 								; title
						, 4 								; smoothing
						, "" 								; options ; "+Owner" Winexist("A") 
						, 1 								; autoShow
						, 0 								; GdipStart
						, 									; WinMover := {x:0,y:0,w:200,h:200}	
						, "" )								; BackgroundColor

OffsetX := round(Btn_Width/15)
OffsetY := round(Btn_Width/15)

Button_Default := Create_Button(Btn_Width, OffsetX, OffsetY)
Button_Pressed := Create_Button(Btn_Width, OffsetX, OffsetY,0)

loop, % Button_Count
{
	Btn_%a_index% := {x: (a_index - 1) * Btn_Width + 10*(a_index - 1), y: 0, w: Btn_Width, h: Btn_Height, v: "Button" a_index}
	NLW.Draw(Button_Default,Btn_%a_index%)
	NLW.Add_Trigger(Btn_%a_index%,"ClickedButton")
}

return

ClickedButton()
{
	global
	
	local Num
	
	RegExMatch(a_guicontrol,"\d+",Num)

	NLW.ClearWindow()
	
	Btn_%Num%.x += OffsetX
	Btn_%Num%.y += OffsetY
	
	loop, % Button_Count
	{
		if (a_index = Num)
			NLW.Draw(Button_Pressed,Btn_%a_index%)
		else
			NLW.Draw(Button_Default,Btn_%a_index%)
	}
	
	while GetKeyState("LButton","P")
		sleep, 10

	NLW.ClearWindow()
	Btn_%Num%.x -= OffsetX
	Btn_%Num%.y -= OffsetY
	
	loop, % Button_Count
		NLW.Draw(Button_Default,Btn_%a_index%)
}

Create_Button(Width, OffsetX, OffsetY, ShowBG := 1)
{
	Height := Width/2
	Rounding := (Width/10)
	Font_Size := (Width/5)
	Font := "Arial"
	
	pBitmap := Gdip_CreateBitmap(Width, Height)
	
	G := Gdip_GraphicsFromImage(pBitmap)
	Gdip_SetSmoothingMode(G, 2)
	
	if (ShowBG)
	{
		pBrush1 := Gdip_BrushCreateSolid(0xFFa15656)
		Gdip_FillRoundedRectangle(G, pBrush1, 0, 0, Width, Height, Rounding)
		Gdip_DeleteBrush(pBrush1)
	}
	
	pBrush2 := Gdip_BrushCreateSolid(0xFFbc8282)
	Gdip_FillRoundedRectangle(G, pBrush2, 0, 0, Width-(OffsetX), Height-(OffsetY), Rounding)
	Gdip_DeleteBrush(pBrush2)
	
	If !Gdip_FontFamilyCreate(Font)
	{
	   MsgBox, 48, Font error!, The font you have specified does not exist on the system
	   ExitApp
	}

	Options = vCenter Centre cFFffffff r4 s%Font_Size% Bold
	Gdip_TextToGraphics(G, "Button", Options, Font, Width, Height-OffsetY/2)
	Gdip_DeleteGraphics(G)
	return pBitmap
}


Exit:
Gdip_DisposeImage( Button_Default )
Gdip_DisposeImage( Button_Pressed )
; gdi+ may now be shutdown on exiting the program
Gdip_Shutdown(pToken)
ExitApp
Return




class LayeredWindow	{
;LayeredWindow class By: Hellbent
	__New( x := 0 , y := 0 , w := 100 , h := 100 , window := 1 , title := " " , smoothing := 4 , options := "" , autoShow := 1 , GdipStart := 0 , WinMover := "" , BackgroundColor := "" ){
		This.X := x , This.Y := y , This.W := w , This.H := h 
		This.Window := window , This.Title := title
		This.Options := options , This.Smoothing := smoothing
		( GdipStart ) ? ( This.Token := Gdip_Startup() )
		This._CreateWindow()
		( autoShow ) ? ( This.ShowWindow() )
		This._SetUpdateLayeredWindow()
		( WinMover ) ? ( This._AddMoveTrigger( WinMover ) )
		( BackgroundColor ) ? ( This.PaintBackground( BackgroundColor , 1 ) )
	}
	_CreateWindow(){
		Gui , % This.Window ": New" , % " +E0x80000 +LastFound -Caption " This.Options 
		This.Hwnd := WinExist()
		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 )
	}
	_SetUpdateLayeredWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc , This.X , This.Y , This.W , This.H )
	}
	UpdateWindow(){
		UpdateLayeredWindow( This.hwnd , This.hdc )
	}
	ShowWindow( update := 1 , Position := "" ){ 
		if( !Position )
			Gui , % This.Window ": Show" , % "w" This.W " h" This.H  , % ( This.Title ) ? ( This.Title ) : ( "" )
		else
			Gui , % This.Window ": Show" , % "x" Position.X " y" Position.Y "w" Position.W " h" Position.H  , % ( This.Title ) ? ( This.Title )  : ( "" )
		( update ) ? ( This.UpdateWindow() )
	}
	_AddMoveTrigger( positons ){ 
		local hwnd , bd
		Gui , % This.Window " : Add" , Text , % "x" positons.x " y" positons.y " w" positons.w " h" positons.h " hwndhwnd"
		This.MoveHwnd := hwnd
		bd := This._WindowMover.Bind( This )
		GuiControl , % This.Window ": +G" , % This.MoveHwnd , % bd
	}
	_WindowMover(){ 
		PostMessage, 0xA1 , 2
	}
	PaintBackground( BackgroundColor := "0xFF000000" , update := 0){ 
		local Brush
		This.BackgroundColor := BackgroundColor
		Brush := Gdip_BrushCreateSolid( BackgroundColor )
		Gdip_FillRectangle( This.G , Brush , 0 , 0 , This.W , This.H )
		Gdip_DeleteBrush( Brush )
		( update ) ? ( This.UpdateWindow() )
	}
	Draw( pBitmap , Positions := "" , update := 1 , disposeBitmap := 0  , PaintBackground := 0){ 
	(PaintBackground) ? ( This.PaintBackground( This.BackgroundColor ) )	
		Gdip_DrawImage( This.G 
						, pBitmap 
						, ( Positions.X1 ) ? ( Positions.X1 ) : ( Positions.X ) ? ( Positions.X ) : ( "" )
						, ( Positions.Y1 ) ? ( Positions.Y1 ) : ( Positions.Y ) ? ( Positions.Y ) : ( "" ) 
						, ( Positions.W1 ) ? ( Positions.W1 ) : ( Positions.W ) ? ( Positions.W ) : ( "" ) 
						, ( Positions.H1 ) ? ( Positions.H1 ) : ( Positions.H ) ? ( Positions.H ) : ( "" ) 
						, ( Positions.X2 ) ? ( Positions.X2 ) : ( Positions.SX ) ? ( Positions.SX ) : ( "" )
						, ( Positions.Y2 ) ? ( Positions.Y2 ) : ( Positions.SY ) ? ( Positions.SY ) : ( "" )
						, ( Positions.W2 ) ? ( Positions.W2 ) : ( Positions.SW ) ? ( Positions.SW ) : ( "" )
						, ( Positions.H2 ) ? ( Positions.H2 ) : ( Positions.SH ) ? ( Positions.SH ) : ( "" ) )
		( update ) ? ( This.UpdateWindow() )
		( disposeBitmap ) ? ( Gdip_DisposeImage( pBitmap ) )
	}
	ClearWindow( update := "" ){ 
		Gdip_GraphicsClear( This.G )
		( update ) ? ( This.UpdateWindow() )
	}
	Add_Trigger(PositionObject,Label:="GuiClose"){
		static
		Gui, % This.Window ": Add", Text, % "x" PositionObject.X " y" PositionObject.Y " w" PositionObject.W " h" PositionObject.H " v" PositionObject.V " g" Label " BackgroundTrans"
	}
	Draw_Text(PosObj,Text,Font:="Arial",FontSize:="12",Color1:="0xFFFFFFFF",Color2:="",PosObj2:="",update:=0){
		local Brush
		(!color2&&color2!="000000")?(Color2:=Color1)
		(StrLen(Color1)=6)?( Color1 := "0xFF" Color1 )
		(StrLen(Color2)=6)?( Color2 := "0xFF" Color2 )
		(PosObj2="")?(PosObj2:=PosObj)
		Brush := Gdip_CreateLineBrushFromRect( 0 , 0 , PosObj2.W , PosObj2.H , Color1 , Color2 , 1 , 1 )
		Gdip_TextToGraphics(This.G, Text, "s" FontSize " c" Brush " Center vCenter Bold x" PosObj.X " y" PosObj.Y, Font , PosObj.W, PosObj.H)
		Gdip_DeleteBrush( Brush )
		( update ) ? ( This.UpdateWindow() )
	}
	Draw_Rectangle(Thickness:="5",PosObj:="",Color1:=0xFFFFFFFF,Color2:="",PosObj2:="",update:=0){
		local Brush, pPen
		(!color2)?(Color2:=Color1)
		(StrLen(Color1)=6)?( Color1 := "0xFF" Color1 )
		(StrLen(Color2)=6)?( Color2 := "0xFF" Color2 )
		(PosObj2="")?(PosObj2:=PosObj)
		Brush := Gdip_CreateLineBrushFromRect( 0 , 0 , PosObj2.W , PosObj2.H , Color1 , Color2 , 1 , 1 )
		pPen := Gdip_CreatePenFromBrush(Brush, Thickness)
		Gdip_DrawRectangle( This.G, pPen, PosObj.X , PosObj.Y , PosObj.W , PosObj.H )
		Gdip_DeleteBrush( Brush )
		Gdip_DeletePen(pPen)
		( update ) ? ( This.UpdateWindow() )
	}
	DeleteWindow( TurnOffGdip := 0 ){
		Gui, % This.Window " : Destroy"
		SelectObject( This.hdc , This.obm )
		DeleteObject( This.hbm )
		DeleteDC( This.hdc )
		Gdip_DeleteGraphics( This.G )
		( TurnOffGdip && This.Token ) ? ( Gdip_Shutdown( This.Token ) )
	}
}







It might be easier if I create a solution to your problem from scratch that you can then work from rather than me trying to edit your code.

Correct me if I am reading this wrong.

You are trying to create a strip of buttons that have feedback built into them.
They are shown on a layered window so that transparency and antialiasing is used.
There is nothing else being shown / drawn besides a strip of n buttons.

Is that right?

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Need help with GDI button and Layered Window

Post by doubledave22 » 06 Feb 2022, 16:30

Yeah, pretty much! I just would like a way to individually update/move/hide each button i've created without having to clear the graphics and update all the buttons each time if possible. I need an on click event for each button and I'd like to replace the default button with the pressed button (like in the gyazo gif I sent).

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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 06 Feb 2022, 17:29

doubledave22 wrote:
06 Feb 2022, 16:30
Yeah, pretty much! I just would like a way to individually update/move/hide each button i've created without having to clear the graphics and update all the buttons each time if possible. I need an on click event for each button and I'd like to replace the default button with the pressed button (like in the gyazo gif I sent).
You are ok with windows 8+ compatibility right?
It can be done for lower versions, but it takes a bit more effort.

User avatar
emrekarahan0001
Posts: 25
Joined: 18 Jan 2021, 14:19

Re: Need help with GDI button and Layered Window

Post by emrekarahan0001 » 06 Feb 2022, 18:07

Maybe it will be of use to you.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

F0 = https://imgur.com/mwKVtZT.png
Button = %A_Desktop%\Button-Main.png
ifnotexist,%Button%
   urldownloadtofile,%f0%,%Button%

Button0 = https://imgur.com/cKNddlh.png
Button1 = %A_Desktop%\Button1.png
ifnotexist,%Button1%
   urldownloadtofile,%Button0%,%Button1%

Gui, -Caption +Owner +AlwaysOnTop
Gui, Add , Picture, x0 y0 w500 h35, %Button%
Gui, Add , Picture, x0 y0 w100 h35 vSMenu1 gSMenu1, %Button1%
Gui, Add , Picture, x100 y0 w100 h35 vSMenu2 gSMenu2, %Button1%
Gui, Add , Picture, x200 y0 w100 h35 vSMenu3 gSMenu3, %Button1%
Gui, Add , Picture, x300 y0 w100 h35 vSMenu4 gSMenu4, %Button1%
Gui, Add , Picture, x400 y0 w100 h35 vSMenu5 gSMenu5, %Button1%
Gui, Show, xCenter yCenter w500 h35, SMenu
Return

SMenu1:
GuiControl, Hide, SMenu1
Sleep, 250
GuiControl, Show, SMenu1
Return

SMenu2:
GuiControl, Hide, SMenu2
Sleep, 250
GuiControl, Show, SMenu2
Return

SMenu3:
GuiControl, Hide, SMenu3
Sleep, 250
GuiControl, Show, SMenu3
Return

SMenu4:
GuiControl, Hide, SMenu4
Sleep, 250
GuiControl, Show, SMenu4
Return

SMenu5:
GuiControl, Hide, SMenu5
Sleep, 250
GuiControl, Show, SMenu5
Return

ESC:
ExitApp
Return

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Need help with GDI button and Layered Window

Post by doubledave22 » 06 Feb 2022, 18:49

Hellbent wrote:
06 Feb 2022, 17:29
You are ok with windows 8+ compatibility right?
It can be done for lower versions, but it takes a bit more effort.
I do have some users on Windows 7 but nothing lower. If it's not a huge hassle it would really help. Happy to kick some money to the hellbent fund if it exists somewhere.

and thanks @emrekarahan0001 ill check it out!

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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 06 Feb 2022, 19:56

Here is a windows 8+ solution.
I went right for a class, if you have any trouble understanding anything just let me know.

You can move the buttons by holding "Shift" when you click them.


.
Animation.gif
Animation.gif (127.58 KiB) Viewed 2214 times

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib>  ;<---Gdip.ahk lib
#Include <PopUpWindow_V2> 	;This was in one of my last posts
;****************************************************************************************************************************************************************************
#SingleInstance, Force
Gdip_Startup()

Buttons := []
Buttons[ 1 ] := { X: 10 , Y: 10 , W: 150 , H: 75 , Label: "Label1"  }
Buttons[ 2 ] := { X: 100 , Y: 100 , W: 150 , H: 75 , Label: "Label1"  }
Buttons[ 3 ] := { ButtonText: "Not Button" , X: 200 , Y: 200 , W: 150 , H: 75 , Label: Func( "Label2" ).Bind( Buttons )  }

Loop, % Buttons.Length()
	Buttons[ A_Index ] := New LWButtons( Buttons[ A_Index ] )

return
*ESC::ExitApp

F1::PopUpWindow.Helper()

Label1:
	tooltip, the button was pressed `nLabel1
	SoundBeep
	return 

Label2( obj ){
	tooltip, % obj[ 3 ].FontColor "`n" obj[ 3 ].X "`n" obj[ 3 ].Hwnd "`nLabel2"
	SoundBeep
	Random, outX, 0 , % A_ScreenWidth - obj[ 3 ].W
	Random, outY, 0 , % A_ScreenHeight - obj[ 3 ].H - 200
	obj[ 3 ].Move( outX , outY )
}

;********************************************************************************************************************************************************************************************************
;********************************************************************************************************************************************************************************************************
;********************************************************************************************************************************************************************************************************
;********************************************************************************************************************************************************************************************************
class LWButtons	{
	;class: Layered Window Buttons
	__New( obj := "" ){
		This._SetDefaults()
		This._UpdateDefaults( obj )
		This._CreateControl()
		This._DrawButton()
	}
	_SetDefaults(){
		
		This.Hwnd := ""
		This.Button := ""
		
		This.X := 10
		This.Y := 10 
		This.W := 10
		This.H := 10
		
		This.RestColor := "0xFF3399FF"
		This.PressedColor := "0xFF336699"
		This.MovingColor := "0xFFff0000"
		
		This.ButtonText := "Button"
		This.Font := "Comic Sans MS"
		This.FontSize := 16
		This.FontColor := "0xFF000000"
		This.FontOptions := " Center vCenter Bold "
		
		This.Roundness := 10
		This.Label := ""
		This.WindowOptions := " -DPIScale +AlwaysOnTop +ToolWindow "
		
		This.Pressed := 0
		
		This.ClickBind := This._ButtonClick.Bind( This )
		;~ OnMessage( 0x201 , This._ButtonClick.Bind( This ) ) ; I could have gone this route, but I like the path I took more.
	}
	_UpdateDefaults( obj := "" ){
		local k , v 
		for k, v in obj
			This[ k ] := obj[ k ]
	}
	_CreateControl(){
		local hwnd , bd := This.ClickBind
		This.Button := New PopUpWindow( { AutoShow: 1 , X: This.X , Y: This.Y , W: This.W , H: This.H , Options: This.WindowOptions } )
		This.Hwnd := This.Button.Hwnd
		Gui, % This.Button.Hwnd ":Add" , Text , % "x" 0 " y" 0 " w" This.W " h" This.H " hwndhwnd"
		GuiControl, % This.Button.Hwnd ":+G" , % hwnd , % bd
	}
	_ButtonClick(){
		if( GetKeyState( "Shift" ) ){
			This.Pressed := 2
			This._DrawButton()
			PostMessage, 0xA1, 2
			While( GetKeyState( "LButton" ) )
				sleep, 60
			WinGetPos, x, y ,,, % "ahk_id " This.Button.Hwnd
			This.Button.UpdateSettings( { X: x , Y: y } )
			This.Pressed := 0
			This._DrawButton()
		}else{
			This.Pressed := 1
			This._DrawButton()
			While( GetKeyState( "LButton" ) )
				sleep, 60
			This.Pressed := 0
			This._DrawButton()
			MouseGetPos,,, win
			if( win = This.Button.Hwnd ){
				if( isObject( This.Label ) )
					Try
						This.Label.Call()
				else 
					Try
						GoSub, % This.Label
			}
		}
		
	}
	_DrawButton(){
		This.Button.ClearWindow()
		This._ButtonGraphics()
		This.Button.UpdateWindow()
	}
	_ButtonGraphics(){
		Brush := Gdip_BrushCreateSolid( ( This.Pressed = 0 ) ? ( This.RestColor ) : ( This.Pressed = 1 ) ? ( This.PressedColor ) : ( This.MovingColor )  ) , Gdip_FillRoundedRectangle( This.Button.G, Brush , 1 , 1 , This.W - 2 , This.H - 2 , This.Roundness ) , Gdip_DeleteBrush( Brush )
		Brush := Gdip_BrushCreateSolid( This.FontColor ) , Gdip_TextToGraphics( This.Button.G , This.ButtonText , "s" This.FontSize " c" Brush " " This.FontOptions " x0 y0" , This.Font, This.W , This.H ) , Gdip_DeleteBrush( Brush )
	}
	Move( x := 10 , y := 10 ){
		This.Button.UpdateSettings( { X: x , Y: y } )
		Gui, % This.Button.Hwnd ":Show", % "x" x " y" y " NA"
	}
	Hide(){
		Gui, % This.Button.Hwnd ":Hide" 
		;~ This.Button.ClearWindow( 1 ) ; <<---------------------  This is how I would normally "Hide" a layered window.
	}
	Show(){
		Gui, % This.Button.Hwnd ":Show", NA 
		;~ This._DrawButton() ; <<------ The way I would normally do it.
	}
	Delete(){
		This.Button.DeleteWindow()
	}
}
doubledave22 wrote:
06 Feb 2022, 18:49
Hellbent wrote:
06 Feb 2022, 17:29
You are ok with windows 8+ compatibility right?
It can be done for lower versions, but it takes a bit more effort.
I do have some users on Windows 7 but nothing lower. If it's not a huge hassle it would really help. Happy to kick some money to the hellbent fund if it exists somewhere.

and thanks @emrekarahan0001 ill check it out!
I'll post a update for win 7 in a bit. Don't worry about payment.


***Edit*** Forgot to make them "toolWindows" . Added it into "This.WindowOptions"

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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 06 Feb 2022, 21:09

doubledave22 wrote:
06 Feb 2022, 16:10
I guess I have to do something like this... just seems ineffecient. Also I notice with updating all controls each time there's some flickering. Check out the gif:
https://gyazo.com/d39783ca8e4f9b389fa3f053009b9886
Layered windows don't flicker.

Without looking at your code I can tell that you are more than likely updating your window each time you redraw each button.
What you need to do is draw everything to the graphics and then update the window.

i.e don't do something like this.

Code: Select all


loop, % someAmount	{
	
	DrawButton()
	Update()
	
}


instead do something like this.

Code: Select all

loop, % someAmount	{
	
	DrawButton()
	
	
}
Update()
You can see from this example that even if you are drawing A LOT, there isn't really much issue.

.
Animation.gif
Animation.gif (63.24 KiB) Viewed 2191 times
.

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib>  ;<---Gdip.ahk lib
#Include <PopUpWindow_V2> 	;This was in one of my last posts
;****************************************************************************************************************************************************************************
#SingleInstance, Force
Gdip_Startup()

ScaleFactor := 1
Active := 0
Gui1 := New PopUpWindow( { AutoShow: 1 , X: "Center" , Y: "Center" , W: 600 * ScaleFactor , H: 160 * ScaleFactor , Options: " -DPIScale +AlwaysOnTop " } )
Gui1.DrawBitmap( HB_BITMAP_MAKER( ScaleFactor , Active ) , { X: 0 , Y: 0 , W: Gui1.W , H: Gui1.H } , dispose := 1 , 1 )

SetTimer, WatchCursor, 30
return
*ESC::ExitApp

F1::PopUpWindow.Helper()

WatchCursor:
	MouseGetPos,,, win
	if( !Active && win = Gui1.Hwnd ){
		Active := 1
		Gui1.DrawBitmap( HB_BITMAP_MAKER( ScaleFactor , Active ) , { X: 0 , Y: 0 , W: Gui1.W , H: Gui1.H } , dispose := 1 , 1 )
	}else if( Active && win != Gui1.Hwnd ){
		Active := 0
		Gui1.DrawBitmap( HB_BITMAP_MAKER( ScaleFactor , Active ) , { X: 0 , Y: 0 , W: Gui1.W , H: Gui1.H } , dispose := 1 , 1 )
	}
	return

HB_BITMAP_MAKER( ScaleFactor := 1 , Active := 0 ){
	;Bitmap Created Using: HB Bitmap Maker
	pBitmap := Gdip_CreateBitmap( 600 * ScaleFactor , 160 * ScaleFactor ) , G := Gdip_GraphicsFromImage( pBitmap ) , Gdip_SetSmoothingMode( G , 2 )
	
	;if active stuff for demo
	;~ Brush := Gdip_BrushCreateSolid( "0xFF42464A" ) , Gdip_FillRoundedRectangle( G , Brush , 2 * ScaleFactor , 2 * ScaleFactor , 596 * ScaleFactor , 156 * ScaleFactor , 10 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( ( !Active ) ? ( "0xFF42464A" ) : ( "0xFF00FF00" ) ) , Gdip_FillRoundedRectangle( G , Brush , 2 * ScaleFactor , 2 * ScaleFactor , 596 * ScaleFactor , 156 * ScaleFactor , 10 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	
	
	Brush := Gdip_CreateLineBrushFromRect( 5 * ScaleFactor , 3 * ScaleFactor , 494 * ScaleFactor , 152 * ScaleFactor , "0xFF92969a" , "0xFF12161a" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawRoundedRectangle( G , Pen , 2 * ScaleFactor , 2 * ScaleFactor , 596 * ScaleFactor , 156 * ScaleFactor , 10 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xFF36373A" ) , Gdip_FillRectangle( G , Brush , 10 * ScaleFactor , 10 * ScaleFactor , 100 * ScaleFactor , 100 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	picBitmap := Gdip_CreateBitmapFromFile( "C:\Users\CivRe\OneDrive\Desktop\AHK Tools\BitMap Maker\HB Bitmap Maker Folder\Saved PNGs\0002.PNG" ) , Gdip_DrawImage( G , picBitmap , 15 * ScaleFactor , 40 * ScaleFactor , 29 * ScaleFactor , 21 * ScaleFactor , 0 , 0 , 29 , 21 ) , Gdip_DisposeImage( picBitmap )
	Brush := Gdip_BrushCreateSolid( "0xFF3399FF" ) , Gdip_TextToGraphics( G , "Activate" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 46 * ScaleFactor " y" 25 * ScaleFactor  , "Segoe ui" , 60 * ScaleFactor , 50 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	picBitmap := Gdip_CreateBitmapFromFile( "C:\Users\CivRe\OneDrive\Desktop\AHK Tools\BitMap Maker\HB Bitmap Maker Folder\Saved PNGs\0004.PNG" ) , Gdip_DrawImage( G , picBitmap , 17 * ScaleFactor , 63 * ScaleFactor , 19 * ScaleFactor , 19 * ScaleFactor , 0 , 0 , 19 , 19 ) , Gdip_DisposeImage( picBitmap )
	picBitmap := Gdip_CreateBitmapFromFile( "C:\Users\CivRe\OneDrive\Desktop\AHK Tools\BitMap Maker\HB Bitmap Maker Folder\Saved PNGs\0005.PNG" ) , Gdip_DrawImage( G , picBitmap , 17 * ScaleFactor , 85 * ScaleFactor , 19 * ScaleFactor , 19 * ScaleFactor , 0 , 0 , 19 , 19 ) , Gdip_DisposeImage( picBitmap )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_TextToGraphics( G , "True" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 45 * ScaleFactor " y" 48 * ScaleFactor  , "Segoe ui" , 60 * ScaleFactor , 50 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xff3399ff" ) , Gdip_TextToGraphics( G , "False" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 45 * ScaleFactor " y" 70 * ScaleFactor  , "Segoe ui" , 60 * ScaleFactor , 50 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Pen := Gdip_CreatePen( "0xFF000000" , 1 ) , Gdip_DrawRectangle( G , Pen , 10 * ScaleFactor , 10 * ScaleFactor , 100 * ScaleFactor , 100 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_FillRectangle( G , Brush , 109 * ScaleFactor , 10 * ScaleFactor , 1 * ScaleFactor , 99 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_FillRectangle( G , Brush , 10 * ScaleFactor , 109 * ScaleFactor , 100 * ScaleFactor , 1 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;position panel
	Brush := Gdip_BrushCreateSolid( "0xFF36373A" ) , Gdip_FillRectangle( G , Brush , 120 * ScaleFactor , 10 * ScaleFactor , 130 * ScaleFactor , 100 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Pen := Gdip_CreatePen( "0xFF000000" , 1 ) , Gdip_DrawRectangle( G , Pen , 120 * ScaleFactor , 10 * ScaleFactor , 130 * ScaleFactor , 100 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_FillRectangle( G , Brush , 249 * ScaleFactor , 10 * ScaleFactor , 1 * ScaleFactor , 99 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_FillRectangle( G , Brush , 120 * ScaleFactor , 109 * ScaleFactor , 130 * ScaleFactor , 1 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 132 * ScaleFactor , 72 * ScaleFactor , 110 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 130 * ScaleFactor , 70 * ScaleFactor , 110 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 131 * ScaleFactor , 70 * ScaleFactor , 108 * ScaleFactor , 31 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 131 * ScaleFactor , 71 * ScaleFactor , 108 * ScaleFactor , 28 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xff3399ff" ) , Gdip_TextToGraphics( G , "Set Position" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 130 * ScaleFactor " y" 71 * ScaleFactor  , "Segoe ui" , 110 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF22262A" ) , Gdip_FillRectangle( G , Brush , 130 * ScaleFactor , 32 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 132 * ScaleFactor , 29 * ScaleFactor , 49 * ScaleFactor , 31 * ScaleFactor , "0xFF3399FF" , "0xFF000000" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawRectangle( G , Pen , 130 * ScaleFactor , 32 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_TextToGraphics( G , "1234" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 130 * ScaleFactor " y" 33 * ScaleFactor  , "Segoe ui" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF22262A" ) , Gdip_FillRectangle( G , Brush , 190 * ScaleFactor , 32 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 132 * ScaleFactor , 29 * ScaleFactor , 49 * ScaleFactor , 31 * ScaleFactor , "0xFF3399FF" , "0xFF000000" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawRectangle( G , Pen , 190 * ScaleFactor , 32 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_TextToGraphics( G , "330" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 190 * ScaleFactor " y" 33 * ScaleFactor  , "Segoe ui" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF000000" ) , Gdip_TextToGraphics( G , "X" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 131 * ScaleFactor " y" 7 * ScaleFactor  , "Segoe ui" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF3399FF" ) , Gdip_TextToGraphics( G , "X" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 130 * ScaleFactor " y" 6 * ScaleFactor  , "Segoe ui" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF000000" ) , Gdip_TextToGraphics( G , "Y" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 191 * ScaleFactor " y" 7 * ScaleFactor  , "Segoe ui" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF3399FF" ) , Gdip_TextToGraphics( G , "Y" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 190 * ScaleFactor " y" 6 * ScaleFactor  , "Segoe ui" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;Color panel
	Brush := Gdip_BrushCreateSolid( "0xFF36373A" ) , Gdip_FillRectangle( G , Brush , 260 * ScaleFactor , 10 * ScaleFactor , 110 * ScaleFactor , 100 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Pen := Gdip_CreatePen( "0xFF000000" , 1 ) , Gdip_DrawRectangle( G , Pen , 260 * ScaleFactor , 10 * ScaleFactor , 110 * ScaleFactor , 100 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_FillRectangle( G , Brush , 369 * ScaleFactor , 10 * ScaleFactor , 1 * ScaleFactor , 99 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_FillRectangle( G , Brush , 260 * ScaleFactor , 109 * ScaleFactor , 110 * ScaleFactor , 1 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 272 * ScaleFactor , 72 * ScaleFactor , 90 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 270 * ScaleFactor , 70 * ScaleFactor , 90 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 131 * ScaleFactor , 70 * ScaleFactor , 108 * ScaleFactor , 31 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 271 * ScaleFactor , 71 * ScaleFactor , 88 * ScaleFactor , 28 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xff3399ff" ) , Gdip_TextToGraphics( G , "Set Color" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 270 * ScaleFactor " y" 71 * ScaleFactor  , "Segoe ui" , 90 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF000000" ) , Gdip_TextToGraphics( G , "0xFF0000" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 261 * ScaleFactor " y" 7 * ScaleFactor  , "Segoe ui" , 110 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF3399FF" ) , Gdip_TextToGraphics( G , "0xFF0000" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 260 * ScaleFactor " y" 6 * ScaleFactor  , "Segoe ui" , 110 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF22262A" ) , Gdip_FillRectangle( G , Brush , 310 * ScaleFactor , 32 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 132 * ScaleFactor , 29 * ScaleFactor , 49 * ScaleFactor , 31 * ScaleFactor , "0xFF3399FF" , "0xFF000000" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawRectangle( G , Pen , 310 * ScaleFactor , 32 * ScaleFactor , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xFF22262A" ) , Gdip_FillRectangle( G , Brush , 270 * ScaleFactor , 30 * ScaleFactor , 30 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFFff0000" ) , Gdip_FillRoundedRectangle( G , Brush , 271 * ScaleFactor , 31 * ScaleFactor , 28 * ScaleFactor , 28 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 273 * ScaleFactor , 33 * ScaleFactor , 23 * ScaleFactor , 4 * ScaleFactor , "0x99F0F0F0" , "0x00000000" , 2 , 1 ) , Gdip_FillRectangle( G , Brush , 273 * ScaleFactor , 33 * ScaleFactor , 23 * ScaleFactor , 2 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 273 * ScaleFactor , 53 * ScaleFactor , 27 * ScaleFactor , 6 * ScaleFactor , "0x00F0F0F0" , "0x99000000" , 2 , 1 ) , Gdip_FillRectangle( G , Brush , 273 * ScaleFactor , 55 * ScaleFactor , 23 * ScaleFactor , 2 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_TextToGraphics( G , "0" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 310 * ScaleFactor " y" 33 * ScaleFactor  , "Segoe ui" , 50 * ScaleFactor , 30 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;Button Panel
	Brush := Gdip_BrushCreateSolid( "0xFF36373A" ) , Gdip_FillRectangle( G , Brush , 380 * ScaleFactor , 10 * ScaleFactor , 100 * ScaleFactor , 100 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;M Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 392 * ScaleFactor , 22 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 390 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 394 * ScaleFactor , 21 * ScaleFactor , 16 * ScaleFactor , 19 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 391 * ScaleFactor , 21 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xff3399ff" ) , Gdip_TextToGraphics( G , "M" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 391 * ScaleFactor " y" 22 * ScaleFactor  , "Segoe ui" , 20 * ScaleFactor , 19 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;M Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 422 * ScaleFactor , 22 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 420 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 394 * ScaleFactor , 21 * ScaleFactor , 16 * ScaleFactor , 19 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 421 * ScaleFactor , 21 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xff3399ff" ) , Gdip_TextToGraphics( G , "C" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 421 * ScaleFactor " y" 22 * ScaleFactor  , "Segoe ui" , 20 * ScaleFactor , 19 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;M Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 452 * ScaleFactor , 22 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 450 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 394 * ScaleFactor , 21 * ScaleFactor , 16 * ScaleFactor , 19 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 451 * ScaleFactor , 21 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xff3399ff" ) , Gdip_TextToGraphics( G , "T" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 451 * ScaleFactor " y" 22 * ScaleFactor  , "Segoe ui" , 20 * ScaleFactor , 19 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;M Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 392 * ScaleFactor , 52 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 390 * ScaleFactor , 50 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 392 * ScaleFactor , 51 * ScaleFactor , 17 * ScaleFactor , 17 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 391 * ScaleFactor , 51 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xffF0F0F0" ) , Gdip_TextToGraphics( G , "1" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 391 * ScaleFactor " y" 52 * ScaleFactor  , "Segoe ui" , 20 * ScaleFactor , 19 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;M Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 392 * ScaleFactor , 82 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 390 * ScaleFactor , 80 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 393 * ScaleFactor , 80 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 391 * ScaleFactor , 81 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xffF0F0F0" ) , Gdip_TextToGraphics( G , "4" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 391 * ScaleFactor " y" 82 * ScaleFactor  , "Segoe ui" , 20 * ScaleFactor , 19 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;M Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 422 * ScaleFactor , 52 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 420 * ScaleFactor , 50 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 392 * ScaleFactor , 51 * ScaleFactor , 17 * ScaleFactor , 17 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 421 * ScaleFactor , 51 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xffF0F0F0" ) , Gdip_TextToGraphics( G , "2" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 421 * ScaleFactor " y" 52 * ScaleFactor  , "Segoe ui" , 20 * ScaleFactor , 19 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;M Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 422 * ScaleFactor , 82 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 420 * ScaleFactor , 80 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 393 * ScaleFactor , 80 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 421 * ScaleFactor , 81 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xffF0F0F0" ) , Gdip_TextToGraphics( G , "5" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 421 * ScaleFactor " y" 82 * ScaleFactor  , "Segoe ui" , 20 * ScaleFactor , 19 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;M Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 452 * ScaleFactor , 82 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 450 * ScaleFactor , 80 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 393 * ScaleFactor , 80 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 451 * ScaleFactor , 81 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xffF0F0F0" ) , Gdip_TextToGraphics( G , "6" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 451 * ScaleFactor " y" 82 * ScaleFactor  , "Segoe ui" , 20 * ScaleFactor , 19 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;M Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 452 * ScaleFactor , 52 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 450 * ScaleFactor , 50 * ScaleFactor , 20 * ScaleFactor , 20 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 392 * ScaleFactor , 51 * ScaleFactor , 17 * ScaleFactor , 17 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 451 * ScaleFactor , 51 * ScaleFactor , 18 * ScaleFactor , 18 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xffF0F0F0" ) , Gdip_TextToGraphics( G , "3" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 451 * ScaleFactor " y" 52 * ScaleFactor  , "Segoe ui" , 20 * ScaleFactor , 19 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Pen := Gdip_CreatePen( "0xFF000000" , 1 ) , Gdip_DrawRectangle( G , Pen , 380 * ScaleFactor , 10 * ScaleFactor , 100 * ScaleFactor , 100 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_FillRectangle( G , Brush , 479 * ScaleFactor , 10 * ScaleFactor , 1 * ScaleFactor , 99 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xaaF0F0F0" ) , Gdip_FillRectangle( G , Brush , 380 * ScaleFactor , 109 * ScaleFactor , 100 * ScaleFactor , 1 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;Copy Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 492 * ScaleFactor , 12 * ScaleFactor , 100 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 490 * ScaleFactor , 10 * ScaleFactor , 100 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 493 * ScaleFactor , 9 * ScaleFactor , 94 * ScaleFactor , 31 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 491 * ScaleFactor , 11 * ScaleFactor , 98 * ScaleFactor , 28 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xff3399FF" ) , Gdip_TextToGraphics( G , "Copy" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 491 * ScaleFactor " y" 12 * ScaleFactor  , "Segoe ui" , 100 * ScaleFactor , 29 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;Copy Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 492 * ScaleFactor , 47 * ScaleFactor , 100 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 490 * ScaleFactor , 45 * ScaleFactor , 100 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 489 * ScaleFactor , 45 * ScaleFactor , 102 * ScaleFactor , 29 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 491 * ScaleFactor , 46 * ScaleFactor , 98 * ScaleFactor , 28 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xff3399FF" ) , Gdip_TextToGraphics( G , "Remove" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 491 * ScaleFactor " y" 47 * ScaleFactor  , "Segoe ui" , 100 * ScaleFactor , 29 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;Copy Button
	Brush := Gdip_BrushCreateSolid( "0x33000000" ) , Gdip_FillRoundedRectangle( G , Brush , 492 * ScaleFactor , 82 * ScaleFactor , 100 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF1D1D1D" ) , Gdip_FillRoundedRectangle( G , Brush , 490 * ScaleFactor , 80 * ScaleFactor , 100 * ScaleFactor , 30 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 493 * ScaleFactor , 82 * ScaleFactor , 99 * ScaleFactor , 27 * ScaleFactor , "0xFF72767a" , "0xFF32363a" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 491 * ScaleFactor , 81 * ScaleFactor , 98 * ScaleFactor , 28 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xff3399FF" ) , Gdip_TextToGraphics( G , "COM Line Info" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 491 * ScaleFactor " y" 82 * ScaleFactor  , "Segoe ui" , 100 * ScaleFactor , 29 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	;edit
	Brush := Gdip_BrushCreateSolid( "0xFF36373A" ) , Gdip_FillRoundedRectangle( G , Brush , 10 * ScaleFactor , 116 * ScaleFactor , 580 * ScaleFactor , 36 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 10 * ScaleFactor , 116 * ScaleFactor , 580 * ScaleFactor , 33 * ScaleFactor , "0x99F0F0F0" , "0xFF000000" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawRoundedRectangle( G , Pen , 10 * ScaleFactor , 116 * ScaleFactor , 580 * ScaleFactor , 35 * ScaleFactor , 5 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xFF22262A" ) , Gdip_FillRectangle( G , Brush , 15 * ScaleFactor , 121 * ScaleFactor , 570 * ScaleFactor , 26 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 13 * ScaleFactor , 120 * ScaleFactor , 573 * ScaleFactor , 26 * ScaleFactor , "0xff3399FF" , "0xFF000000" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawRoundedRectangle( G , Pen , 15 * ScaleFactor , 121 * ScaleFactor , 570 * ScaleFactor , 25 * ScaleFactor , 0 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xFF3399FF" ) , Gdip_TextToGraphics( G , "Sample" , "s" 12 * ScaleFactor " Center vCenter Bold c" Brush " x" 15 * ScaleFactor " y" 121 * ScaleFactor  , "Segoe ui" , 570 * ScaleFactor , 25 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0x9922262A" ) , Gdip_FillEllipse( G , Brush , 50 * ScaleFactor , 14 * ScaleFactor , 22 * ScaleFactor , 22 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_CreateLineBrushFromRect( 47 * ScaleFactor , 17 * ScaleFactor , 29 * ScaleFactor , 20 * ScaleFactor , "0xFF3399FF" , "0xFF000000" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawEllipse( G , Pen , 50 * ScaleFactor , 14 * ScaleFactor , 21 * ScaleFactor , 21 * ScaleFactor ) , Gdip_DeletePen( Pen )
	Brush := Gdip_BrushCreateSolid( "0xFF000000" ) , Gdip_TextToGraphics( G , "1" , "s" 14 * ScaleFactor " Center vCenter Bold c" Brush " x" 22 * ScaleFactor " y" 16 * ScaleFactor  , "Segoe ui" , 81 * ScaleFactor , 21 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Brush := Gdip_BrushCreateSolid( "0xFF3399FF" ) , Gdip_TextToGraphics( G , "1" , "s" 14 * ScaleFactor " Center vCenter Bold c" Brush " x" 21 * ScaleFactor " y" 15 * ScaleFactor  , "Segoe ui" , 81 * ScaleFactor , 21 * ScaleFactor ) , Gdip_DeleteBrush( Brush )
	Gdip_DeleteGraphics( G )
	return pBitmap
}
That example also shows how you can go about dealing with DPI Scaling.

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Need help with GDI button and Layered Window

Post by doubledave22 » 06 Feb 2022, 22:05

@Hellbent :bravo: :clap:

Yep.. thats what I was doing. I was using your previous library and Call() method updates window by default. Reduced it to just updating at the end and works without flicker. It's actually so satisfying haha.

So I watched your PopupWindow youtube with Joe Glines and learned a few things especially about the differences between W7 and W10. Such a bummer you can't hide text controls for layered windows in Windows 7.

Ultimately I am trying to create an overlay class and right now I am using a combination of layered windows and standard controls all as separate GUIs. I set these to be owned by the window and use wineventhook to make sure everything moves together.

I will be looking into this tomorrow but if I create one layered window and then draw all the various images and pseudo buttons, lines, etc do you know if all these drawings will just move with the layered window? I wonder why I am managing a bunch of small GUIs when I can just paint to one and have that track it's owner.

Anyway, thanks again for the examples I will play around tomorrow and let you know how it goes.

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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 06 Feb 2022, 22:11

@doubledave22

In case you missed it. viewtopic.php?p=444062#p444034

I'll do the windows 7 version once I'm free.

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Need help with GDI button and Layered Window

Post by doubledave22 » 07 Feb 2022, 10:54

Hellbent wrote:
06 Feb 2022, 22:11
@doubledave22

In case you missed it. viewtopic.php?p=444062#p444034

I'll do the windows 7 version once I'm free.
Ah yes I saw, I am looking now...

I think there's some missing pieces in the PopUpWindow class.

AddTrigger() takes a "Label" and a "Value" but neither are utilized in the method.

Another question about GUI name in AddTrigger(). Am i reading this right, you use This.Hwnd as the gui name here? I have run into problems in the past when I tried doing this since sometimes the hwnd is stored as hex (0x532af4) and sometimes it's just decimal 5402938429 for the same number (as you know and love). Is this not a problem because we immediately store this.hwnd when creating the gui?

Code: Select all

Gui, % This.Hwnd ":Add", Text, % "x" cc.X " y" cc.Y " w" cc.W " h" cc.H " hwndhwnd"

I wanted to try making the buttons you built a child window of a main layered window and see what happens when moving the main window. This won't work on Win7 though correct?

Also, in LWButtons class any reason we cant just do a winmove here instead? I'm not sure if Gui, show is doing anything extra here. In my testing winmove working fine so just curious about this.

Code: Select all

	Move( x := 10 , y := 10 ){
		This.Button.UpdateSettings( { X: x , Y: y } )
		winmove, % "ahk_id " This.Button.Hwnd, , x, y
		;Gui, % This.Button.Hwnd ":Show", % "x" x " y" y " NA"
	}
I'd also like to share one thing that allows all of this to be possible for me. This may help others too. I never thought I could use layered windows because they need "+Alwaysontop" but if you are trying to overlay a layered window on a specific window you can also set +Owner%ThatWindow% instead of +Alwaysontop and the layered window will stay just above the owner.

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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 07 Feb 2022, 13:33

doubledave22 wrote:
07 Feb 2022, 10:54

I think there's some missing pieces in the PopUpWindow class.
AddTrigger() takes a "Label" and a "Value" but neither are utilized in the method.
Yeah, the trigger method hasn't been fully implemented yet. I was working on a project and wanted a new way of binding the triggers but at the time I wasn't sure how I should go about it. I have since come up with a way to do it but I haven't done the coding and testing for it yet.
If you look at how I bound button[ 3 ] in the LWButtons script you can see how I will likely code it.
i.e either pass a name of a label or a function object. For now the triggers only allow access to the DrawTriggers method which just paints the area where the controls are. I can try to add it in today when I do a windows 7 version, but I have a few questions for you first.
Even with the trigger method added in, you won't be able to use it for scripts that run on windows 7 though as you are aware, hidden controls can't be detected pre windows 8.

Another question about GUI name in AddTrigger(). Am i reading this right, you use This.Hwnd as the gui name here? I have run into problems in the past when I tried doing this since sometimes the hwnd is stored as hex (0x532af4) and sometimes it's just decimal 5402938429 for the same number (as you know and love). Is this not a problem because we immediately store this.hwnd when creating the gui?

Code: Select all

Gui, % This.Hwnd ":Add", Text, % "x" cc.X " y" cc.Y " w" cc.W " h" cc.H " hwndhwnd"
That's correct, the name of the gui is the hwnd of the window. You can run into issues here and there with things not looking right ( in hex and then in dec), but once you put your hex number into a If statement it is converted to dec to do the comparisons. A place that you might have had issues in the past is with windows messages "OnMessage" where the msg and hwnd params are always in dec.

I wanted to try making the buttons you built a child window of a main layered window and see what happens when moving the main window. This won't work on Win7 though correct?
That's correct. On windows 8+ you could just give the buttons a parent and move the parent to move all the buttons, but on Win 7 you will get an error if you try to set a layered window as a child. Which brings up the questions I have.
Before I had started coding out the LWButtons class I had noticed that you wanted to be able to move / hide / etc. the individual buttons around (I assume around to any monitor as the stated point of using layered windows was to have rounded edges which is only a issue if the buttons don't have a background / parent window )
Hence why the buttons are individual windows.
With some of your users being on windows 7 the current method may not be the best fit. So I think I need a bit more info on what you want the buttons to be able to do so that the solution can be derived from that.

Also, in LWButtons class any reason we cant just do a winmove here instead? I'm not sure if Gui, show is doing anything extra here. In my testing winmove working fine so just curious about this.

Code: Select all

	Move( x := 10 , y := 10 ){
		This.Button.UpdateSettings( { X: x , Y: y } )
		winmove, % "ahk_id " This.Button.Hwnd, , x, y
		;Gui, % This.Button.Hwnd ":Show", % "x" x " y" y " NA"
	}
They are basically the same, I would go with the Gui commands though since it is a ahk gui created in the same script.

I'd also like to share one thing that allows all of this to be possible for me. This may help others too. I never thought I could use layered windows because they need "+Alwaysontop" but if you are trying to overlay a layered window on a specific window you can also set +Owner%ThatWindow% instead of +Alwaysontop and the layered window will stay just above the owner.
You can do that without issue. When you create a new layered window you just change the "WindowOptions" (or w/e I called that key/var)
You would change it to something like

Code: Select all


{ ... , WindowOptions: "+Owner" ThatWindow } )

I'm going to adapt that lwbuttons class to work for win 7 now and perhaps add that trigger method.

If you can, please paint me a better picture of this.
Ultimately I am trying to create an overlay class and right now I am using a combination of layered windows and standard controls all as separate GUIs. I set these to be owned by the window and use wineventhook to make sure everything moves together.

I will be looking into this tomorrow but if I create one layered window and then draw all the various images and pseudo buttons, lines, etc do you know if all these drawings will just move with the layered window? I wonder why I am managing a bunch of small GUIs when I can just paint to one and have that track it's owner.
Atm I am confused by the notion of having the buttons all on a single layered window and being able to move each button on it's own and as a group?

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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 07 Feb 2022, 14:41

Don't miss the post before this one ^. DBL Post ( soon to be TRPL Post )

Here is the LWButtons class adapted for windows 7+ ( likely works for earlier versions too but I don't "KNOW" that it will )

Code: Select all


;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib>  ;<---Gdip.ahk lib
#Include <PopUpWindow_V2> 	;This was in one of my last posts
;****************************************************************************************************************************************************************************
#SingleInstance, Force
Gdip_Startup()

Buttons := []
Buttons[ 1 ] := { X: 10 , Y: 100 , W: 150 , H: 75 , Label: "Label1"  }
Buttons[ 2 ] := { X: 100 , Y: 200 , W: 150 , H: 75 , Label: "Label1"  }
Buttons[ 3 ] := { ButtonText: "Not Button" , X: 200 , Y: 300 , W: 150 , H: 75 , Label: Func( "Label2" ).Bind( Buttons )  }

Loop, % Buttons.Length()
	Buttons[ A_Index ] := New LWButtons( Buttons[ A_Index ] )



return
*ESC::ExitApp

F1::PopUpWindow.Helper()

Label1:
	tooltip, the button was pressed `nLabel1
	SoundBeep
	return 

Label2( obj ){
	tooltip, % obj[ 3 ].FontColor "`n" obj[ 3 ].X "`n" obj[ 3 ].Hwnd "`nLabel2"
	SoundBeep
	Random, outX, 0 , % A_ScreenWidth - obj[ 3 ].W
	Random, outY, 0 , % A_ScreenHeight - obj[ 3 ].H - 200
	obj[ 3 ].Move( outX , outY )
}

;********************************************************************************************************************************************************************************************************
;********************************************************************************************************************************************************************************************************
;********************************************************************************************************************************************************************************************************
;********************************************************************************************************************************************************************************************************
class LWButtons	{
	;class: Layered Window Buttons
	__New( obj := "" ){
		This._SetDefaults()
		This._UpdateDefaults( obj )
		This._CreateControl()
		This._DrawButton()
	}
	_SetDefaults(){
		
		This.Hwnd := ""
		This.Button := ""
		
		This.X := 10
		This.Y := 10 
		This.W := 10
		This.H := 10
		
		This.RestColor := "0xFF3399FF"
		This.PressedColor := "0xFF336699"
		This.MovingColor := "0xFFff0000"
		
		This.ButtonText := "Button"
		This.Font := "Comic Sans MS"
		This.FontSize := 16
		This.FontColor := "0xFF000000"
		This.FontOptions := " Center vCenter Bold "
		
		This.Roundness := 10
		This.Label := ""
		This.WindowOptions := " -DPIScale +AlwaysOnTop +ToolWindow"
		
		This.Pressed := 0
		
		OnMessage( 0x201 , This._ButtonClick.Bind( This ) ) 
	}
	_UpdateDefaults( obj := "" ){
		local k , v 
		for k, v in obj
			This[ k ] := obj[ k ]
	}
	_CreateControl(){
		local hwnd , bd := This.ClickBind
		This.Button := New PopUpWindow( { AutoShow: 1 , X: This.X , Y: This.Y , W: This.W , H: This.H , Options: This.WindowOptions } )
		This.Hwnd := This.Button.Hwnd
		
	}
	_ButtonClick(){
		local win
		MouseGetPos,,, win
		if( win = This.Hwnd ){
			if( GetKeyState( "Shift" ) ){
				This.Pressed := 2
				This._DrawButton()
				PostMessage, 0xA1, 2
				While( GetKeyState( "LButton" ) )
					sleep, 60
				WinGetPos, x, y ,,, % "ahk_id " This.Button.Hwnd
				This.Button.UpdateSettings( { X: x , Y: y } )
				This.Pressed := 0
				This._DrawButton()
			}else{
				This.Pressed := 1
				This._DrawButton()
				While( GetKeyState( "LButton" ) )
					sleep, 60
				This.Pressed := 0
				This._DrawButton()
				MouseGetPos,,, win
				if( win = This.Button.Hwnd ){
					if( isObject( This.Label ) )
						Try
							This.Label.Call()
					else 
						Try
							GoSub, % This.Label
				}
			}
		}
		
	}
	_DrawButton(){
		This.Button.ClearWindow()
		This._ButtonGraphics()
		This.Button.UpdateWindow()
	}
	_ButtonGraphics(){
		Brush := Gdip_BrushCreateSolid( ( This.Pressed = 0 ) ? ( This.RestColor ) : ( This.Pressed = 1 ) ? ( This.PressedColor ) : ( This.MovingColor )  ) , Gdip_FillRoundedRectangle( This.Button.G, Brush , 1 , 1 , This.W - 2 , This.H - 2 , This.Roundness ) , Gdip_DeleteBrush( Brush )
		Brush := Gdip_BrushCreateSolid( This.FontColor ) , Gdip_TextToGraphics( This.Button.G , This.ButtonText , "s" This.FontSize " c" Brush " " This.FontOptions " x0 y0" , This.Font, This.W , This.H ) , Gdip_DeleteBrush( Brush )
	}
	Move( x := 10 , y := 10 ){
		This.Button.UpdateSettings( { X: x , Y: y } )
		Gui, % This.Button.Hwnd ":Show", % "x" x " y" y " NA"
	}
	Hide(){
		Gui, % This.Button.Hwnd ":Hide" 
		;~ This.Button.ClearWindow( 1 ) ; <<---------------------  This is how I would normally "Hide" a layered window.
	}
	Show(){
		Gui, % This.Button.Hwnd ":Show", NA 
		;~ This._DrawButton() ; <<------ The way I would normally do it.
	}
	Delete(){
		This.Button.DeleteWindow()
	}
}

doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: Need help with GDI button and Layered Window

Post by doubledave22 » 07 Feb 2022, 14:47

Hellbent wrote:
07 Feb 2022, 13:33
Atm I am confused by the notion of having the buttons all on a single layered window and being able to move each button on it's own and as a group?
I will send you a message with some more details about my exact use case and show some examples of what I have already. I won't miss any of your posts don't worry!

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

Re: Need help with GDI button and Layered Window

Post by Hellbent » 07 Feb 2022, 17:31

doubledave22 wrote:
07 Feb 2022, 14:47
Hellbent wrote:
07 Feb 2022, 13:33
Atm I am confused by the notion of having the buttons all on a single layered window and being able to move each button on it's own and as a group?
I will send you a message with some more details about my exact use case and show some examples of what I have already. I won't miss any of your posts don't worry!
Got it. I'll take a look when I have the time.

Here is the updated version of the PopUpWindow class.

It has the trigger method finished. I also updated a few of the helper tool clips.

PopUpWindow class v2.2

Code: Select all

;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
;####################################################################################################################################################################################
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(){
		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 ]
		
	}
}
Here is an example of how to use the triggers. ( Windows 8+ )

Code: Select all

;****************************************************************************************************************************************************************************
#Include <My Altered GDIP lib>  ;<---Gdip.ahk lib
#Include <PopUpWindow_V2> 	;------- v2.2
;****************************************************************************************************************************************************************************
#SingleInstance, Force
Gdip_Startup()

Gui1 := New PopUpWindow( { AutoShow: 1 , X: "Center" , Y: "Center" , W: 600 , H: 300 , Options: " -DPIScale +AlwaysOnTop " } )
Gui1.PaintBackground( { Color: "0x6FFF0000" , X: 2 , Y: 2 , W: Gui1.W - 4 , H: Gui1.H - 4 , Round: 50 } , AutoUpdate := 1 ) 

Buttons := []
Buttons[ 1 ] := Gui1.AddTrigger( { X: 30 , Y: 30 , W: 150 , H: 30 , Value: "" , Label: Func( "DemoLabel1" ) } )
Buttons[ 2 ] := Gui1.AddTrigger( { X: 30 , Y: 70 , W: 150 , H: 30 , Value: "Hello World" , Label: Func( "DemoLabel2" ).Bind( Gui1 ) } )
Buttons[ 3 ] := Gui1.AddTrigger( { X: 30 , Y: 110 , W: 150 , H: 30 , Value: "" , Label: "DemoLabel3" } )

Gui1.DrawTriggers( color := "0xFFFFff00" , AutoUpdate := 1 )

return
GuiContextMenu:
*ESC::ExitApp

RALT::PopUpWindow.Helper()

DemoLabel1(){
	SoundBeep
	ToolTip, here
	return
}

DemoLabel2( obj , hwnd ){
	ToolTip, % obj.Controls[ obj.Handles[ hwnd ] ].Value
}

DemoLabel3:
	SoundBeep
	ToolTip, there
	return

Post Reply

Return to “Ask for Help (v1)”