Why no SetGadgetColor for buttons?
Why no SetGadgetColor for buttons?
Hello,
is there a special reason, why SetGadgetColor doesn't work for normal buttons? I know there are some Modules and codes for colored buttons (and they work quite well), but I wich the normal button would be able to be colored too.
is there a special reason, why SetGadgetColor doesn't work for normal buttons? I know there are some Modules and codes for colored buttons (and they work quite well), but I wich the normal button would be able to be colored too.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Re: Why no SetGadgetColor for buttons?
Is a limitation from the Windows OS
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Re: Why no SetGadgetColor for buttons?
I suspected that. Which is also strange, because other gadgets can easily be colored. Maybe because buttons were among the first controls introduced.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Re: Why no SetGadgetColor for buttons?
I don't understand these things of Windows OS Another no-sense "feature" is when the text is not vertically centered, by example on on textgadgets
It's ridiculous!
It's ridiculous!
Re: Why no SetGadgetColor for buttons?
Many elements support color initially, since the background is not a picture. The button is not originally a one-color plane. There is a style for the button when it is drawn by the user. It is difficult to set it just by color, since most likely you need to draw both the border of the button, this is already 3 colors, and the icon. And we also need the Callback function. If you have your own Callback, then it's probably more difficult to put it all together.
Re: Why no SetGadgetColor for buttons?
As mk-soft said, buttons don't support colors in Windows. And vertical alignment for text gadgets aren't supported by Windows, either. (I tested both in Visual Basic, and there's no property settings for either of these attributes).
Re: Why no SetGadgetColor for buttons?
Code: Select all
Structure tagED0_Simple Align #PB_Structure_AlignC
hText.i
cchAlloc.l
cchTextMax.l
cch.l
cLines.l
ichMinSel.l
ichMaxSel.l
ichCaret.l
iCaretLine.l
ichScreenStart.l
ichLinesOnScreen.l
xOffset.l
charPasswordChar.l
cPasswordCharWidth.l
*hwnd
pwnd.q
rcFmt.rect
*hwndParent
ptPrevMouse.POINT
prevKeys.l
fSingle.l
EndStructure
Procedure VCenter_SL_Edit(hWnd)
Protected *tagED.tagED0_Simple = GetWindowLongPtr_(hWnd, 0)
If *tagED And *tagED\fSingle & 1
Protected rc.rect
GetClientRect_(*tagED\hwnd, @rc)
Protected h = *tagED\rcFmt\bottom - *tagED\rcFmt\top
*tagED\rcFmt\top = ((rc\bottom - rc\top) - h) / 2
*tagED\rcFmt\bottom = *tagED\rcFmt\top + h
EndIf
EndProcedure
OpenWindow(0, 0, 0, 322, 205, "StringGadget Flags", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
StringGadget(0, 8, 10, 306, 40, "Normal StringGadget...")
StringGadget(1, 8, 60, 306, 40, "Centered StringGadget...")
VCenter_SL_Edit(GadgetID(1))
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Re: Why no SetGadgetColor for buttons?
thanks fryquez I already know the workarounds, but something as simple as that must be done directly, for example with a flag, I don't understand that laziness of Microsoft since years and years, no matter what language you use.
- DeanH
- Enthusiast
- Posts: 229
- Joined: Wed May 07, 2008 4:57 am
- Location: Adelaide, South Australia
- Contact:
Re: Why no SetGadgetColor for buttons?
For the Windows OS, not being able to set the colour of a pushbutton and not being able to vertically centre text easily has been a lack. I think it goes way back to Windows 2 when there were only a handful of basic controls. Buttons, static text (TextGadget) and Editbox are "old controls". For whatever reason, Microsoft has not added much to these old controls over time. There are plenty of workarounds as you are aware. I agree, though, it is something one would have thought would have been addressed by MS long ago but hasn't.
It is possible to have multi-line text in a pushbutton by adding #Pb_Button_Multiline to the style. It will automatically centre the text. Also applies to checkboxes and radiobuttons ... which MS oddly considers types of buttons.
It is possible to have multi-line text in a TextGadget and centre it horizontally. It is possible to vertically centre a single line of text in the same type of control but I have not found out how to do both together without resorting to a work-around. Same for string and editor gadgets.
Below is a simple example. I have not found the #SS_EDITCONTROL constant in PB6. It displays multi-line text in a TextGadget (static text control) horizontally centred. #SS_CENTERIMAGE will vertically centre the text but only a single line.
It is possible to have multi-line text in a pushbutton by adding #Pb_Button_Multiline to the style. It will automatically centre the text. Also applies to checkboxes and radiobuttons ... which MS oddly considers types of buttons.
It is possible to have multi-line text in a TextGadget and centre it horizontally. It is possible to vertically centre a single line of text in the same type of control but I have not found out how to do both together without resorting to a work-around. Same for string and editor gadgets.
Below is a simple example. I have not found the #SS_EDITCONTROL constant in PB6. It displays multi-line text in a TextGadget (static text control) horizontally centred. #SS_CENTERIMAGE will vertically centre the text but only a single line.
Code: Select all
#SS_EDITCONTROL=$2000
OpenWindow(1,#PB_Ignore,#PB_Ignore,320,240,"Test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
ButtonGadget(10,12,12,70,64,"Click here to close",#PB_Button_MultiLine)
TextGadget(20,100,12,60,64,"Multi line text gadget", #WS_BORDER | #SS_CENTER | #SS_EDITCONTROL | #SS_NOTIFY)
TextGadget(30,180,12,90,64,"Single line", #PB_Text_Center | #WS_BORDER | #SS_NOTIFY | #SS_CENTERIMAGE)
StringGadget(40,12,100,80,64,"Multi line string gadget",#ES_CENTER|#ES_MULTILINE | #ESB_DISABLE_LEFT | #ESB_DISABLE_RIGHT | #ES_READONLY)
EditorGadget(50,100,100,70,64,#PB_Editor_WordWrap | #ES_CENTER|#ES_MULTILINE | #ESB_DISABLE_LEFT | #ESB_DISABLE_RIGHT | #ES_READONLY)
SetGadgetText(50,"Multi line editor gadget")
Repeat
e=WaitWindowEvent()
If e=#PB_Event_CloseWindow
Break
EndIf
If e=#PB_Event_Gadget
g=EventGadget()
If g=10 Or g=20
Break
EndIf
EndIf
ForEver
CloseWindow(1)
Re: Why no SetGadgetColor for buttons?
It's possible to colourize true buttons in Windows, its a lot of work.
You have to use subclassing and also uxtheme functions such as
IsThemeBackgroundPartiallyTransparent()
DrawThemeParentBackground()
DrawThemeBackground()
GetThemeBackgroundContentRect()
You also have to manage the state of the button (normal, hovered etc.)
Here is a utility I wrote with coloured buttons.
and the callback i use (written more than 10 years ago), i never get crash (i also use gdiplus to colorise buttons)
Code: Select all
Procedure.i Gdiplus_Window_Callback(Window, Message, wParam, lParam)
;///////////////////////////////////////////////////////////////////////////////////////////////////
;//
;// FONCTION: Gdiplus_Window_Callback()
;//
;// BUT: Callback dessinant les boutons couleur
;//
;// PARAMS: Window, Message, wParam, lParam
;//
;// RETOURNE: L'adresse de la procedure d'origine ou la procedure par défaut
;//
;///////////////////////////////////////////////////////////////////////////////////////////////////
Protected stateID, partID, ButtonText.s
Protected BoutonStyle, TexteStyle, textWidth, textHeight, Font
Protected TextColor, Color1, Color2, SavedDC
Protected rc_Interior.RECT, rc_InteriorF.RECTF, rc_ThemeContent.rect
Protected *di.DRAWITEMSTRUCT
Protected *token, *gfx, *brush, *OriginProc
Protected Alpha_Value, hBmpTampon, hdcMem, solidBrush
If ListSize(Gdiplus_Window_SubClassing_Infos()) = 0
ProcedureReturn DefWindowProc_(window, message, wParam, lParam)
EndIf
ForEach (Gdiplus_Window_SubClassing_Infos())
;// on se positionne sur le bon élément
If Gdiplus_Window_SubClassing_Infos()\Gdiplus_SubClassed_Window = Window
Break
EndIf
Next
*OriginProc = GetProp_(Window, Gdiplus_Window_SubClassing_Infos()\Gdiplus_SubClassed_WindowString$)
If *OriginProc = 0
ProcedureReturn DefWindowProc_(window, message, wParam, lParam)
EndIf
*di = lParam
If *di
Select Message
Case #WM_DRAWITEM
If *di\CtlType = #ODT_BUTTON
hdcMem = CreateCompatibleDC_(*di\hDC)
If hdcMem = 0
ProcedureReturn CallWindowProc_(*OriginProc,Window, Message, wParam, lParam)
EndIf
hBmpTampon = CreateCompatibleBitmap_(*di\hDC, GetDeviceCaps_(*di\hDC, #HORZRES), GetDeviceCaps_(*di\hDC, #VERTRES))
If hBmpTampon = 0
DeleteDC_(hdcMem)
ProcedureReturn CallWindowProc_(*OriginProc,Window, Message, wParam, lParam)
EndIf
;// sélectionne l'élément de la Map correspondant au bouton à dessiner, + teste l'initialisation de GDI+ etc.
If ((*GLB_Gdiplus_token <> -1) And GLB_hTheme And MapSize(GLB_Bouton()) And FindMapElement(GLB_Bouton(), Str(GadgetID(*di\CtlID))) = #False)
DeleteDC_(hdcMem)
DeleteObject_(hBmpTampon)
ProcedureReturn CallWindowProc_(*OriginProc,Window, Message, wParam, lParam)
EndIf
;// sélectionne le bmp dans le dc
SelectObject_(hdcMem, hBmpTampon)
If *GdipCreateFromHDC(hdcMem, @*gfx) = #Ok
;// sauvegarde du dc
SavedDC = SaveDC_(*di\hDC)
If GLB_Bouton()\Gdiplus_ButtonStyle = #Button_oldStyle
If *di\itemState & #ODS_DISABLED
partID = #DFC_BUTTON
stateID = #DFCS_BUTTONPUSH|#DFCS_FLAT|#DFCS_INACTIVE
Alpha_Value = 255
TextColor = GetSysColor_(#COLOR_GRAYTEXT)
Color1 = GetSysColor_(#COLOR_BTNFACE)
Color2 = GetSysColor_(#COLOR_BTNFACE)
ElseIf *di\itemState & #ODS_SELECTED
partID = #DFC_BUTTON
stateID = #DFCS_BUTTONPUSH|#DFCS_FLAT|#DFCS_PUSHED
Alpha_Value = GLB_Bouton()\Selected_Alpha
TextColor = GLB_Bouton()\Selected_TextColor
Color1 = GLB_Bouton()\Selected_BackGround_UpperColor
Color2 = GLB_Bouton()\Selected_BackGround_LowerColor
Else
partID = #DFC_BUTTON
stateID = #DFCS_BUTTONPUSH|#DFCS_FLAT
If GLB_Bouton()\IsMouseOver
Alpha_Value = GLB_Bouton()\MouseOver_Alpha
TextColor = GLB_Bouton()\MouseOver_TextColor
Color1 = GLB_Bouton()\MouseOver_BackGround_UpperColor
Color2 = GLB_Bouton()\MouseOver_BackGround_LowerColor
Else
Alpha_Value = GLB_Bouton()\Normal_Alpha
TextColor = GLB_Bouton()\Normal_TextColor
Color1 = GLB_Bouton()\Normal_BackGround_UpperColor
Color2 = GLB_Bouton()\Normal_BackGround_LowerColor
EndIf
EndIf
Else ;// GLB_Bouton()\Gdiplus_ButtonStyle = #Button_XPStyle
If *di\itemState & #ODS_DISABLED
; Debug "#ODS_DISABLED"
; Debug #PBS_DISABLED
partID = #BP_PUSHBUTTON
stateID = #PBS_DISABLED
Alpha_Value = GLB_Bouton()\Normal_Alpha
Alpha_Value = 80
TextColor = GLB_Bouton()\Normal_TextColor
; TextColor = GetSysColor_(#COLOR_GRAYTEXT)
; TextColor = $B1A2A2 ;$838383
; Color1 = GetSysColor_(#COLOR_BTNFACE)
; Color2 = GetSysColor_(#COLOR_BTNFACE)
; Color1 = GLB_Bouton()\Normal_BackGround_UpperColor
Color2 = GLB_Bouton()\Normal_BackGround_LowerColor
Color1 = Color2
ElseIf *di\itemState & #ODS_SELECTED
; Debug #PBS_PRESSED
partID = #BP_PUSHBUTTON
stateID = #PBS_PRESSED
Alpha_Value = GLB_Bouton()\Selected_Alpha
TextColor = GLB_Bouton()\Selected_TextColor
Color1 = GLB_Bouton()\Selected_BackGround_UpperColor
Color2 = GLB_Bouton()\Selected_BackGround_LowerColor
Else
partID = #BP_PUSHBUTTON
stateID = #PBS_NORMAL
; Debug #PBS_NORMAL
If GLB_Bouton()\IsMouseOver
Alpha_Value = GLB_Bouton()\MouseOver_Alpha
TextColor = GLB_Bouton()\MouseOver_TextColor
Color1 = GLB_Bouton()\MouseOver_BackGround_UpperColor
Color2 = GLB_Bouton()\MouseOver_BackGround_LowerColor
Else
Alpha_Value = GLB_Bouton()\Normal_Alpha
TextColor = GLB_Bouton()\Normal_TextColor
Color1 = GLB_Bouton()\Normal_BackGround_UpperColor
Color2 = GLB_Bouton()\Normal_BackGround_LowerColor
EndIf
EndIf
EndIf
If GLB_Bouton()\Gdiplus_ButtonStyle = #Button_XPStyle
;// on redessine le bouton
If IsThemeBackgroundPartiallyTransparent_(GLB_hTheme, partID, stateID)
DrawThemeParentBackground_(*di\hwndItem, hdcMem, *di\rcItem)
EndIf
DrawThemeBackground_(GLB_hTheme, hdcMem, partID, stateID, *di\rcItem, 0)
GetThemeBackgroundContentRect_(GLB_hTheme, *di\hDC, partID, stateID, *di\rcItem, @rc_ThemeContent)
rc_Interior = rc_ThemeContent
ElseIf GLB_Bouton()\Gdiplus_ButtonStyle = #Button_oldStyle
DrawFrameControl_(hdcMem, *di\rcItem, partID, stateID)
rc_Interior = *di\rcItem
InflateRect_(rc_Interior, -GetSystemMetrics_(#SM_CXEDGE), -GetSystemMetrics_(#SM_CYEDGE))
Else ;// GLB_Bouton()\Gdiplus_ButtonStyle = #Button_ThickFrame
GetThemeBackgroundContentRect_(GLB_hTheme, hdcMem, partID, stateID, *di\rcItem, @rc_ThemeContent)
rc_Interior = rc_ThemeContent
solidBrush = CreateSolidBrush_(GLB_Bouton()\Gdiplus_ThickFrameColor)
If solidBrush
FillRect_(hdcMem, *di\rcItem, solidBrush)
DeleteObject_(solidBrush)
EndIf
EndIf
Select GLB_Bouton()\LinearGradientMode
Case #LinearGradientModehorizontal
rc_InteriorF\x = rc_Interior\left
rc_InteriorF\y = rc_Interior\top+1
rc_InteriorF\Width = rc_Interior\right - rc_Interior\left -2
rc_InteriorF\Height = rc_Interior\bottom - rc_Interior\top-2
*GdipCreateLineBrushFromRect(@rc_InteriorF, Gdiplus_ARGB(Color1, Alpha_Value), Gdiplus_ARGB(Color2, Alpha_Value), GLB_Bouton()\LinearGradientMode, #WrapModeTile, @*brush)
*GdipFillRectangle(*gfx, *brush, rc_InteriorF\x+1, rc_InteriorF\y, rc_InteriorF\Width, rc_InteriorF\Height)
Default ;/ #LinearGradientModeVertical, #LinearGradientModeForwardDiagonal, #LinearGradientModeBackwardDiagonal
If GLB_Bouton()\Gdiplus_ButtonStyle = #Button_oldStyle
rc_InteriorF\x = rc_Interior\left+1
rc_InteriorF\y = rc_Interior\top+1
rc_InteriorF\Height = rc_Interior\bottom - rc_Interior\top-1
rc_InteriorF\Width = rc_Interior\right - rc_Interior\left -2
*GdipCreateLineBrushFromRect(@rc_InteriorF, Gdiplus_ARGB(Color1, Alpha_Value), Gdiplus_ARGB(Color2, Alpha_Value), GLB_Bouton()\LinearGradientMode, #WrapModeTile, @*brush)
*GdipFillRectangle(*gfx, *brush, rc_InteriorF\x, rc_InteriorF\y, rc_InteriorF\Width, rc_InteriorF\Height-1)
Else
; Debug "Default"
rc_InteriorF\x = rc_Interior\left
rc_InteriorF\y = rc_Interior\top
rc_InteriorF\Height = rc_Interior\bottom - rc_Interior\top
rc_InteriorF\Width = rc_Interior\right - rc_Interior\left
*GdipCreateLineBrushFromRect(@rc_InteriorF, Gdiplus_ARGB(Color1, Alpha_Value), Gdiplus_ARGB(Color2, Alpha_Value), GLB_Bouton()\LinearGradientMode, #WrapModeTile, @*brush)
rc_InteriorF\x = rc_Interior\left+1
rc_InteriorF\y = rc_Interior\top+1
rc_InteriorF\Height = rc_Interior\bottom - rc_Interior\top-2
rc_InteriorF\Width = rc_Interior\right - rc_Interior\left -2
*GdipFillRectangle(*gfx, *brush, rc_InteriorF\x, rc_InteriorF\y, rc_InteriorF\Width, rc_InteriorF\Height)
EndIf
EndSelect
;// destruction de la brush
Gdiplus_DelBrush(*brush)
;// écriture du texte du bouton
ButtonText = GetGadgetText(*di\CtlID)
If Len(ButtonText)
;// couleur texte , fond transparent
SetTextColor_(hdcMem, TextColor)
SetBkMode_(hdcMem, #TRANSPARENT)
Font = GetGadgetFont(*di\CtlID)
If Font
SelectObject_(hdcMem, Font)
EndIf
;// lecture du style du bouton
BoutonStyle = GetWindowLongPtr_(*di\hwndItem, #GWL_STYLE)
If BoutonStyle & #BS_RIGHT
TexteStyle | #DT_RIGHT
ElseIf BoutonStyle & #BS_LEFT
TexteStyle | #DT_LEFT
Else
TexteStyle | #DT_CENTER
EndIf
If (Not(BoutonStyle & #BS_MULTILINE))
TexteStyle | #DT_SINGLELINE | #DT_WORDBREAK | #DT_VCENTER
rc_Interior\right-1
Else
TexteStyle | #DT_WORDBREAK
;// calcul du rectangle du texte à centrer et centrage
DrawText_(hdcMem, @ButtonText, -1, @rc_Interior, #DT_CALCRECT | TexteStyle)
textWidth = rc_Interior\right - rc_Interior\left
textHeight = rc_Interior\bottom - rc_Interior\top
rc_Interior\left = ((*di\rcItem\right - *di\rcItem\left) - (rc_Interior\right - rc_Interior\left)) / 2
rc_Interior\right = rc_Interior\left + textWidth
rc_Interior\top = (*di\rcItem\bottom - *di\rcItem\top - textheight) / 2
rc_Interior\bottom = rc_Interior\top + textheight
EndIf
;// on écrit le texte
DrawTextEx_(hdcMem, ButtonText, -1, @rc_Interior, TexteStyle | #DT_EXPANDTABS , 0)
;// on copie le hDC de la mémoire vers celui du bouton
BitBlt_(*di\hDC, 0, 0, *di\rcItem\right - *di\rcItem\left, *di\rcItem\bottom - *di\rcItem\top, hdcMem, 0, 0, #SRCCOPY)
EndIf
DeleteDC_(hdcMem)
DeleteObject_(hBmpTampon)
Gdiplus_DelGraphics(*gfx)
If SavedDC
RestoreDC_(*di\hDC, SavedDC)
EndIf
ProcedureReturn #True
EndIf
EndIf
EndSelect
EndIf
ProcedureReturn CallWindowProc_(*OriginProc,Window, Message, wParam, lParam)
EndProcedure
A+
Denis
Denis
- Mindphazer
- Enthusiast
- Posts: 346
- Joined: Mon Sep 10, 2012 10:41 am
- Location: Savoie
Re: Why no SetGadgetColor for buttons?
Hello Denis,
could you provide a small example to show the use of your callback procedure ?
Thanks a lot
could you provide a small example to show the use of your callback procedure ?
Thanks a lot
MacBook Pro 14" M1 Pro - 16 Gb - MacOS 14 - Iphone 15 Pro Max - iPad at home
...and unfortunately... Windows at work...
...and unfortunately... Windows at work...
Re: Why no SetGadgetColor for buttons?
Hello Mindphazer,
to do what you want, I should post the whole library which has a lot of functions, I have never done that and I don't think I will because I don't provide if I haven't written a doc.
It would quickly become incomprehensible.I would have to answer a lot of questions and I don't have the time.
So writing doc is very time consuming.
Sorry Mindphazer
to do what you want, I should post the whole library which has a lot of functions, I have never done that and I don't think I will because I don't provide if I haven't written a doc.
It would quickly become incomprehensible.I would have to answer a lot of questions and I don't have the time.
So writing doc is very time consuming.
Sorry Mindphazer
A+
Denis
Denis
- Mindphazer
- Enthusiast
- Posts: 346
- Joined: Mon Sep 10, 2012 10:41 am
- Location: Savoie
Re: Why no SetGadgetColor for buttons?
It's okay, no problem.
I totally understand your point
I totally understand your point
MacBook Pro 14" M1 Pro - 16 Gb - MacOS 14 - Iphone 15 Pro Max - iPad at home
...and unfortunately... Windows at work...
...and unfortunately... Windows at work...
Re: Why no SetGadgetColor for buttons?
Mindphazer,
If you want to see how the coloured buttons work, here are 2 links to my utility. Be careful, don't upload any images with it, as the tool may start changing its content.
x64 version
CleanUpImage_X64.exe
x86 version
CleanUpImage_X86.exe
If you want to see how the coloured buttons work, here are 2 links to my utility. Be careful, don't upload any images with it, as the tool may start changing its content.
x64 version
CleanUpImage_X64.exe
x86 version
CleanUpImage_X86.exe
A+
Denis
Denis
- Mindphazer
- Enthusiast
- Posts: 346
- Joined: Mon Sep 10, 2012 10:41 am
- Location: Savoie
Re: Why no SetGadgetColor for buttons?
Thanks Denis,
I'll have a look
I'll have a look
MacBook Pro 14" M1 Pro - 16 Gb - MacOS 14 - Iphone 15 Pro Max - iPad at home
...and unfortunately... Windows at work...
...and unfortunately... Windows at work...