By
kurtykurtyboy
GuiFlatButton is a UDF to easily create regular buttons with different colors for background, foreground, border, hover, focus, etc..
This started as an effort to change the background color of a button and eventually grew into a full UDF.
If you've looked around forums for changing button background colors, you have probably noticed that each proposed workaround has its own set of issues/side-effects. The answers usually circle back to 'use ownerdrawn buttons' and 'not worth it'. Well, now it is possible for anyone to easily create ownerdrawn buttons - totally worth it!
Some issues with other workarounds such as drawing with GDI+ or using a colored label as a 'button':
Not 'real' buttons so you lose built-in functionality that windows gives to buttons
Messy / inefficient code in the main while loop to check for mouse position
Slow to respond to click, paint, etc...
Having to deal with GUIRegisterMsg messages
Not straight-forward to implement
GuiFlatButton is not a workaround; it is a technique to respond to Windows' built-in owner-drawn button events.
With minimal effort, we can now create true simple colored buttons.
The idea is to create an owner-drawn button using GUICtrlCreateButton then subclass the GUI and controls to handle the button-specific events to paint it however we want.
This UDF magically does all of this for us! No need to worry about event handling or main while loop logic.
How to use
It couldn't be any easier! Simply create a new button using the familiar syntax. This creates an ownerdrawn button with default colors.
$mybutton1 = GuiFlatButton_Create("Button 1", 78, 20, 120, 40)
If you want to change the background and text colors:
GuiFlatButton_SetBkColor(-1, 0x5555FF)
GuiFlatButton_SetColor(-1, 0xFFFFFF)
Advanced Usage
Set background/text/border all at once
GuiFlatButton_SetColors(-1, 0x0000FF, 0xFFFFFF, 0x9999FF)
Set ALL colors for ALL button states! (normal, focus, hover, selected)
Local $aColorsEx = [0x0000FF, 0xFFFFFF, -2, 0x4444FF, 0xFFFFFF, 0xAAAAFF, 0x6666FF, 0xFFFFFF, 0xCCCCFF, 0x0000EE, 0xFFFFFF, 0x7777EE]
GuiFlatButton_SetColorsEx(-1, $aColorsEx)
Set default colors to apply to any future buttons
;set colors
GuiFlatButton_SetDefaultColors(0x0000FF, 0xFFFFFF, 0x9999FF)
;create buttons
$mybutton1 = GuiFlatButton_Create("Button 1", 12, 20, 120, 40)
$mybutton2 = GuiFlatButton_Create("Button 2", 143, 20, 120, 40)
Set ALL color defaults
;set colors
Local $aColorsEx = [0x0000FF, 0xFFFFFF, -2, 0x4444FF, 0xFFFFFF, 0xAAAAFF, 0x6666FF, 0xFFFFFF, 0xCCCCFF, 0x0000EE, 0xFFFFFF, 0x7777EE]
GuiFlatButton_SetDefaultColorsEx($aColorsEx)
;create buttons
$mybutton1 = GuiFlatButton_Create("Button 1", 12, 20, 120, 40)
$mybutton2 = GuiFlatButton_Create("Button 2", 143, 20, 120, 40)
Available Functions
Simple Example
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include "GuiFlatButton.au3"
Example()
;GUI with one button
Func Example()
Local $hGUI, $mybutton1
$hGUI = GUICreate("GuiFlatButton Ex0", 275, 120)
GUISetBkColor(0x333333)
Local $idLabel = GUICtrlCreateLabel("Click the button", 10, 100, 150, 30)
GUICtrlSetColor(-1, 0xFFFFFF)
;create new button then set the background and foreground colors
$mybutton1 = GuiFlatButton_Create("Button 1" & @CRLF & "Line 2", 78, 20, 120, 40, $BS_MULTILINE)
GuiFlatButton_SetBkColor(-1, 0x5555FF)
GuiFlatButton_SetColor(-1, 0xFFFFFF)
GUISetState(@SW_SHOW, $hGUI)
Local $i = 0
Local $iMsg
While 1
$iMsg = GUIGetMsg()
Switch $iMsg
Case $GUI_EVENT_CLOSE
ExitLoop
Case $mybutton1
$i += 1
GUICtrlSetData($idLabel, $i)
ConsoleWrite($i & @CRLF)
EndSwitch
Sleep(10)
WEnd
GUIDelete()
EndFunc ;==>Example
Menu/Toolbar Example
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include "GuiFlatButton.au3"
Example()
;Example GUI with toolbar
Func Example()
Local $hGUI, $idLabel, $aButtons, $iTbSize
$hGUI = GUICreate("GuiFlatButton Ex2", 300, 200)
GUISetBkColor(0x444444)
$idLabel = GUICtrlCreateLabel("Click a button", 10, 180, 150, 30)
GUICtrlSetColor(-1, 0xFFFFFF)
$aButtons = createToolbar()
$iTbSize = UBound($aButtons)
GUISetState(@SW_SHOW, $hGUI)
Local $i = 0
Local $iMsg
While 1
$iMsg = GUIGetMsg()
Switch $iMsg
Case $GUI_EVENT_CLOSE
ExitLoop
Case $aButtons[0] To $aButtons[$iTbSize - 1]
ConsoleWrite("1")
GUICtrlSetData($idLabel, GuiFlatButton_Read($iMsg))
EndSwitch
Sleep(10)
WEnd
GUIDelete()
EndFunc ;==>Example
Func createToolbar()
Local $aButtons[6]
Local $bkColor = 0x777777
Local $textColor = 0xFFFFFF
Local $borderColor = 0x999999
Local $aBtnClrs[12] = [0x777777, 0xFFFFFF, $GUI_BKCOLOR_TRANSPARENT, 0x888888, 0xFFFFFF, $GUI_BKCOLOR_TRANSPARENT, 0x999999, 0xFFFFFF, $GUI_BKCOLOR_TRANSPARENT, 0x666666, 0xFFFFFF, $GUI_BKCOLOR_TRANSPARENT]
For $i = 0 To UBound($aButtons) - 1
$aButtons[$i] = GuiFlatButton_Create("B" & $i, $i * 50, 0, 50, 17)
GuiFlatButton_SetColorsEx($aButtons[$i], $aBtnClrs)
Next
Return $aButtons
EndFunc ;==>createToolbar
Icon Example
You can even easily add icons to your buttons -- just create a new button and send it an icon!
#include <GDIPlus.au3>
#include "GuiFlatButton.au3"
Example()
;buttons with Icon images
Func Example()
;get images for demonstration
_GDIPlus_Startup() ;initialize GDI+
Local $hIcon = _WinAPI_ShellExtractIcon(@SystemDir & '\shell32.dll', 258, 24, 24) ;extract the 'Save' icon
Local $hBitmap = _GDIPlus_BitmapCreateFromHICON($hIcon) ;Create Bitmap from Icon (for demonstration)
Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap) ;Create HBitmap from Bitmap
_GDIPlus_BitmapDispose($hBitmap) ;dispose the bitmap
_GDIPlus_Shutdown() ;done with GDI+
Local $hGUI = GUICreate("GuiFlatButton Ex5", 255, 400)
GUISetBkColor(0xEEEEEE)
;set default colors of future buttons
Local $aColorsEx = _
[0xE2E5E8, 0X000000, 0x888888, _ ; normal : Background, Text, Border
0xE2E5E8, 0X000000, 0x333333, _ ; focus : Background, Text, Border
0xE8E8E8, 0X000000, 0x666666, _ ; hover : Background, Text, Border
0xDDDDDD, 0X000000, 0xAAAAAA] ; selected : Background, Text, Border
GuiFlatButton_SetDefaultColorsEx($aColorsEx)
;normal button with icon
$label1 = GUICtrlCreateLabel( "$BS_TOOLBUTTON -->", 5, 10)
GUICtrlSetBkColor(-1, $GUI_BKCOLOR_TRANSPARENT)
Local $mybutton1 = GuiFlatButton_Create("Save", 130, 5, 50, 48, $BS_TOOLBUTTON)
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybutton1), $BM_SETIMAGE, $IMAGE_ICON, $hIcon))
;align top
Local $mybuttonT = GuiFlatButton_Create("Top", 5, 65, 120, 55, $BS_TOP)
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybuttonT), $BM_SETIMAGE, $IMAGE_ICON, $hIcon))
;align top-left
Local $mybuttonTL = GuiFlatButton_Create("Top-Left", 5, 125, 120, 55, BITOR($BS_TOP, $BS_LEFT))
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybuttonTL), $BM_SETIMAGE, $IMAGE_ICON, $hIcon))
;align top-right
Local $mybuttonTR = GuiFlatButton_Create("Top-Right", 5, 185, 120, 55, BITOR($BS_TOP, $BS_RIGHT))
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybuttonTR), $BM_SETIMAGE, $IMAGE_ICON, $hIcon))
;align left
Local $mybuttonL = GuiFlatButton_Create("Left", 5, 245, 120, 55, $BS_LEFT)
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybuttonL), $BM_SETIMAGE, $IMAGE_ICON, $hIcon))
;align bottom
Local $mybuttonB = GuiFlatButton_Create("Bottom", 130, 65, 120, 55, $BS_BOTTOM)
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybuttonB), $BM_SETIMAGE, $IMAGE_ICON, $hIcon))
;align bottom-left
Local $mybuttonBL = GuiFlatButton_Create("Bottom-Left", 130, 125, 120, 55, BITOR($BS_BOTTOM, $BS_LEFT))
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybuttonBL), $BM_SETIMAGE, $IMAGE_ICON, $hIcon))
;align bottom-right
Local $mybuttonBR = GuiFlatButton_Create("Bottom-Right", 130, 185, 120, 55, BITOR($BS_BOTTOM, $BS_RIGHT))
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybuttonBR), $BM_SETIMAGE, $IMAGE_ICON, $hIcon))
;align right
Local $mybuttonR = GuiFlatButton_Create("Right", 130, 245, 120, 55, $BS_RIGHT)
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybuttonR), $BM_SETIMAGE, $IMAGE_ICON, $hIcon))
GuiFlatButton_SetState($mybuttonR, $GUI_DISABLE )
;disabled
Local $mybuttonDisable = GuiFlatButton_Create("Disabled", 130, 310, 120, 55, $BS_TOOLBUTTON)
_WinAPI_DeleteObject(_SendMessage(GUICtrlGetHandle($mybuttonDisable), $BM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap))
GuiFlatButton_SetState($mybuttonDisable, $GUI_DISABLE )
;clean up!
_WinAPI_DestroyIcon( $hIcon )
_WinAPI_DeleteObject( $hHBitmap )
GUISetState(@SW_SHOW, $hGUI)
Local $iMsg
While 1
$iMsg = GUIGetMsg()
Switch $iMsg
Case $GUI_EVENT_CLOSE
ExitLoop
EndSwitch
Sleep(10)
WEnd
GUIDelete()
EndFunc ;==>Example
I'm sure there are some use-cases I've forgotten, so feedback is welcome!
Download the latest UDF and several more examples:
GuiFlatButton_20220919.zip (1,121)
Update 2022-09-19
Added update from 05/25 back in after it was accidentally removed
Update 2022-09-01
Added $BS_MULTILINE button style
Added ellipses when text is longer than the button
Fixed compatibility with Opt("MustDeclareVars", 1)
Update 2022-05-25
Fixed issue, buttons disappear when a GUI containing a child window with WS_EX_MDICHILD extended style is moved
Update 2022-05-24
Fixed issue releasing subclassing when GUI is deleted but program is not closed
Fixed occasional white background flicker
Added function GuiFlatButton_GetPos
Update 2021-01-02
Fixed bug, not drawing correctly after deleting GUI with GUIDelete()
Fixed bug, changing default colors changed all buttons, even previously created buttons
Made some internal functions more efficient
Update 2019-04-14
Fixed bug, not showing pressed down state when clicking rapidly
Added Icon/Bitmap support!
Added function GuiFlatButton_SetPos to change the position and/or size of a button
Update 2019-02-09
Added 2 new functions to set the button colors globally for all future buttons.
GuiFlatButton_SetDefaultColors
GuiFlatButton_SetDefaultColorsEx
Credits to:
Melba23 (UDF template)
LarsJ (general subclassing code)
4ggr35510n (TrackMouseEvent example)
binhnx (disable dragging with $WS_EX_CONTROLPARENT)
GUIRegisterMsg in AutoIt Help (owner-draw button example)
funkey (_WinAPI_DrawState example)