33 * @file ColorButton.ahk
44 * @author Nikola Perovic
55 * @link https://github.com/nperovic/ColorButton.ahk
6- * @date 2024/04/28
7- * @version 1.0.1
6+ * @date 2024/04/29
7+ * @version 1.1.0
88 ***********************************************************************/
99
1010#Requires AutoHotkey v2.1-alpha.9
@@ -37,14 +37,19 @@ class NMCUSTOMDRAWINFO {
3737 * btn := myGui.AddButton(, "SUPREME")
3838 * btn.SetBackColor(0xaa2031)
3939 */
40- class _BtnColor extends Gui .Button {
40+ class _BtnColor extends Gui .Button
41+ {
4142 static __New() => super.Prototype.SetBackColor := ObjBindMethod(this, " SetBackColor" )
4243
4344 /**
44- * @param {Gui.Button} myBtn
45- * @param {integer} bkColor
45+ * @param {Gui.Button} myBtn omitted.
46+ * @param {integer} btnBgColor Button's background color.
47+ * @param {integer} [colorBehindBtn] The color of the button's surrounding area. If omitted, if will be the same as `myGui.BackColor`.
48+ * @param {integer} [roundedCorner] Specifies the rounded corner preference for the button. If omitted, :
49+ * > For Windows 11: Enabled. (value: 9)
50+ * > For Windows 10: Disabled.
4651 */
47- static SetBackColor(myBtn, bkColor )
52+ static SetBackColor(myBtn, btnBgColor, colorBehindBtn?, roundedCorner? )
4853 {
4954 static IS_WIN11 := (VerCompare(A_OSVersion , " 10.0.22200" ) >= 0 )
5055 static WM_CTLCOLORBTN := 0x0135
@@ -54,57 +59,64 @@ class _BtnColor extends Gui.Button {
5459 static WS_CLIPCHILDREN := 0x02000000
5560 static WS_CLIPSIBLINGS := 0x04000000
5661
57- clr := (IsNumber(bkColor ) ? bkColor : Number((! InStr (bkColor , " 0x" ) ? " 0x" : "" ) bkColor ))
62+ clr := (IsNumber(btnBgColor ) ? btnBgColor : Number((! InStr (btnBgColor , " 0x" ) ? " 0x" : "" ) btnBgColor ))
5863 hoverColor := BrightenColor(clr, 10 )
59- hbrush := CreateSolidBrush(ColorHex(myBtn.Gui .BackColor))
64+ btnBkColr := ColorHex(colorBehindBtn ?? myBtn.Gui .BackColor)
65+ hbrush := CreateSolidBrush(btnBkColr)
6066
61- myBtn.Gui .Opt(" +E" WS_EX_COMPOSITED " + " WS_CLIPCHILDREN )
67+ myBtn.Gui .Opt(" +E" WS_EX_COMPOSITED )
6268 myBtn.Gui .OnEvent(" Close" , (* ) => (DeleteObject(hbrush), unset))
6369
6470 myBtn.Opt(" +" WS_CLIPSIBLINGS)
6571 SetWindowTheme(myBtn.hwnd, IsColorDark(clr) ? " DarkMode_Explorer" : " Explorer" )
6672 myBtn.Redraw()
6773
6874 myBtn.Gui .OnMessage (WM_CTLCOLORBTN, (GuiObj, wParam, * ) {
69- Critical (- 1 )
70- SelectObject(wParam, hbrush)
7175 SetBkMode(wParam, 0 )
72- SetBkColor(wParam, ColorHex(GuiObj.BackColor))
76+ SelectObject(wParam, hbrush)
77+ SetBkColor(wParam, btnBkColr)
7378 return hbrush
74- })
79+ }, - 1 )
7580
7681 myBtn.OnNotify(NM_CUSTOMDRAW, (gCtrl, lParam) {
7782 static CDDS_PREPAINT := 1
83+ static CDDS_PREERASE := 0x3
7884 static CDIS_HOT := 0x0040
7985 static DC_BRUSH := 18
8086 static DC_PEN := 19
8187
82- Critical (- 1 )
83-
8488 /** @type {NMCUSTOMDRAWINFO} */
8589 lpnmCD := StructFromPtr(NMCUSTOMDRAWINFO, lParam)
8690
87- if (lpnmCD.hdr.code != NM_CUSTOMDRAW || lpnmCD.hdr.hwndFrom != gCtrl.hwnd || lpnmCD.dwDrawStage != CDDS_PREPAINT)
91+ if (lpnmCD.hdr.code != NM_CUSTOMDRAW || lpnmCD.hdr.hwndFrom != gCtrl.hwnd || ( lpnmCD.dwDrawStage != CDDS_PREPAINT) )
8892 return
8993
94+ Critical()
95+
9096 brushColor := RgbToBgr(GetKeyState("LButton", "P") || !(lpnmCD.uItemState & CDIS_HOT) ? clr : hoverColor )
9197
98+ if (IS_WIN11 || IsSet(roundedCorner)) {
99+ rcRgn := CreateRoundRectRgn(lpnmCD.rc.left, lpnmCD.rc.top, lpnmCD.rc.right, lpnmCD.rc.bottom, roundedCorner ?? 9, roundedCorner ?? 9)
100+ SetWindowRgn(lpnmCD.hdr.hwndFrom, rcRgn, 0)
101+ }
102+
92103 SetBkMode(lpnmCD.hdc, 0)
93104 SetDCBrushColor(lpnmCD.hdc, brushColor)
94- SelectObject(lpnmCD.hdc, bru := GetStockObject(DC_BRUSH))
95105 SetDCPenColor(lpnmCD.hdc, brushColor)
106+ SelectObject(lpnmCD.hdc, bru := GetStockObject(DC_BRUSH))
96107 SelectObject(lpnmCD.hdc, GetStockObject(DC_PEN))
97-
98- if IS_WIN11
99- RoundRect(lpnmCD.hdc, lpnmCD.rc.left, lpnmCD.rc.top, lpnmCD.rc.right, lpnmCD.rc.bottom, 8, 8)
100- else
101- FillRect(lpnmCD.hdc, lpnmCD.rc, bru)
108+ FillRect(lpnmCD.hdc, lpnmCD.rc, bru)
109+
110+ if IsSet(rcRgn)
111+ DeleteObject(rcRgn)
102112
103113 return true
104114 })
105115
106116 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}")))
107117
118+ CreateRoundRectRgn(nLeftRect, nTopRect, nRightRect, nBottomRect, nWidthEllipse, nHeightEllipse) => DllCall('Gdi32\CreateRoundRectRgn', 'int', nLeftRect, 'int', nTopRect, 'int', nRightRect, 'int', nBottomRect, 'int', nWidthEllipse, 'int', nHeightEllipse, 'ptr')
119+
108120 CreateSolidBrush(crColor) => DllCall('Gdi32\CreateSolidBrush', 'uint', crColor, 'ptr')
109121
110122 ColorHex(clr) => Number((!InStr(clr, "0x") ? "0x" : "") clr)
@@ -115,6 +127,8 @@ class _BtnColor extends Gui.Button {
115127
116128 SetDCBrushColor(hdc, crColor) => DllCall('Gdi32\SetDCBrushColor', 'ptr', hdc, 'uint', crColor, 'uint')
117129
130+ SetWindowRgn(hWnd, hRgn, bRedraw) => DllCall("User32\SetWindowRgn", "ptr", hWnd, "ptr", hRgn, "int", bRedraw, "int")
131+
118132 DeleteObject(hObject) => DllCall('Gdi32\DeleteObject', 'ptr', hObject, 'int')
119133
120134 FillRect(hDC, lprc, hbr) => DllCall("User32\FillRect", "ptr", hDC, "ptr", lprc, "ptr", hbr, "int")
0 commit comments