[2024/05/06] ColorButton.ahk | An extended method that lets you customize gui button background colors.

Post your working scripts, libraries and tools.
User avatar
NPerovic
Posts: 39
Joined: 31 Dec 2022, 01:25
Contact:

[2024/05/06] ColorButton.ahk | An extended method that lets you customize gui button background colors.

01 May 2024, 13:37

This is an extended method for changing a button's background color.

Updates: 2024/05/06
  • Update structure for 32-bit AutoHotkey v2.0.X. (No changes for the structure for v2.1-alpha.x)
  • Fixed the corner issues for win 10 users.
Note: Those structure classes for v2.0.X works the same way as v2.1-alpha.x.



Features
  • Easily change a button's background color.
  • Automatically set the text colour to white or black depends on the background colour.
  • Compatible with AutoHotkey v2.1-alpha.9 or later. Update: v2.0 is also supported now.
  • Learn more about the ahk v2.1-alpha: Click here

Rounded Button
Image

No Rounded Corners
Image


How To Use
  1. Download the ColorButton.ahk file.
  2. Include the ColorButton.ahk file in your script.
  3. Implement the background color by using the SetBackColor method on your button object.

SetBackColor

Code: Select all

GuiCtrl.SetBackColor(btnBgColor, [colorBehindBtn, roundedCorner])

Parameters

btnBgColor
Type: Integer
Button's background color. (RGB)

colorBehindBtn
Type: Integer
The color of the button's surrounding area. If omitted, if will be the same as GuiObj.BackColor.
Usually, omit this parameter and let it be transparent will looks better.

roundedCorner
Type: Integer
Specifies the rounded corner preference for the button.
If omitted, the default style will be used. (Enabled on win 11, disabled on win 10)


Examples




Get Code

GitHub: ColorButton.ahk


For v2.1-alpha.9 or later

Code: Select all

/************************************************************************
 * @description An extended method for changing a button's background color.
 * @file ColorButton.ahk
 * @author Nikola Perovic
 * @link https://github.com/nperovic/ColorButton.ahk
 * @date 2024/05/06
 * @version 1.2.0
 ***********************************************************************/

#Requires AutoHotkey v2.1-alpha.9
#SingleInstance

class NMCUSTOMDRAWINFO {
    hdr        : NMCUSTOMDRAWINFO.NMHDR
    dwDrawStage: u32
    hdc        : uptr
    rc         : NMCUSTOMDRAWINFO.RECT
    dwItemSpec : uptr
    uItemState : i32
    lItemlParam: iptr

    class RECT {
        left: i32, top: i32, right: i32, bottom: i32
    }

    class NMHDR {
        hwndFrom: uptr
        idFrom  : uptr
        code    : i32
    }
}

/**
 * The extended class for the built-in `Gui.Button` class.
 * @method SetBackColor Set the button's background color
 * @example
 * btn := myGui.AddButton(, "SUPREME")
 * btn.SetBackColor(0xaa2031)
 */
class _BtnColor extends Gui.Button
{
    static __New() => super.Prototype.SetBackColor := ObjBindMethod(this, "SetBackColor")

    /**
     * @param {Gui.Button} myBtn omitted.
     * @param {integer} btnBgColor Button's background color. (RGB)
     * @param {integer} [colorBehindBtn] The color of the button's surrounding area. If omitted, if will be the same as `myGui.BackColor`. **(Usually let it be transparent looks better.)**
     * @param {integer} [roundedCorner] Specifies the rounded corner preference for the button. If omitted,        : 
     * > For Windows 11: Enabled. (value: 9)  
     * > For Windows 10: Disabled.   
     */
    static SetBackColor(myBtn, btnBgColor, colorBehindBtn?, roundedCorner?)
    {
        static BS_FLAT          := 0x8000
        static BS_BITMAP        := 0x0080
        static IS_WIN11         := (VerCompare(A_OSVersion, "10.0.22200") >= 0)
        static WM_CTLCOLORBTN   := 0x0135
        static NM_CUSTOMDRAW    := -12
        static WM_DESTROY       := 0x0002
        static WS_EX_COMPOSITED := 0x02000000
        static WS_CLIPSIBLINGS  := 0x04000000
        static BTN_STYLE        := (WS_CLIPSIBLINGS | BS_FLAT | BS_BITMAP)

        rcRgn       := unset
        clr         := IsNumber(btnBgColor) ? btnBgColor : ColorHex(btnBgColor)
        isDark      := IsColorDark(clr)
        hoverColor  := RgbToBgr(BrightenColor(clr, isDark ? 15 : -15))
        pushedColor := RgbToBgr(BrightenColor(clr, isDark ? -10 : 10))
        clr         := RgbToBgr(clr)
        btnBkColr   := (colorBehindBtn ?? !IS_WIN11) && RgbToBgr(ColorHex(myBtn.Gui.BackColor))
        hbrush      := (colorBehindBtn ?? !IS_WIN11) ? CreateSolidBrush(btnBkColr) : GetStockObject(5)

        myBtn.Gui.OnMessage(WM_CTLCOLORBTN, ON_WM_CTLCOLORBTN)

        if btnBkColr
            myBtn.Gui.OnEvent("Close", (*) => DeleteObject(hbrush))

        myBtn.Opt(BTN_STYLE (IsSet(colorBehindBtn) ? "Background" colorBehindBtn : "")) ;  
        myBtn.OnNotify(NM_CUSTOMDRAW, (gCtrl, lParam) => ON_NM_CUSTOMDRAW(gCtrl, lParam))
        SetWindowTheme(myBtn.hwnd, isDark ? "DarkMode_Explorer" : "Explorer")
        myBtn.Redraw()
        SetWindowPos(mybtn.hwnd, 0,,,,, 0x43)

        ON_WM_CTLCOLORBTN(GuiObj, wParam, lParam, Msg)
        {
            if (lParam != myBtn.hwnd || !myBtn.Focused)
                return

            SelectObject(wParam, hbrush)
            SetBkMode(wParam, 0)

            if (colorBehindBtn ?? !IS_WIN11) 
                SetBkColor(wParam, btnBkColr)

            return hbrush 
        }

        first := 1

        ON_NM_CUSTOMDRAW(gCtrl, lParam)
        {
            static CDDS_PREPAINT        := 0x1
            static CDDS_PREERASE        := 0x3
            static CDIS_HOT             := 0x40
            static CDRF_NOTIFYPOSTPAINT := 0x10
            static CDRF_SKIPPOSTPAINT   := 0x100
            static CDRF_SKIPDEFAULT     := 0x4
            static CDRF_NOTIFYPOSTERASE := 0x40
            static CDRF_DODEFAULT       := 0x0
            static DC_BRUSH             := GetStockObject(18)
            static DC_PEN               := GetStockObject(19)
            
            lpnmCD := StructFromPtr(NMCUSTOMDRAWINFO, lParam)

            if (lpnmCD.hdr.code != NM_CUSTOMDRAW ||lpnmCD.hdr.hwndFrom != gCtrl.hwnd)
                return CDRF_DODEFAULT
            
            switch lpnmCD.dwDrawStage {
            case CDDS_PREERASE:
            {
                SetBkMode(lpnmCD.hdc, 0)
                if (roundedCorner ?? IS_WIN11) {
                    rcRgn := CreateRoundRectRgn(lpnmCD.rc.left, lpnmCD.rc.top, lpnmCD.rc.right, lpnmCD.rc.bottom, roundedCorner ?? 9, roundedCorner ?? 9)
                    SetWindowRgn(gCtrl.hwnd, rcRgn, 1)
                    DeleteObject(rcRgn)
                }
                return CDRF_NOTIFYPOSTERASE 
            }
            case CDDS_PREPAINT: 
            {
                isPressed  := GetKeyState("LButton", "P")
                brushColor := (!(lpnmCD.uItemState & CDIS_HOT) || first ? clr : isPressed ? pushedColor : hoverColor)
                penColor   := (!first && gCtrl.Focused && !isPressed ? 0xFFFFFF : brushColor)
                
                SelectObject(lpnmCD.hdc, DC_BRUSH)
                SetDCBrushColor(lpnmCD.hdc, brushColor)
                SelectObject(lpnmCD.hdc, DC_PEN)
                SetDCPenColor(lpnmCD.hdc, penColor)

                rounded := !!(rcRgn ?? 0)

                if (!first && gCtrl.Focused && !isPressed) {
                    if !rounded {
                        lpnmCD.rc.left   += 1
                        lpnmCD.rc.top    += 1
                        lpnmCD.rc.right  -= 1
                        lpnmCD.rc.bottom -= 1
                    }
                    DrawFocusRect(lpnmCD.hdc, lpnmCD.rc)
                }

                if rounded {
                    RoundRect(lpnmCD.hdc, lpnmCD.rc.left, lpnmCD.rc.top, lpnmCD.rc.right - rounded, lpnmCD.rc.bottom - rounded, roundedCorner ?? 9, roundedCorner ?? 9)
                    DeleteObject(rcRgn)
                    rcRgn := ""                    
                }
                else FillRect(lpnmCD.hdc, lpnmCD.rc, DC_BRUSH)

                if first
                    first := 0

                SetWindowPos(mybtn.hwnd, 0,,,,, 0x4043)

                return CDRF_NOTIFYPOSTPAINT
            }}
            
            return CDRF_DODEFAULT
        }

        static RgbToBgr(color) => (IsInteger(color) ? ((Color >> 16) & 0xFF) | (Color & 0x00FF00) | ((Color & 0xFF) << 16) : NUMBER(RegExReplace(STRING(color), "Si)c?(?:0x)?(?<R>\w{2})(?<G>\w{2})(?<B>\w{2})", "0x${B}${G}${R}")))

        static CreateRoundRectRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, nWidthEllipse, nHeightEllipse) => DllCall('Gdi32\CreateRoundRectRgn', 'int', nLeftRect, 'int', nTopRect, 'int', nRightRect, 'int', nBottomRect, 'int', nWidthEllipse, 'int', nHeightEllipse, 'ptr')

