I have a proposal to add a "Rectangle" class that adds a picture with a specified color with the c option.
It has the method "SetColor(color)" to change the color.
This can also be used to add some lines to your gui.
I was thinking of changing the native picture class to accept an included c option, but I do not know how we can change the method Opt().
I would prefer to do it this way.
[Codebox=autohotkey]; Creating rectangles filled with a color
g.AddRectangle("x" 230 " y" 00 " w" 32 " h" 32 " cRed")
g.AddRectangle("x" 262 " y" 0 " w" 32 " h" 32 " cGreen")
g.AddRectangle("x" 230 " y" 32 " w" 32 " h" 32 " cBlue")
g.AddRectangle("x" 262 " y" 32 " w" 32 " h" 32 " cYellow")[/Codebox]
- 2021-10-16 20_03_12-Test.png (10.28 KiB) Viewed 6310 times
Code: Select all
; ==================================================================
; GuiControl_Ex
; ==================================================================
class ListComboBox_Ext {
Static __New() {
For prop in this.Prototype.OwnProps() {
Gui.ListBox.Prototype.%prop% := this.prototype.%prop%
Gui.ComboBox.Prototype.%prop% := this.prototype.%prop%
}
}
GetCount() {
If (this.Type = "ListBox")
return SendMessage(0x018B, 0, 0, this.hwnd) ; LB_GETCOUNT
Else If (this.Type = "ComboBox")
return SendMessage(0x146, 0, 0, this.hwnd) ; CB_GETCOUNT
}
GetText(row) {
If (this.Type = "ListBox")
return this._GetString(0x18A,0x189,row) ; 0x18A > LB_GETTEXTLEN // 0x189 > LB_GETTEXT
Else if (this.Type = "ComboBox")
return this._GetString(0x149,0x148,row) ; 0x149 > CB_GETLBTEXTLEN // 0x148 > CB_GETLBTEXT
}
GetItems() {
result := []
Loop this.GetCount()
result.Push(this.GetText(A_Index))
return result
}
_GetString(getLen_msg,get_msg,row) {
size := SendMessage(getLen_msg, row-1, 0, this.hwnd) ; GETTEXTLEN
buf := Buffer( (size+1) * (StrLen(Chr(0xFFFF))?2:1), 0 )
SendMessage(get_msg, row-1, buf.ptr, this.hwnd) ; GETTEXT
return StrGet(buf)
}
}
class ListView_Ext extends Gui.ListView { ; Technically no need to extend classes unless
Static __New() { ; you are attaching new base on control creation.
For prop in this.Prototype.OwnProps()
super.Prototype.%prop% := this.Prototype.%prop%
}
Checked(row) { ; This was taken directly from the AutoHotkey help files.
return (SendMessage(4140,row-1,0xF000,, "ahk_id " this.hwnd) >> 12) - 1 ; VM_GETITEMSTATE = 4140 / LVIS_STATEIMAGEMASK = 0xF000
}
IconIndex(row,col:=1) { ; from "just me" LV_EX ; Link: https://www.autohotkey.com/boards/viewtopic.php?f=76&t=69262&p=298308#p299057
LVITEM := Buffer((A_PtrSize=8)?56:40, 0) ; create variable/structure
NumPut("UInt", 0x2, "Int", row-1, "Int", col-1, LVITEM.ptr, 0) ; LVIF_IMAGE := 0x2 / iItem (row) / column num
NumPut("Int", 0, LVITEM.ptr, (A_PtrSize=8)?36:28) ; iImage
SendMessage(StrLen(Chr(0xFFFF))?0x104B:0x1005, 0, LVITEM.ptr,, "ahk_id " this.hwnd) ; LVM_GETITEMA/W := 0x1005 / 0x104B
return NumGet(LVITEM.ptr, (A_PtrSize=8)?36:28, "Int")+1 ;iImage
}
GetColWidth(n) {
return SendMessage(0x101D, n-1, 0, this.hwnd)
}
}
class StatusBar_Ext extends Gui.StatusBar {
Static __New() {
For prop in this.Prototype.OwnProps()
super.Prototype.%prop% := this.Prototype.%prop%
}
RemoveIcon(part:=1) {
hIcon := SendMessage(0x414, part-1, 0, this.hwnd)
If hIcon
SendMessage(0x40F, part-1, 0, this.hwnd)
return DllCall("DestroyIcon","UPtr",hIcon)
}
}
class PicButton extends Gui.Button {
Static __New() {
Gui.Prototype.AddPicButton := this.AddPicButton
}
Static AddPicButton(sOptions:="",sPicFile:="",sPicFileOpt:="") {
ctl := this.Add("Button",sOptions)
ctl.base := PicButton.Prototype
ctl.SetImg(sPicFile, sPicFileOpt)
return ctl
}
SetImg(sFile, sOptions:="") { ; input params exact same as first 2 params of LoadPicture()
Static ImgType := 0 ; thanks to teadrinker: https://www.autohotkey.com/boards/viewtopic.php?p=299834#p299834
Static BS_ICON := 0x40, BS_BITMAP := 0x80, BM_SETIMAGE := 0xF7
hImg := LoadPicture(sFile, sOptions, &_type)
curStyle := ControlGetStyle(this.hwnd)
ControlSetStyle (curStyle | (!_type?BS_BITMAP:BS_ICON)), this.hwnd
hOldImg := SendMessage(BM_SETIMAGE, _type, hImg, this.hwnd)
If (hOldImg)
(ImgType) ? DllCall("DestroyIcon","UPtr",hOldImg) : DllCall("DeleteObject","UPtr",hOldImg)
ImgType := _type ; store current img type for next call/release
}
Type {
get => "PicButton"
}
}
class Rectangle extends Gui.Pic {
; Creates a Picture with one color, the color defined by an option starting with a c in the options.
Static __New() {
Gui.Prototype.AddRectangle := this.AddRectangle
}
Static AddRectangle(sOptions := "", sPicFile := "") {
Color := RegExReplace(sOptions, ".*\bc([^\s]*)\b.*", "$1", &ColorCount)
if (ColorCount and Color != ""){
sOptions := RegExReplace(sOptions, "(.*)\bc([^\s]*)\b\s?(.*)", "$1$3") " +0x4E"
}
ctl := this.Add("Picture", sOptions, sPicFile)
ctl.base := Rectangle.Prototype
ctl.SetColor(Color)
return ctl
}
SetColor(sColor) { ; input params exact same as first 2 params of LoadPicture()
This.Color := sColor
switch sColor{
case "Black":
sColor := "000000"
case "Silver":
sColor := "C0C0C0"
case "Gray":
sColor := "808080"
case "White":
sColor := "FFFFFF"
case "Maroon":
sColor := "800000"
case "Red":
sColor := "FF0000"
case "Purple":
sColor := "800080"
case "Fuchsia":
sColor := "FF00FF"
case "Green":
sColor := "008000"
case "Lime":
sColor := "00FF00"
case "Olive":
sColor := "808000"
case "Yellow":
sColor := "FFFF00"
case "Navy":
sColor := "000080"
case "Blue":
sColor := "0000FF"
case "Teal":
sColor := "008080"
case "Aqua":
sColor := "00FFFF"
}
BMBITS := Buffer(4, 0), NumPut("UInt", "0x" . sColor, BMBITS, 0)
hBM := DllCall("Gdi32.dll\CreateBitmap", "Int", 1, "Int", 1, "UInt", 1, "UInt", 24, "Ptr", 0)
hBM := DllCall("User32.dll\CopyImage", "Ptr", hBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008)
DllCall("Gdi32.dll\SetBitmapBits", "Ptr", hBM, "UInt", 3, "Ptr", BMBITS)
return DllCall("User32.dll\SendMessage", "Ptr", this.hwnd, "UInt", 0x172, "Ptr", 0, "Ptr", hBM)
}
Type {
get => "Picture"
}
}
class SplitButton extends Gui.Button {
Static __New() {
super.Prototype.SetImg := PicButton.Prototype.SetImg
Gui.Prototype.AddSplitButton := this.AddSplitButton
}
Static AddSplitButton(sOptions:="",sText:="",callback:="") {
Static BS_SPLITBUTTON := 0xC
ctl := this.Add("Button",sOptions,sText)
ctl.base := SplitButton.Prototype
ControlSetStyle (ControlGetStyle(ctl.hwnd) | BS_SPLITBUTTON), ctl.hwnd
If callback
ctl.callback := callback
, ctl.OnNotify(-1248, ObjBindMethod(ctl,"DropCallback"))
return ctl
}
Drop() {
this.DropCallback(this,0)
}
DropCallback(ctl, lParam) {
ctl.GetPos(&x,&y,,&h)
f := this.callback, f(ctl,{x:x, y:y+h})
}
Type {
get => "SplitButton"
}
}
class ToggleButton extends Gui.Checkbox {
Static __New() {
super.Prototype.SetImg := PicButton.Prototype.SetImg
Gui.Prototype.AddToggleButton := this.AddToggleButton
}
Static AddToggleButton(sOptions:="",sText:="") {
ctl := this.Add("Checkbox",sOptions " +0x1000",sText)
ctl.base := ToggleButton.Prototype
return ctl
}
Type {
get => "ToggleButton"
}
}
class Edit_Ext extends Gui.Edit {
Static __New() {
For prop in this.Prototype.OwnProps()
super.Prototype.%prop% := this.prototype.%prop%
}
Append(txt, top := false) {
txtLen := SendMessage(0x000E, 0, 0,,this.hwnd) ;WM_GETTEXTLENGTH
pos := (!top) ? txtLen : 0
SendMessage(0x00B1, pos, pos,,this.hwnd) ;EM_SETSEL
SendMessage(0x00C2, False, StrPtr(txt),,this.hwnd) ;EM_REPLACESEL
}
}
Here is the example:
Code: Select all
; AHK v2
#INCLUDE _GuiCtlExt.ahk
Global g
IL := IL_Create(2)
IL_Add(IL, "shell32.dll", 128)
IL_Add(IL, "shell32.dll", 129)
IL_Add(IL, "shell32.dll", 256)
g := Gui("-MinimizeBox -MaximizeBox","Test")
g.OnEvent("close",gui_close)
g.OnEvent("escape",gui_close)
ctl := g.Add("ListView","+Report w210 h100 vLV Checked Icon2",["test"])
ctl.SetImageList(IL,1)
ctl.Add("check Icon3","Row1"), hwnd := ctl.hwnd
ctl.Add("icon1","Row2")
ctl.Opt("+Report")
ctl.ModifyCol()
g.Add("ListBox","w100 h100 vLB",["ListBox Item 1","ListBox Item 2","ListBox Item 3"])
g.Add("ComboBox","x+10 yp w100 h100 vCB Section",["ComboBox Item 1","ComboBox Item 2","ComboBox Item 3","ComboBox Item 4"])
btn := g.AddPicButton("vPicBtn w24 h24","netshell.dll","Icon151 w20 h20")
btn.OnEvent("click",gui_events)
btn := g.Add("Button","vData x+0","Show Data")
btn.OnEvent("Click",gui_events)
btn := g.AddSplitButton("vDropBtn1 xs h32 w48","",gui_events) ; here the callback is only for clicking the split down arrow
btn.OnEvent("click",gui_events) ; this is for when you click the "normal" part of the button
btn.SetImg("netshell.dll","Icon151 w20 h20")
btn := g.AddToggleButton("vToggleBtn w48 h32","")
btn.OnEvent("click",gui_events)
btn.SetImg("netshell.dll","Icon151 w20 h20")
; Creating rectangles filled with a color
g.AddRectangle("x" 230 " y" 00 " w" 32 " h" 32 " cRed")
g.AddRectangle("x" 262 " y" 0 " w" 32 " h" 32 " cGreen")
g.AddRectangle("x" 230 " y" 32 " w" 32 " h" 32 " cBlue")
g.AddRectangle("x" 262 " y" 32 " w" 32 " h" 32 " cYellow")
g.show()
gui_close(*) {
ExitApp
}
gui_events(ctl, info) {
Global g
If (ctl.name = "DropBtn1") && IsObject(info) {
m(info)
} Else If (ctl.name = "DropBtn1") {
msgbox "You clicked the button portion of the drop button.`r`n`r`nTry clicking the arrow."
} Else If (ctl.Name = "PicBtn")
msgbox "You clicked the pic btn."
Else If (ctl.name = "Data") {
LVr := 1, LBr := 2, CBr := 3, LBi := "", CBi := ""
For item in g["LB"].GetItems()
LBi .= (LBi?"`r`n`t":"`t") item
For item in g["CB"].GetItems()
CBi .= (CBi?"`r`n`t":"`t") item
MsgBox "ListView`r`n`r`n"
. "`tIconIndex Row " LVr ": " g["LV"].IconIndex(LVr) "`r`n"
. "`tChecked Row " LVr ": " (g["LV"].Checked(LVr)?"true":"false") "`r`n"
. "`trow count: " g["LV"].GetCount() "`r`n"
. "`tsecond row text: " g["LV"].GetText(2) "`r`n`r`n" ; original LV.GetText() still works as expected
. "ListBox`r`n`r`n"
. "`tItemText Row " LBr ": " g["LB"].GetText(LBr) "`r`n" ; .GetText() method added to ListBox
. "`tRow Count: " g["LB"].GetCount() "`r`n`r`n"
. "`tItems:`r`n" LBI "`r`n`r`n"
. "ComboBox`r`n`r`n"
. "`tItemText Row " CBr ": " g["CB"].GetText(CBr) "`r`n"
. "`tRow Count: " g["CB"].GetCount() "`r`n`r`n"
. "`tItems:`r`n" CBi
} Else If (ctl.name = "ToggleBtn")
Msgbox "Value: " ctl.Value
}
m(coords) {
me := Menu()
me.Add("Item 1",m_event)
me.Add("Item 2",m_event)
me.Show(coords.x, coords.y)
}
m_event(item, pos, m) {
msgbox "You clicked: " item
}
Here is my try to add a method so the Opt method will also accept the c parameter, but this failed...
Code: Select all
Opt(sOptions){
Color := RegExReplace(sOptions, ".*\bc([^\s]*)\b.*", "$1", &ColorCount)
if (ColorCount and Color != "") {
sOptions := RegExReplace(sOptions, "(.*)\bc([^\s]*)\b\s?(.*)", "$1$3") " +0x4E"
this.SetColor(Color)
}
this.Opt(sOptions)
}