Hi Joe.
I have the radio class with the fix for the screen reader issue added in.
I have decided to let you adjust the checkbox class since you have already done editing to it.
You can find the changes that you need to make in
_AddControl( obj ){ and
_DrawControl( obj ){
As for the Radio class.
I added in the extra param to
__New() like we had talked about. You can use either param to pass any and all the info that you want to pass.
I made a little demo script that should give you a better sense of what you can do. What I didn't show is that you can pass the same key/value in both objects. So for example you could pass {MainColor: } in both and it will use the second one you passed (the use of that may not be entirely clear at first but it is very useful).
Here is the radio class (still early draft):
Code: Select all
; <><><><><><><><><><><><><><><><> Custom Auto Size Radio Class <><><><><><><><><><><><><><><><>
;**************************************************************************************************************************************************************************
;**************************************************************************************************************************************************************************
;**************************************************************************************************************************************************************************
;By: Hellbent
;Version: 0.2
;Date: June 16th, 2021
;Purpose: Create Custom Gui Radio Controls
;Creates custom radio controls that auto size based on the font type and font size that you use with them and the text that you feed them.
;Adapted to work with screen readers.
class AutoSizeRadio {
static Index := 0 , Handles := [] , Controls := [] , Groups := []
__New( Input1 := "" , Input2 := "" ){
AutoSizeRadio.Controls[ ++AutoSizeRadio.Index ] := {}
AutoSizeRadio._SetDefaults( AutoSizeRadio.Controls[AutoSizeRadio.Index] )
AutoSizeRadio._UpdateDefaults( Input1 , Input2 , AutoSizeRadio.Controls[AutoSizeRadio.Index] )
AutoSizeRadio._GetTextSize( AutoSizeRadio.Controls[AutoSizeRadio.Index] )
AutoSizeRadio._AddControl( AutoSizeRadio.Controls[AutoSizeRadio.Index] )
AutoSizeRadio._DrawControl( AutoSizeRadio.Controls[AutoSizeRadio.Index] )
return AutoSizeRadio.Controls[AutoSizeRadio.Index]
}
_SetDefaults(obj){
obj.X := 10
obj.Y := 10
obj.W := 10
obj.H := 10
obj.MinW := 50
obj.MinH := 20
obj.Window := 1
obj.State := 0
obj.Value := 1
obj.BackgroundColor := "0xFFFFFF00"
obj.MainColor := "0xFFDCAE26"
obj.Text := "Radio"
obj.Font := "Arial"
obj.FontSize := "16"
obj.FontOptions := " vCenter Bold "
obj.CheckColor := "0xFF00FF00"
obj.ControlNumber := AutoSizeRadio.Index
obj.Group := 1
( (temp := AutoSizeRadio._GetGray( SubStr( obj.MainColor , 3 ) )) < 128 ) ? ( obj.FontColorTop := "0xFFFFFFFF" , obj.FontColorBottom := "0xFF000000" )
: ( obj.FontColorTop := "0xFF000000" , obj.FontColorBottom := "0xFFFFFFFF" )
}
_UpdateDefaults( input1 := "" , Input2 := "" , obj := "" ){
for k , v in input1
obj[k] := v
for k , v in input2
obj[k] := v
( temp := AutoSizeRadio._GetGray( SubStr( obj.MainColor , 3 ) ) < 128 ) ? ( obj.FontColorTop := "0xFFFFFFFF" , obj.FontColorBottom := "0xFF000000" )
: ( obj.FontColorTop := "0xFF000000" , obj.FontColorBottom := "0xFFFFFFFF" )
if(!isObject(AutoSizeRadio.Groups[obj.Group]))
AutoSizeRadio.Groups[obj.Group] := [ ]
AutoSizeRadio.Groups[obj.Group].Push(obj.ControlNumber)
}
_AddControl( obj ){
local hwnd
Gui, % obj.Window ":Add", Text, % "x" obj.x " y" obj.y " w" obj.w " h" obj.h " BackgroundTrans ", % obj.Text
Gui, % obj.Window ":Add", Picture, % "xp yp wp hp hwndhwnd gAutoSizeRadio._TriggerCheck"
AutoSizeRadio.Handles[hwnd] := AutoSizeRadio.Index
obj.Hwnd := hwnd
}
_GetTextSize(obj){
local pBitmap, G, Brush, temparr
pBitmap := Gdip_CreateBitmap( 10,10), G := Gdip_GraphicsFromImage( pBitmap ), Gdip_SetSmoothingMode( G , 2 )
Brush := Gdip_BrushCreateSolid( "0xFF000000")
temparr := StrSplit( Gdip_TextToGraphics( G , obj.Text, " s" obj.Fontsize " c" Brush " " obj.FontOptions " Left NoWrap x" 0 " y" 0 , obj.Font , 10000, 10000 ),"|","|" )
Gdip_DeleteBrush( Brush ), Gdip_DeleteGraphics( G ), Gdip_DisposeImage( pBitmap )
obj.StringWidth := temparr[3]
obj.StringHeight := temparr[4]
obj.W := obj.StringWidth + obj.StringHeight + 6 + obj.StringHeight + 6
obj.H := obj.StringHeight + 6 + 2
(obj.W<Obj.MinW)?(obj.W := Obj.MinW)
(obj.H<Obj.MinH)?(obj.H := Obj.MinH)
}
_TriggerCheck(){
local cIndex , gIndex , cNum , sNum
MouseGetPos,,,,ctrl,2
cIndex := AutoSizeRadio.Handles[ctrl]
gIndex := AutoSizeRadio.Controls[cIndex].Group
cNum := AutoSizeRadio.Controls[cIndex].ControlNumber
Loop, % AutoSizeRadio.Groups[gIndex].Length()
AutoSizeRadio.Controls[ AutoSizeRadio.Groups[gIndex,A_Index] ].State := 0
Loop, % AutoSizeRadio.Groups[gIndex].Length()
if(AutoSizeRadio.Groups[gIndex,A_Index]=cNum)
snum := A_Index
Loop, % AutoSizeRadio.Groups[gIndex].Length()
AutoSizeRadio.Controls[AutoSizeRadio.Groups[gIndex,A_Index]].Value := snum
AutoSizeRadio.Controls[cIndex].State := 1
AutoSizeRadio._CreateBitmap(gIndex)
}
_CreateBitmap( group ){
Loop, % AutoSizeRadio.Groups[group].Length()
AutoSizeRadio._DrawControl( AutoSizeRadio.Controls[ AutoSizeRadio.Groups[ group , A_Index ] ] )
}
_GetGray( OUTPUTCOLOR ){
StringTrimLeft,OUTPUTCOLOR,OUTPUTCOLOR,2
StringLeft , r , OUTPUTCOLOR , 2
StringTrimLeft,OUTPUTCOLOR,OUTPUTCOLOR,2
StringLeft , g , OUTPUTCOLOR , 2
StringTrimLeft,OUTPUTCOLOR,OUTPUTCOLOR,2
StringLeft , b , OUTPUTCOLOR , 2
r := "0x" r , g := "0x" g , b := "0x" b
REDSLIDERVALUE := r+0 , GreenSLIDERVALUE := g+0 , BlueSLIDERVALUE := b+0
GreyScaleSLIDERVALUE := Round((REDSLIDERVALUE+GreenSLIDERVALUE+BlueSLIDERVALUE)/3)
return GreyScaleSLIDERVALUE
}
_DrawControl( obj ){
local width := obj.StringWidth + obj.StringHeight + 6 + obj.StringHeight + 6 , Height := obj.StringHeight + 6 , a , b , c
(Width<Obj.MinW)?(Width := obj.MinW)
(Height<obj.MinH)?(Height := obj.MinH)
pBitmap := Gdip_CreateBitmap( width , Height + 2 ) , G := Gdip_GraphicsFromImage( pBitmap ) , Gdip_SetSmoothingMode( G , 2 )
Brush := Gdip_BrushCreateSolid( obj.BackgroundColor ) , Gdip_FillRectangle( G , Brush , -1 , -1 , width + 2 , Height + 4 ) , Gdip_DeleteBrush( Brush )
Brush := Gdip_BrushCreateSolid( obj.MainColor ) , Gdip_FillRoundedRectangle( G , Brush , 1 , 1 , width-2 , Height , 5 ) , Gdip_DeleteBrush( Brush )
;***********************************************
;Remove / comment this to remove gradient
Brush := Gdip_CreateLineBrushFromRect( 1 , 3 , Width - 6 , Height , "0x33F0F0F0" , "0x99000000" , 1 , 1 ) , Gdip_FillRoundedRectangle( G , Brush , 1 , 1 , Width - 2 , Height , 5 ) , Gdip_DeleteBrush( Brush )
;***********************************************
Brush := Gdip_CreateLineBrushFromRect( 1 , 1 , Width - 1 , Height , "0xFFF0F0F0" , "0xFF000000" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawRoundedRectangle( G , Pen , 1 , 1 , Width - 2 , Height , 5 ) , Gdip_DeletePen( Pen )
Brush := Gdip_BrushCreateSolid( "0xFFF0F0F0" ) , Gdip_FillRoundedRectangle( G , Brush , 3 , 3 , Height-4 , Height-4 , 5 ) , Gdip_DeleteBrush( Brush )
Pen := Gdip_CreatePen( "0xaa000000" , 1 ) , Gdip_DrawRoundedRectangle( G , Pen , 3 , 3 , Height-4 , Height-4 , 5 ) , Gdip_DeletePen( Pen )
if(obj.State){
Brush := Gdip_BrushCreateSolid( (obj.State)?(obj.Checkcolor):("0xFFc2c6ca") ) , Gdip_FillEllipse( G , Brush , 4 , 4 , Height-6 , Height-6 ) , Gdip_DeleteBrush( Brush )
Brush := Gdip_CreateLineBrushFromRect( 6 , 7 , Height-6 , Height-6 , (obj.State)?( "0x44" SubStr(obj.Checkcolor,4)):("0x44a2a6aa") , (obj.State)?("0x99000000"):("0x33000000") , 1 , 1 ) , Gdip_FillEllipse( G , Brush , 4 , 4 , Height-6 , Height-6 ) , Gdip_DeleteBrush( Brush )
Brush := Gdip_CreateLineBrushFromRect( 4 , 4 , Height-6 , Height-6 , "0xFF008080" , "0xFF000000" , 1 , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawEllipse( G , Pen , 4 , 4 , Height-6 , Height-6 ) , Gdip_DeletePen( Pen )
}
a := Height + 7,b := Height - 3,c := Width - 4
list = %a% , 4 | %c% , 4 | %c% , %b% | %a% , %b% |
Brush := Gdip_CreateLineBrush( 30 , 3 , width /2 , 1 , (!obj.State)?("0xFFF0F0F0"):(obj.Checkcolor) , (!obj.State)?("0xFF000000"):("0xFFffffff") , 1 ) , Pen := Gdip_CreatePenFromBrush( Brush , 1 ) , Gdip_DeleteBrush( Brush ) , Gdip_DrawLines( G , Pen , List ) , Gdip_DeletePen( Pen )
Brush := Gdip_BrushCreateSolid( obj.FontColorBottom ) , Gdip_TextToGraphics( G , obj.Text , "s" obj.FontSize " " obj.FontOptions " c" Brush " x" Height+5 " y3" , obj.Font , obj.StringWidth , Height ) , Gdip_DeleteBrush( Brush )
Brush := Gdip_BrushCreateSolid( obj.FontColorTop ) , Gdip_TextToGraphics( G , obj.Text , "s" obj.FontSize " " obj.FontOptions " c" Brush " x" Height+4 " y2" , obj.Font , obj.StringWidth , Height ) , Gdip_DeleteBrush( Brush )
Gdip_DeleteGraphics( G )
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
Gdip_DisposeImage( pBitmap )
GuiControl, % obj.Window ":" , % obj.Hwnd, % "HBitmap:" hBitmap
DeleteObject( hBitmap )
}
DeleteControl( input ){
;Might improve this later
;~ GuiControl, % input.Window ":Move" , % input.Hwnd, x-100 y-100 w0 h0
AutoSizeRadio.Controls[ input.ControlNumber ] := ""
}
}
;**************************************************************************************************************************************************************************
.
And here is a demo of it's use. (This uses the method we spoke of before of having the radio settings placed elsewhere in the script)
Code: Select all
;***************************************************************************************************
;#Include ;GDIP
;#Include ;AutoSizeRadio Class
;***************************************************************************************************
#SingleInstance, Force
SetBatchLines, -1
Gdip_Startup()
Gui, 1:+AlwaysOnTop -DPIScale
Gui, 1:Color, 22262a
Gui, 1:Margin, 10, 10
Group1 := SetupRadioGroup1()
Group1[1] := New AutoSizeRadio( { X: "m" , Y: "m" , Window: "1" , BackgroundColor: "0xFF22262A" } , Group1[1] )
Loop, 3
Group1[A_Index+1] := New AutoSizeRadio( { X: "m" , Y: "+5" , Window: "1" , BackgroundColor: "0xFF22262A" } , Group1[A_Index+1] )
OptionList := SetupRadioGroup2()
Loop, % OptionList.Length()
OptionList[ A_Index ] := New AutoSizeRadio( OptionList[ A_Index ] )
OtherRadios := SetupRadioGroup3()
Loop, % OtherRadios.Length()
OtherRadios[ A_Index ] := New AutoSizeRadio( { CheckColor: "0xFF00ff00" } , OtherRadios[ A_Index ] )
Gui, 1:Show,, AutoSizeRadio
return
GuiClose:
*ESC::ExitApp
Numpad1::
Gui, 1:+OwnDialogs
; Using the "STATE" key
; getting the state of the first radio in the first group
msgbox, % "State of radio 1: ( " Group1[1].State " )"
;Using the "VALUE" key
;Getting the selected radio from the first group. ( You can use any radio in the group to get this value )
msgbox, % "The selected radio in grounp 1 is: ( " Group1[2].Value " )"
return
Numpad2::
;How to delete a radio when you are destorying a gui.
;Will improve to do other things later.
AutoSizeRadio.DeleteControl( Group1[1] )
Group1[1] := ""
return
;**************************************************************************************************************************************************************************
SetupRadioGroup1(){
local obj := []
obj[1] := { Group: 1
, State: 0
, Value: 0
, Text: "Option 1"
, FontSize: 12
, Font: "Segoe UI"
, MinW: 150
, MinH: 30
, MainColor: "0xFFFFBF00"
, CheckColor: "0xFFff0000" }
obj[2] := { Group: 1, State: 0, Value: 0, Text: "Option 2", FontSize: 12 , Font: "Segoe UI", MinW: 150, MinH: 30, MainColor: "0xFF0000FF", CheckColor: "0xFFff0000" }
obj[3] := { Group: 1, State: 0, Value: 0, Text: "Option 3", FontSize: 12 , Font: "Segoe UI", MinW: 150, MinH: 30, MainColor: "0xFF32E64F", CheckColor: "0xFFff0000" }
obj[4] := { Group: 1, State: 0, Value: 0, Text: "Option 4", FontSize: 12 , Font: "Segoe UI", MinW: 150, MinH: 30, MainColor: "0xFF9A04DF", CheckColor: "0xFFff0000" }
return obj
}
;**************************************************************************************************************************************************************************
SetupRadioGroup2(){
local obj := [] , fs := 24 , Font := "Comic Sans MS" , GroupName := 2 , MinimumHeight := 60
obj[1] := { Window: 1, X: "+10", Y: "m", BackgroundColor: "0xFF22262A", Group: GroupName, State: 1, Value: 1, Text: "Item 1", FontSize: fs , Font: Font , MinW: 150, MinH: MinimumHeight, MainColor: "0xFFFDD42D", CheckColor: "0xFF11FFFF" }
obj[2] := { Window: 1, X: "p", Y: "+5", BackgroundColor: "0xFF22262A", Group: GroupName, State: 0, Value: 1, Text: "Item 2", FontSize: fs , Font: Font , MinW: 150, MinH: MinimumHeight, MainColor: "0xFFC80530", CheckColor: "0xFF11FFFF" }
obj[3] := { Window: 1, X: "p", Y: "+5", BackgroundColor: "0xFF22262A", Group: GroupName, State: 0, Value: 1, Text: "Item 3", FontSize: fs , Font: Font , MinW: 150, MinH: MinimumHeight, MainColor: "0xFF8C24AD", CheckColor: "0xFF11FFFF" }
obj[4] := { Window: 1, X: "p", Y: "+5", BackgroundColor: "0xFF22262A", Group: GroupName, State: 0, Value: 1, Text: "Item 4", FontSize: fs , Font: Font , MinW: 150, MinH: MinimumHeight, MainColor: "0xFFF5CE19", CheckColor: "0xFF11FFFF" }
obj[5] := { Window: 1, X: "p", Y: "+5", BackgroundColor: "0xFF22262A", Group: GroupName, State: 0, Value: 1, Text: "Item 5", FontSize: fs , Font: Font , MinW: 150, MinH: MinimumHeight, MainColor: "0xFFF4035D", CheckColor: "0xFF11FFFF" }
obj[6] := { Window: 1, X: "p", Y: "+5", BackgroundColor: "0xFF22262A", Group: GroupName, State: 0, Value: 1, Text: "Item 6", FontSize: fs , Font: Font , MinW: 150, MinH: MinimumHeight, MainColor: "0xFF1EFD4C", CheckColor: "0xFF11FFFF" }
return obj
}
;**************************************************************************************************************************************************************************
SetupRadioGroup3(){
local obj := [] , fs := 64 , Font := "Courier New" , GroupName := 3
obj[1] := { Window: 1, X: "+10", Y: "m", BackgroundColor: "0xFF22262A", Group: GroupName, State: 0, Value: 2, Text: "Blah Blah 1", FontSize: fs , Font: Font , MinW: 600, MinH: 30, MainColor: "0xFFffffff" }
obj[2] := { Window: 1, X: "p", Y: "+5", BackgroundColor: "0xFF22262A", Group: GroupName, State: 1, Value: 2, Text: "Some other text", FontSize: fs , Font: Font , MinW: 150, MinH: 30, MainColor: "0xFF888888" }
obj[3] := { Window: 1, X: "p", Y: "+5", BackgroundColor: "0xFF22262A", Group: GroupName, State: 0, Value: 2, Text: "Blah Blah 3", FontSize: fs , Font: Font , MinW: 150, MinH: 30, MainColor: "0xFF000000" }
return obj
}
F.Y.I. You can just paste the class into the demo script. There is no need to save it to another file.
I have already tested this with the screen reader and it works flawlessly on my end.
If I forgot anything or if you have any questions let me know.
*EDIT*
Added a way to delete a radio for when you are destroying a gui. (See Numpad2 in the demo)