        static CreateSolidBrush(crColor) => DllCall('Gdi32\CreateSolidBrush', 'uint', crColor, 'ptr')

        static ColorHex(clr) => Number((!InStr(clr, "0x") ? "0x" : "") clr)

        static DrawFocusRect(hDC, lprc) => DllCall("User32\DrawFocusRect", "ptr", hDC, "ptr", lprc, "int")

        static GetStockObject(fnObject) => DllCall('Gdi32\GetStockObject', 'int', fnObject, 'ptr')

        static SetWindowPos(hWnd, hWndInsertAfter, X := 0, Y := 0, cx := 0, cy := 0, uFlags := 0x40) => DllCall("User32\SetWindowPos", "ptr", hWnd, "ptr", hWndInsertAfter, "int", X, "int", Y, "int", cx, "int", cy, "uint", uFlags, "int")

        static SetDCPenColor(hdc, crColor) => DllCall('Gdi32\SetDCPenColor', 'ptr', hdc, 'uint', crColor, 'uint')

        static SetDCBrushColor(hdc, crColor) => DllCall('Gdi32\SetDCBrushColor', 'ptr', hdc, 'uint', crColor, 'uint')

        static SetWindowRgn(hWnd, hRgn, bRedraw) => DllCall("User32\SetWindowRgn", "ptr", hWnd, "ptr", hRgn, "int", bRedraw, "int")

        static DeleteObject(hObject) {
            DllCall('Gdi32\DeleteObject', 'ptr', hObject, 'int')
        }

        static FillRect(hDC, lprc, hbr) => DllCall("User32\FillRect", "ptr", hDC, "ptr", lprc, "ptr", hbr, "int")

        static IsColorDark(clr) => 
            ( (clr >> 16 & 0xFF) / 255 * 0.2126 
            + (clr >>  8 & 0xFF) / 255 * 0.7152 
            + (clr       & 0xFF) / 255 * 0.0722 < 0.5 )

        static RGB(R := 255, G := 255, B := 255) => ((R << 16) | (G << 8) | B)
        
        static BrightenColor(clr, perc := 5) => ((p := perc / 100 + 1), RGB(Round(Min(255, (clr >> 16 & 0xFF) * p)), Round(Min(255, (clr >> 8 & 0xFF) * p)), Round(Min(255, (clr & 0xFF) * p))))

        static RoundRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect, nWidth, nHeight) => DllCall('Gdi32\RoundRect', 'ptr', hdc, 'int', nLeftRect, 'int', nTopRect, 'int', nRightRect, 'int', nBottomRect, 'int', nWidth, 'int', nHeight, 'int')
        
        static SetTextColor(hdc, color) => DllCall("SetTextColor", "Ptr", hdc, "UInt", color)
        
        static SetWindowTheme(hwnd, appName, subIdList?) => DllCall("uxtheme\SetWindowTheme", "ptr", hwnd, "ptr", StrPtr(appName), "ptr", subIdList ?? 0)
        
        static SelectObject(hdc, hgdiobj) => DllCall('Gdi32\SelectObject', 'ptr', hdc, 'ptr', hgdiobj, 'ptr')
                
        static SetBkColor(hdc, crColor) => DllCall('Gdi32\SetBkColor', 'ptr', hdc, 'uint', crColor, 'uint')
        
        static SetBkMode(hdc, iBkMode) => DllCall('Gdi32\SetBkMode', 'ptr', hdc, 'int', iBkMode, 'int')
    }
}

; Example
/*
myGui := Gui()
myGui.SetFont("cWhite s20", "Segoe UI")
myGui.BackColor := 0x2c2c2c
btn := myGui.AddButton(, "SUPREME")
btn.SetBackColor(0xaa2031)
btn2 := myGui.AddButton(, "SUPREME")
btn2.SetBackColor(0xffd155)
btn3 := myGui.AddButton(, "SUPREME")
btn3.SetBackColor("0x7755ff", , 0)

myGui.Show("w280 h280")


For v2.0+ (Not suitable for v2.1-alpha.9 or later. Alpha users please use the one above.)

Code: Select all

/************************************************************************
 * @description An extended method for changing a button's background color.
 * @file ColorButton.ahk
 * @author Nikola Perovic
 * @link https://github.com/nperovic/ColorButton.ahk
 * @date 2024/05/06
 * @version 1.2.0
 ***********************************************************************/

#Requires AutoHotkey v2.0
#SingleInstance

StructFromPtr(StructClass, Address) => StructClass(Address)

Buffer.Prototype.PropDesc := PropDesc
PropDesc(buf, name, ofst, type, ptr?) {
    if (ptr??0)
        NumPut(type, NumGet(ptr, ofst, type), buf, ofst)
    buf.DefineProp(name, {
        Get: NumGet.Bind(, ofst, type),
        Set: (p, v) => NumPut(type, v, buf, ofst)
    })
}
class NMHDR extends Buffer {
    __New(ptr?) {
        super.__New(A_PtrSize * 2 + 4)
        this.PropDesc("hwndFrom", 0, "uptr", ptr?)
        this.PropDesc("idFrom", A_PtrSize,"uptr", ptr?)   
        this.PropDesc("code", A_PtrSize * 2 ,"int", ptr?)     
    }
}

class RECT extends Buffer { 
    __New(ptr?) {
        super.__New(16)
        for i, prop in ["left", "top", "right", "bottom"]
            this.PropDesc(prop, 4 * (i-1), "int", ptr?)
    }
}
class NMCUSTOMDRAWINFO extends Buffer
{
    __New(ptr?) {
        static x64 := (A_PtrSize = 8)
        super.__New(x64 ? 80 : 48)
        this.hdr := NMHDR(ptr?)
        this.rc  := RECT((ptr??0) ? ptr + (x64 ? 40 : 20) : unset)
        this.PropDesc("dwDrawStage", x64 ? 24 : 12, "uint", ptr?)  
        this.PropDesc("hdc"        , x64 ? 32 : 16, "uptr", ptr?)          
        this.PropDesc("dwItemSpec" , x64 ? 56 : 36, "uptr", ptr?)   
        this.PropDesc("uItemState" , x64 ? 64 : 40, "int", ptr?)   
        this.PropDesc("lItemlParam", x64 ? 72 : 44, "iptr", ptr?)
    }
}

class _Gui extends Gui
{
    static __New() {
        super.Prototype.OnMessage         := ObjBindMethod(this, "OnMessage")
        super.Control.Prototype.OnMessage := ObjBindMethod(this, "OnMessage")
    }

    static OnMessage(obj, Msg, Callback, AddRemove?)
    {
        OnMessage(Msg, _callback, AddRemove?)
        obj.OnEvent("Close", g => OnMessage(Msg, _callback, 0))

        _callback(wParam, lParam, uMsg, hWnd)
        {
            try if (uMsg = Msg && hWnd = obj.hwnd)
                return Callback(obj, wParam, lParam, uMsg)
        }
    }
}

class _Gui extends Gui
{
    static __New() => (super.Prototype.OnMessage := ObjBindMethod(this, "OnMessage"))

    static OnMessage(obj, Msg, Callback, AddRemove?)
    {
        OnMessage(Msg, _callback, AddRemove?)
        obj.OnEvent("Close", g => OnMessage(Msg, _callback, 0))

        _callback(wParam, lParam, uMsg, hWnd)
        {
            if (uMsg = Msg && hWnd = obj.hwnd)
                return Callback(obj, wParam, lParam, uMsg)
        }
    }
}

/**
 * The extended class for the built-in `Gui.Button` class.
 * @method SetBackColor Set the button's background color
 * @example
 * btn := myGui.AddButton(, "SUPREME")
 * btn.SetBackColor(0xaa2031)
 */
class _BtnColor extends Gui.Button
{
    static __New() => super.Prototype.SetBackColor := ObjBindMethod(this, "SetBackColor")

    /**
     * @param {Gui.Button} myBtn omitted.
     * @param {integer} btnBgColor Button's background color. (RGB)
     * @param {integer} [colorBehindBtn] The color of the button's surrounding area. If omitted, if will be the same as `myGui.BackColor`. **(Usually let it be transparent looks better.)**
     * @param {integer} [roundedCorner] Specifies the rounded corner preference for the button. If omitted,        : 
     * > For Windows 11: Enabled. (value: 9)  
     * > For Windows 10: Disabled.   
     */
    static SetBackColor(myBtn, btnBgColor, colorBehindBtn?, roundedCorner?)
    {
        static BS_FLAT          := 0x8000
        static BS_BITMAP        := 0x0080
        static IS_WIN11         := (VerCompare(A_OSVersion, "10.0.22200") >= 0)
        static WM_CTLCOLORBTN   := 0x0135
        static NM_CUSTOMDRAW    := -12
        static WM_DESTROY       := 0x0002
        static WS_EX_COMPOSITED := 0x02000000
        static WS_CLIPSIBLINGS  := 0x04000000
        static BTN_STYLE        := (WS_CLIPSIBLINGS | BS_FLAT | BS_BITMAP)

        rcRgn       := unset
        clr         := IsNumber(btnBgColor) ? btnBgColor : ColorHex(btnBgColor)
        isDark      := IsColorDark(clr)
        hoverColor  := RgbToBgr(BrightenColor(clr, isDark ? 15 : -15))
        pushedColor := RgbToBgr(BrightenColor(clr, isDark ? -10 : 10))
        clr         := RgbToBgr(clr)
        btnBkColr   := (colorBehindBtn ?? !IS_WIN11) && RgbToBgr(ColorHex(myBtn.Gui.BackColor))
        hbrush      := (colorBehindBtn ?? !IS_WIN11) ? CreateSolidBrush(btnBkColr) : GetStockObject(5)

        myBtn.Gui.OnMessage(WM_CTLCOLORBTN, ON_WM_CTLCOLORBTN)

        if btnBkColr
            myBtn.Gui.OnEvent("Close", (*) => DeleteObject(hbrush))

        myBtn.Opt(BTN_STYLE (IsSet(colorBehindBtn) ? "Background" colorBehindBtn : "")) ;  
        myBtn.OnNotify(NM_CUSTOMDRAW, (gCtrl, lParam) => ON_NM_CUSTOMDRAW(gCtrl, lParam))
        SetWindowTheme(myBtn.hwnd, isDark ? "DarkMode_Explorer" : "Explorer")
        myBtn.Redraw()
        SetWindowPos(mybtn.hwnd, 0,,,,, 0x43)

        ON_WM_CTLCOLORBTN(GuiObj, wParam, lParam, Msg)
        {
            if (lParam != myBtn.hwnd || !myBtn.Focused)
                return

            SelectObject(wParam, hbrush)
            SetBkMode(wParam, 0)

            if (colorBehindBtn ?? !IS_WIN11) 
                SetBkColor(wParam, btnBkColr)

            return hbrush 
        }

        first := 1

        ON_NM_CUSTOMDRAW(gCtrl, lParam)
        {
            static CDDS_PREPAINT        := 0x1
            static CDDS_PREERASE        := 0x3
            static CDIS_HOT             := 0x40
            static CDRF_NOTIFYPOSTPAINT := 0x10
            static CDRF_SKIPPOSTPAINT   := 0x100
            static CDRF_SKIPDEFAULT     := 0x4
            static CDRF_NOTIFYPOSTERASE := 0x40
            static CDRF_DODEFAULT       := 0x0
            static DC_BRUSH             := GetStockObject(18)
            static DC_PEN               := GetStockObject(19)
            
            lpnmCD := StructFromPtr(NMCUSTOMDRAWINFO, lParam)

            if (lpnmCD.hdr.code != NM_CUSTOMDRAW ||lpnmCD.hdr.hwndFrom != gCtrl.hwnd)
                return CDRF_DODEFAULT
            
            switch lpnmCD.dwDrawStage {
            case CDDS_PREERASE:
            {
                SetBkMode(lpnmCD.hdc, 0)
                if (roundedCorner ?? IS_WIN11) {
                    rcRgn := CreateRoundRectRgn(lpnmCD.rc.left, lpnmCD.rc.top, lpnmCD.rc.right, lpnmCD.rc.bottom, roundedCorner ?? 9, roundedCorner ?? 9)
                    SetWindowRgn(gCtrl.hwnd, rcRgn, 1)
                    DeleteObject(rcRgn)
                }
                return CDRF_NOTIFYPOSTERASE 
            }
            case CDDS_PREPAINT: 
            {
                isPressed  := GetKeyState("LButton", "P")
                brushColor := (!(lpnmCD.uItemState & CDIS_HOT) || first ? clr : isPressed ? pushedColor : hoverColor)
                penColor   := (!first && gCtrl.Focused && !isPressed ? 0xFFFFFF : brushColor)
                
                SelectObject(lpnmCD.hdc, DC_BRUSH)
                SetDCBrushColor(lpnmCD.hdc, brushColor)
                SelectObject(lpnmCD.hdc, DC_PEN)
                SetDCPenColor(lpnmCD.hdc, penColor)

                rounded := !!(rcRgn ?? 0)

                if (!first && gCtrl.Focused && !isPressed) {
                    if !rounded {
                        lpnmCD.rc.left   += 1
                        lpnmCD.rc.top    += 1
                        lpnmCD.rc.right  -= 1
                        lpnmCD.rc.bottom -= 1
                    }
                    DrawFocusRect(lpnmCD.hdc, lpnmCD.rc)
                }

                if rounded {
                    RoundRect(lpnmCD.hdc, lpnmCD.rc.left, lpnmCD.rc.top, lpnmCD.rc.right - rounded, lpnmCD.rc.bottom - rounded, roundedCorner ?? 9, roundedCorner ?? 9)
                    DeleteObject(rcRgn)
                    rcRgn := ""                    
                }
                else FillRect(lpnmCD.hdc, lpnmCD.rc, DC_BRUSH)

                if first
                    first := 0

                SetWindowPos(mybtn.hwnd, 0,,,,, 0x4043)

                return CDRF_NOTIFYPOSTPAINT
            }}
            
            return CDRF_DODEFAULT
        }

        static RgbToBgr(color) => (IsInteger(color) ? ((Color >> 16) & 0xFF) | (Color & 0x00FF00) | ((Color & 0xFF) << 16) : NUMBER(RegExReplace(STRING(color), "Si)c?(?:0x)?(?<R>\w{2})(?<G>\w{2})(?<B>\w{2})", "0x${B}${G}${R}")))

        static CreateRoundRectRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, nWidthEllipse, nHeightEllipse) => DllCall('Gdi32\CreateRoundRectRgn', 'int', nLeftRect, 'int', nTopRect, 'int', nRightRect, 'int', nBottomRect, 'int', nWidthEllipse, 'int', nHeightEllipse, 'ptr')

        static CreateSolidBrush(crColor) => DllCall('Gdi32\CreateSolidBrush', 'uint', crColor, 'ptr')

        static ColorHex(clr) => Number((!InStr(clr, "0x") ? "0x" : "") clr)

        static DrawFocusRect(hDC, lprc) => DllCall("User32\DrawFocusRect", "ptr", hDC, "ptr", lprc, "int")

        static GetStockObject(fnObject) => DllCall('Gdi32\GetStockObject', 'int', fnObject, 'ptr')

        static SetWindowPos(hWnd, hWndInsertAfter, X := 0, Y := 0, cx := 0, cy := 0, uFlags := 0x40) => DllCall("User32\SetWindowPos", "ptr", hWnd, "ptr", hWndInsertAfter, "int", X, "int", Y, "int", cx, "int", cy, "uint", uFlags, "int")

        static SetDCPenColor(hdc, crColor) => DllCall('Gdi32\SetDCPenColor', 'ptr', hdc, 'uint', crColor, 'uint')

        static SetDCBrushColor(hdc, crColor) => DllCall('Gdi32\SetDCBrushColor', 'ptr', hdc, 'uint', crColor, 'uint')

        static SetWindowRgn(hWnd, hRgn, bRedraw) => DllCall("User32\SetWindowRgn", "ptr", hWnd, "ptr", hRgn, "int", bRedraw, "int")

        static DeleteObject(hObject) {
            DllCall('Gdi32\DeleteObject', 'ptr', hObject, 'int')
        }

        static FillRect(hDC, lprc, hbr) => DllCall("User32\FillRect", "ptr", hDC, "ptr", lprc, "ptr", hbr, "int")

        static IsColorDark(clr) => 
            ( (clr >> 16 & 0xFF) / 255 * 0.2126 
            + (clr >>  8 & 0xFF) / 255 * 0.7152 
            + (clr       & 0xFF) / 255 * 0.0722 < 0.5 )

        static RGB(R := 255, G := 255, B := 255) => ((R << 16) | (G << 8) | B)
        
        static BrightenColor(clr, perc := 5) => ((p := perc / 100 + 1), RGB(Round(Min(255, (clr >> 16 & 0xFF) * p)), Round(Min(255, (clr >> 8 & 0xFF) * p)), Round(Min(255, (clr & 0xFF) * p))))

        static RoundRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect, nWidth, nHeight) => DllCall('Gdi32\RoundRect', 'ptr', hdc, 'int', nLeftRect, 'int', nTopRect, 'int', nRightRect, 'int', nBottomRect, 'int', nWidth, 'int', nHeight, 'int')
        
        static SetTextColor(hdc, color) => DllCall("SetTextColor", "Ptr", hdc, "UInt", color)
        
        static SetWindowTheme(hwnd, appName, subIdList?) => DllCall("uxtheme\SetWindowTheme", "ptr", hwnd, "ptr", StrPtr(appName), "ptr", subIdList ?? 0)
        
        static SelectObject(hdc, hgdiobj) => DllCall('Gdi32\SelectObject', 'ptr', hdc, 'ptr', hgdiobj, 'ptr')
                
        static SetBkColor(hdc, crColor) => DllCall('Gdi32\SetBkColor', 'ptr', hdc, 'uint', crColor, 'uint')
        
        static SetBkMode(hdc, iBkMode) => DllCall('Gdi32\SetBkMode', 'ptr', hdc, 'int', iBkMode, 'int')
    }
}

; Example
/*
myGui := Gui()
myGui.SetFont("cWhite s20", "Segoe UI")
myGui.BackColor := 0x2c2c2c
btn := myGui.AddButton(, "SUPREME")
btn.SetBackColor(0xaa2031)
btn2 := myGui.AddButton(, "SUPREME")
btn2.SetBackColor(0xffd155)
btn3 := myGui.AddButton(, "SUPREME")
btn3.SetBackColor("0x7755ff", , 0)

myGui.Show("w280 h280")
keywords: gui, gui button, win32 gui, button color, gui button color, change color, button background color, v2 gui, gdi, customdraw, roundrect, WM_NOTIFY, v2.1, alpha
Last edited by NPerovic on 05 May 2024, 19:49, edited 1 time in total.
✨ Dark Theme for Everything
✨ Other Scripts

just me
Posts: 9511
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ColorButton.ahk | An extended method that lets you customize gui button background colors.

02 May 2024, 02:01

Moin,

running the code embedded in your v2.0 script with v2.0.13 on Win 10

Code: Select all

myGui := Gui()
myGui.SetFont("cWhite s24", "Segoe UI")
myGui.BackColor := 0x2c2c2c
btn := myGui.AddButton(, "SUPREME")
btn.SetBackColor(0xaa2031)
btn2 := myGui.AddButton(, "SUPREME")
btn2.SetBackColor(0xffd155)
myGui.Show("w300 h300")
i get:
Zwischenablage01.png
Zwischenablage01.png (10.11 KiB) Viewed 1152 times
ozzii
Posts: 482
Joined: 30 Oct 2013, 06:04

Re: ColorButton.ahk | An extended method that lets you customize gui button background colors.

02 May 2024, 03:51

Same like 'just me'
On Win 10 latest version/updates
But like this it's OK ;)
btn.SetBackColor(0xaa2031,, 0)
User avatar
NPerovic
Posts: 39
Joined: 31 Dec 2022, 01:25
Contact:

Re: ColorButton.ahk | An extended method that lets you customize gui button background colors.

03 May 2024, 13:58

just me wrote:
02 May 2024, 02:01
Moin,

running the code embedded in your v2.0 script with v2.0.13 on Win 10

Code: Select all

myGui := Gui()
myGui.SetFont("cWhite s24", "Segoe UI")
myGui.BackColor := 0x2c2c2c
btn := myGui.AddButton(, "SUPREME")
btn.SetBackColor(0xaa2031)
btn2 := myGui.AddButton(, "SUPREME")
btn2.SetBackColor(0xffd155)
myGui.Show("w300 h300")
i get:
Zwischenablage01.png

Thank you very much for the feedback:)

Could you please try this to see if it resolves the issue? I currently don't have access to a Windows 10 device to test it myself. Your assistance with testing would be immensely appreciated!


Code: Select all

class _BtnColor extends Gui.Button
{
    static __New() => super.Prototype.SetBackColor := ObjBindMethod(this, "SetBackColor")

    /**
     * @param {Gui.Button} myBtn omitted.
     * @param {integer} btnBgColor Button's background color. (RGB)
     * @param {integer} [colorBehindBtn] The color of the button's surrounding area. If omitted, if will be the same as `myGui.BackColor`. **(Usually let it be transparent looks better.)**
     * @param {integer} [roundedCorner] Specifies the rounded corner preference for the button. If omitted,        : 
     * > For Windows 11: Enabled. (value: 9)  
     * > For Windows 10: Disabled.   
     */
    static SetBackColor(myBtn, btnBgColor, colorBehindBtn?, roundedCorner?)
    {
        static BS_FLAT          := 0x8000
        static BS_BITMAP        := 0x0080
        static IS_WIN11         := (VerCompare(A_OSVersion, "10.0.22200") >= 0)
        static WM_CTLCOLORBTN   := 0x0135
        static NM_CUSTOMDRAW    := -12
        static WM_DESTROY       := 0x0002
        static WS_EX_COMPOSITED := 0x02000000
        static WS_CLIPSIBLINGS  := 0x04000000

        rcRgn       := unset
        clr         := IsNumber(btnBgColor) ? btnBgColor : ColorHex(btnBgColor)
        isDark      := IsColorDark(clr)
        hoverColor  := RgbToBgr(BrightenColor(clr, isDark ? 15 : -15))
        pushedColor := RgbToBgr(BrightenColor(clr, isDark ? -10 : 10))
        clr         := RgbToBgr(clr)
        btnBkColr   := (colorBehindBtn ?? !IS_WIN11) && RgbToBgr(ColorHex(myBtn.Gui.BackColor))
        hbrush      := (colorBehindBtn ?? !IS_WIN11) ? CreateSolidBrush(btnBkColr) : GetStockObject(5)

        myBtn.Gui.Opt("+" WS_CLIPSIBLINGS)
        myBtn.Gui.OnMessage(WM_CTLCOLORBTN, ON_WM_CTLCOLORBTN)

        if btnBkColr
            myBtn.Gui.OnEvent("Close", (*) => DeleteObject(hbrush))

        myBtn.Opt("+" (WS_CLIPSIBLINGS | BS_FLAT | BS_BITMAP)) ; 
        myBtn.OnNotify(NM_CUSTOMDRAW, (gCtrl, lParam) => ON_NM_CUSTOMDRAW(gCtrl, lParam))
        SetWindowTheme(myBtn.hwnd, isDark ? "DarkMode_Explorer" : "Explorer")

        ON_WM_CTLCOLORBTN(GuiObj, wParam, lParam, Msg)
        {
            Critical(-1)

            if (lParam != myBtn.hwnd) 
                return

            if (colorBehindBtn ?? !IS_WIN11) {
                SelectObject(wParam, hbrush)
                SetBkMode(wParam, 0)
                SetBkColor(wParam, btnBkColr)
            }

            return hbrush 
        }

        first := 1

        ON_NM_CUSTOMDRAW(gCtrl, lParam)
        {
            static CDDS_PREPAINT        := 0x1
            static CDDS_PREERASE        := 0x3
            static CDIS_HOT             := 0x40
            static CDRF_NOTIFYPOSTPAINT := 0x10
            static CDRF_SKIPPOSTPAINT   := 0x100
            static CDRF_SKIPDEFAULT     := 0x4
            static CDRF_NOTIFYPOSTERASE := 0x40
            static CDRF_DODEFAULT       := 0x0
            static DC_BRUSH             := GetStockObject(18)
            static DC_PEN               := GetStockObject(19)
            
            Critical(-1)

            lpnmCD := StructFromPtr(NMCUSTOMDRAWINFO, lParam)

            if (lpnmCD.hdr.code != NM_CUSTOMDRAW ||lpnmCD.hdr.hwndFrom != gCtrl.hwnd)
                return CDRF_DODEFAULT
            
            switch lpnmCD.dwDrawStage {
            case CDDS_PREERASE:
            {
                if (roundedCorner ?? IS_WIN11) {
                    rcRgn := CreateRoundRectRgn(lpnmCD.rc.left, lpnmCD.rc.top, lpnmCD.rc.right, lpnmCD.rc.bottom, roundedCorner ?? 9, roundedCorner ?? 9)
                    SetWindowRgn(gCtrl.hwnd, rcRgn, 1)
                }
                SetBkMode(lpnmCD.hdc, 0)
                return CDRF_NOTIFYPOSTERASE 
            }
            case CDDS_PREPAINT: 
            {
                isPressed  := GetKeyState("LButton", "P")
                brushColor := (!(lpnmCD.uItemState & CDIS_HOT) || first ? clr : isPressed ? pushedColor : hoverColor)

                SelectObject(lpnmCD.hdc, DC_BRUSH)
                SetDCBrushColor(lpnmCD.hdc, brushColor)
                SelectObject(lpnmCD.hdc, DC_PEN)
                SetDCPenColor(lpnmCD.hdc, !first && gCtrl.Focused && !isPressed ? 0xFFFFFF : brushColor)

                rounded := !!(rcRgn ?? 0)

                if (!first && gCtrl.Focused && !isPressed) {
                    if !rounded {
                        lpnmCD.rc.left   += 1
                        lpnmCD.rc.top    += 1
                        lpnmCD.rc.right  -= 1
                        lpnmCD.rc.bottom -= 1
                    }
                    DrawFocusRect(lpnmCD.hdc, lpnmCD.rc)
                }

                if rounded {
                    RoundRect(lpnmCD.hdc, lpnmCD.rc.left, lpnmCD.rc.top, lpnmCD.rc.right - rounded, lpnmCD.rc.bottom - rounded, roundedCorner ?? 9, roundedCorner ?? 9)
                    DeleteObject(rcRgn)
                    rcRgn := ""                    
                }
                else {
                    FillRect(lpnmCD.hdc, lpnmCD.rc, DC_BRUSH)
                }

                if first
                    first := 0

                SetWindowPos(mybtn.hwnd, 0,,,,, 0x4043)

                return CDRF_NOTIFYPOSTPAINT
            }}
            
            return CDRF_DODEFAULT
        }

        static RgbToBgr(color) => (IsInteger(color) ? ((Color >> 16) & 0xFF) | (Color & 0x00FF00) | ((Color & 0xFF) << 16) : NUMBER(RegExReplace(STRING(color), "Si)c?(?:0x)?(?<R>\w{2})(?<G>\w{2})(?<B>\w{2})", "0x${B}${G}${R}")))

        static CreateRoundRectRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, nWidthEllipse, nHeightEllipse) => DllCall('Gdi32\CreateRoundRectRgn', 'int', nLeftRect, 'int', nTopRect, 'int', nRightRect, 'int', nBottomRect, 'int', nWidthEllipse, 'int', nHeightEllipse, 'ptr')

        static CreateSolidBrush(crColor) => DllCall('Gdi32\CreateSolidBrush', 'uint', crColor, 'ptr')

        static ColorHex(clr) => Number((!InStr(clr, "0x") ? "0x" : "") clr)

        static DrawFocusRect(hDC, lprc) => DllCall("User32\DrawFocusRect", "ptr", hDC, "ptr", lprc, "int")

        static GetStockObject(fnObject) => DllCall('Gdi32\GetStockObject', 'int', fnObject, 'ptr')

        static SetWindowPos(hWnd, hWndInsertAfter, X := 0, Y := 0, cx := 0, cy := 0, uFlags := 0x40) => DllCall("User32\SetWindowPos", "ptr", hWnd, "ptr", hWndInsertAfter, "int", X, "int", Y, "int", cx, "int", cy, "uint", uFlags, "int")

        static SetDCPenColor(hdc, crColor) => DllCall('Gdi32\SetDCPenColor', 'ptr', hdc, 'uint', crColor, 'uint')

        static SetDCBrushColor(hdc, crColor) => DllCall('Gdi32\SetDCBrushColor', 'ptr', hdc, 'uint', crColor, 'uint')

        static SetWindowRgn(hWnd, hRgn, bRedraw) => DllCall("User32\SetWindowRgn", "ptr", hWnd, "ptr", hRgn, "int", bRedraw, "int")

        static DeleteObject(hObject) {
            DllCall('Gdi32\DeleteObject', 'ptr', hObject, 'int')
        }

        static FillRect(hDC, lprc, hbr) => DllCall("User32\FillRect", "ptr", hDC, "ptr", lprc, "ptr", hbr, "int")

        static IsColorDark(clr) => 
            ( (clr >> 16 & 0xFF) / 255 * 0.2126 
            + (clr >>  8 & 0xFF) / 255 * 0.7152 
            + (clr       & 0xFF) / 255 * 0.0722 < 0.5 )

        static RGB(R := 255, G := 255, B := 255) => ((R << 16) | (G << 8) | B)
        
        static BrightenColor(clr, perc := 5) => ((p := perc / 100 + 1), RGB(Round(Min(255, (clr >> 16 & 0xFF) * p)), Round(Min(255, (clr >> 8 & 0xFF) * p)), Round(Min(255, (clr & 0xFF) * p))))

        static RoundRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect, nWidth, nHeight) => DllCall('Gdi32\RoundRect', 'ptr', hdc, 'int', nLeftRect, 'int', nTopRect, 'int', nRightRect, 'int', nBottomRect, 'int', nWidth, 'int', nHeight, 'int')
        
        static SetTextColor(hdc, color) => DllCall("SetTextColor", "Ptr", hdc, "UInt", color)
        
        static SetWindowTheme(hwnd, appName, subIdList?) => DllCall("uxtheme\SetWindowTheme", "ptr", hwnd, "ptr", StrPtr(appName), "ptr", subIdList ?? 0)
        
        static SelectObject(hdc, hgdiobj) => DllCall('Gdi32\SelectObject', 'ptr', hdc, 'ptr', hgdiobj, 'ptr')
                
        static SetBkColor(hdc, crColor) => DllCall('Gdi32\SetBkColor', 'ptr', hdc, 'uint', crColor, 'uint')
        
        static SetBkMode(hdc, iBkMode) => DllCall('Gdi32\SetBkMode', 'ptr', hdc, 'int', iBkMode, 'int')
    }
}
✨ Dark Theme for Everything
✨ Other Scripts

just me
Posts: 9511
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ColorButton.ahk | An extended method that lets you customize gui button background colors.

04 May 2024, 01:49

Hi @NPerovic, I tested. Result on Win 10:
Zwischenablage01.png
Zwischenablage01.png (10.13 KiB) Viewed 852 times
Thanks for sharing this script. It never occurred to me that buttons support custom draw.
just me
Posts: 9511
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ColorButton.ahk | An extended method that lets you customize gui button background colors.

04 May 2024, 01:58

BTW:

Code: Select all

class NMCUSTOMDRAWINFO
{
    static Call(ptr)
    {
        return {
            hdr: {
                hwndFrom: NumGet(ptr, 0 ,"uptr"),
                idFrom  : NumGet(ptr, 8 ,"uptr"),
                code    : NumGet(ptr, 16 ,"int")
            },
            dwDrawStage: NumGet(ptr, 24, "uint"),
            hdc        : NumGet(ptr, 32, "uptr"),
            rc         : RECT(
                NumGet(ptr, 40, "uint"),
                NumGet(ptr, 44, "uint"),
                NumGet(ptr, 48, "int"),
                NumGet(ptr, 52, "int")
            ),
            dwItemSpec : NumGet(ptr, 56, "uptr"),
            uItemState : NumGet(ptr, 64, "int"),
            lItemlParam: NumGet(ptr, 72, "iptr")
        }
That's only for AHK64 (A_PtrSize = 8)
User avatar
NPerovic
Posts: 39
Joined: 31 Dec 2022, 01:25
Contact:

Re: ColorButton.ahk | An extended method that lets you customize gui button background colors.

05 May 2024, 19:51

just me wrote:
04 May 2024, 01:58
BTW:

Code: Select all

class NMCUSTOMDRAWINFO
{
    static Call(ptr)
    {
        return {
            hdr: {
                hwndFrom: NumGet(ptr, 0 ,"uptr"),
                idFrom  : NumGet(ptr, 8 ,"uptr"),
                code    : NumGet(ptr, 16 ,"int")
            },
            dwDrawStage: NumGet(ptr, 24, "uint"),
            hdc        : NumGet(ptr, 32, "uptr"),
            rc         : RECT(
                NumGet(ptr, 40, "uint"),
                NumGet(ptr, 44, "uint"),
                NumGet(ptr, 48, "int"),
                NumGet(ptr, 52, "int")
            ),
            dwItemSpec : NumGet(ptr, 56, "uptr"),
            uItemState : NumGet(ptr, 64, "int"),
            lItemlParam: NumGet(ptr, 72, "iptr")
        }
That's only for AHK64 (A_PtrSize = 8)
Right! Thanks for pointing this out. I've updated the code for the structure for v2.0 users.
✨ Dark Theme for Everything
✨ Other Scripts

sashaatx
Posts: 342
Joined: 27 May 2021, 08:27
Contact:

Re: ColorButton.ahk | An extended method that lets you customize gui button background colors.

06 May 2024, 10:44

NPerovic wrote:
05 May 2024, 19:51
just me wrote:
04 May 2024, 01:58
BTW:

Code: Select all

class NMCUSTOMDRAWINFO
{
    static Call(ptr)
    {
        return {
            hdr: {
                hwndFrom: NumGet(ptr, 0 ,"uptr"),
                idFrom  : NumGet(ptr, 8 ,"uptr"),
                code    : NumGet(ptr, 16 ,"int")
            },
            dwDrawStage: NumGet(ptr, 24, "uint"),
            hdc        : NumGet(ptr, 32, "uptr"),
            rc         : RECT(
                NumGet(ptr, 40, "uint"),
                NumGet(ptr, 44, "uint"),
                NumGet(ptr, 48, "int"),
                NumGet(ptr, 52, "int")
            ),
            dwItemSpec : NumGet(ptr, 56, "uptr"),
            uItemState : NumGet(ptr, 64, "int"),
            lItemlParam: NumGet(ptr, 72, "iptr")
        }
That's only for AHK64 (A_PtrSize = 8)
Right! Thanks for pointing this out. I've updated the code for the structure for v2.0 users.
hey big fan of your stuff.

I do a lot of gui work,
https://github.com/samfisherirl/Easy-Auto-GUI-for-AHK-v2 and
https://github.com/samfisherirl/Useful-AHK-v2-Libraries-and-Classes?tab=readme-ov-file#gui-libraries

I worked with GuiResizer for all of my commercial application guis due to various resolutions, and various displays for the same application.

I wrote a class that works with ImageButton.ahk, but Im not a big knower of DLL calls for default win32/C++ stuff.

See bottom gif and here for an example class for resizable image buttons: https://github.com/samfisherirl/GuiResizer-Addons/blob/main/ButtonStyle.ahk

I'd like to incorporate your solution into the GuiResizer, allowing the button size to be changed on the fly. I am not looking for you to write anything, if you could do me the courtesy of pointing me to the aspect of your script that executes the color change where I can tinker and attempt to implement it into a resizable design.

Let me know if you have any questions and thanks in advance.
Attachments
292956102-b30eccaa-faa9-42a7-ae3a-ef345383c1b8.gif
292956102-b30eccaa-faa9-42a7-ae3a-ef345383c1b8.gif (1023.05 KiB) Viewed 563 times
https://github.com/samfisherirl
? /Easy-Auto-GUI-for-AHK-v2 ? /Useful-AHK-v2-Libraries-and-Classes : /Pulovers-Macro-Creator-for-AHKv2 :
User avatar
kczx3
Posts: 1648
Joined: 06 Oct 2015, 21:39

Re: [2024/05/06] ColorButton.ahk | An extended method that lets you customize gui button background colors.

06 May 2024, 11:01

As far as I can tell, nothing of the code presented in this thread pertains to the size of the button. It merely colors the button as it is sized.
sashaatx
Posts: 342
Joined: 27 May 2021, 08:27
Contact:

Re: [2024/05/06] ColorButton.ahk | An extended method that lets you customize gui button background colors.

06 May 2024, 11:19

kczx3 wrote:
06 May 2024, 11:01
As far as I can tell, nothing of the code presented in this thread pertains to the size of the button. It merely colors the button as it is sized.
sh*t youre right. this worked just fine, resizer and dark mode. Not sure why last time I tried, something conflicted.

Code: Select all

#Requires Autohotkey v2
#SingleInstance force
#Include <GuiReSizer>
#Include <ColorButton>
myCtrls := {}
myGui := Gui(), myGui.Opt("+Resize +MinSize250x150")
myGui.OnEvent("Size", GuiReSizer)
myCtrls.ButtonOK := myGui.Add("Button", "", "&OK").SetBackColor("0x7755ff", , 0)
pushToResizer(myCtrls.ButtonOK, .373, .153, .573, .727)


pushToResizer(ctrl, xp, yp, wp, hp)
{
	ctrl.xp := xp 
	ctrl.yp := yp 
	ctrl.wp := wp 
	ctrl.hp := hp 
}

myGui.Show()
https://github.com/samfisherirl
? /Easy-Auto-GUI-for-AHK-v2 ? /Useful-AHK-v2-Libraries-and-Classes : /Pulovers-Macro-Creator-for-AHKv2 :
sashaatx
Posts: 342
Joined: 27 May 2021, 08:27
Contact:

Re: ColorButton.ahk | An extended method that lets you customize gui button background colors.

07 May 2024, 04:25

NPerovic wrote:
05 May 2024, 19:51
just me wrote:
04 May 2024, 01:58
BTW:

Code: Select all

class NMCUSTOMDRAWINFO
{
    static Call(ptr)
    {
        return {
            hdr: {
                hwndFrom: NumGet(ptr, 0 ,"uptr"),
                idFrom  : NumGet(ptr, 8 ,"uptr"),
                code    : NumGet(ptr, 16 ,"int")
            },
            dwDrawStage: NumGet(ptr, 24, "uint"),
            hdc        : NumGet(ptr, 32, "uptr"),
            rc         : RECT(
                NumGet(ptr, 40, "uint"),
                NumGet(ptr, 44, "uint"),
                NumGet(ptr, 48, "int"),
                NumGet(ptr, 52, "int")
            ),
            dwItemSpec : NumGet(ptr, 56, "uptr"),
            uItemState : NumGet(ptr, 64, "int"),
            lItemlParam: NumGet(ptr, 72, "iptr")
        }
That's only for AHK64 (A_PtrSize = 8)
Right! Thanks for pointing this out. I've updated the code for the structure for v2.0 users.
personal choice, but I try to return ctrls back from methods but this may be bad practice for some reason

Code: Select all

	;line 232 
	        static SelectObject(hdc, hgdiobj) => DllCall('Gdi32\SelectObject', 'ptr', hdc, 'ptr', hgdiobj, 'ptr')
                
        static SetBkColor(hdc, crColor) => DllCall('Gdi32\SetBkColor', 'ptr', hdc, 'uint', crColor, 'uint')
        
        static SetBkMode(hdc, iBkMode) => DllCall('Gdi32\SetBkMode', 'ptr', hdc, 'int', iBkMode, 'int')
        
        return myBtn
    }
}
 
; now
G.btn := G.Add("Button", "", "&OK").SetBgColor(0x000000)
https://github.com/samfisherirl
? /Easy-Auto-GUI-for-AHK-v2 ? /Useful-AHK-v2-Libraries-and-Classes : /Pulovers-Macro-Creator-for-AHKv2 :
User avatar
NPerovic
Posts: 39
Joined: 31 Dec 2022, 01:25
Contact:

Re: ColorButton.ahk | An extended method that lets you customize gui button background colors.

08 May 2024, 15:07

sashaatx wrote:
06 May 2024, 10:44
hey big fan of your stuff.

I do a lot of gui work,
https://github.com/samfisherirl/Easy-Auto-GUI-for-AHK-v2 and
https://github.com/samfisherirl/Useful-AHK-v2-Libraries-and-Classes?tab=readme-ov-file#gui-libraries

I worked with GuiResizer for all of my commercial application guis due to various resolutions, and various displays for the same application.

I wrote a class that works with ImageButton.ahk, but Im not a big knower of DLL calls for default win32/C++ stuff.

See bottom gif and here for an example class for resizable image buttons: https://github.com/samfisherirl/GuiResizer-Addons/blob/main/ButtonStyle.ahk

I'd like to incorporate your solution into the GuiResizer, allowing the button size to be changed on the fly. I am not looking for you to write anything, if you could do me the courtesy of pointing me to the aspect of your script that executes the color change where I can tinker and attempt to implement it into a resizable design.

Let me know if you have any questions and thanks in advance.

Thank you for reaching out and for your kind words! I’m thrilled to hear that you’re a fan of my work. 😊

I often recommend your “Easy Auto GUI for AHK v2” to beginners who are looking to build GUIs with AHK, and it’s great to see such valuable resources being shared within the community.👍

Regarding the button resizing issue, I noticed in your subsequent reply that it seems to be resolved now.

Should you have any further questions or suggestions, please do not hesitate to let me know. 😊
✨ Dark Theme for Everything
✨ Other Scripts


Return to “Scripts and Functions (v2)”

Who is online

Users browsing this forum: OpalMonkey and 29 guests