Page 1 of 1
How to set background color in splitter gadget?
Posted: Wed Nov 12, 2014 3:55 pm
by Kukulkan
Hi,
I like to set the background of my program. Sadly, as soon as I start to use the splitter, the background colour is no longer set for the splitter content background.
Example:
Code: Select all
CompilerIf #PB_Compiler_Unicode
#XmlEncoding = #PB_UTF8
CompilerElse
#XmlEncoding = #PB_Ascii
CompilerEndIf
#Dialog = 0
#Xml = 0
#Image = 0
XML$ = "<window id='#PB_Any' name='test' text='test' minwidth='400' minheight='auto' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
"<singlebox margin='10'>"+
" <splitter name='splitter' flags='#PB_Splitter_Separator'>"+
" <vbox align='left'>"+
" <button text='Some button' />"+
" <empty />"+
" <vbox>"+
" <button text='Example UI content' />"+
" <button text='Example UI content' />"+
" </vbox>"+
" </vbox>"+
" <vbox align='center'>"+
" <button text='Example UI content' />"+
" <button text='Example UI content' />"+
" </vbox>"+
" </splitter>"+
"</singlebox>"+
"</window>"
If CatchXML(#Xml, @XML$, StringByteLength(XML$), 0, #XmlEncoding) And XMLStatus(#Xml) = #PB_XML_Success
If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "test")
SetWindowColor(DialogWindow(#Dialog), RGB(200, 223, 205))
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Else
Debug "Error -Dialog- : " + DialogError(#Dialog)
EndIf
Else
Debug "Error XML : " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
EndIf
I tried it with
SetClassLong_(DialogGadget(#Dialog, "splitter"), #GCL_HBRBACKGROUND, CreateSolidBrush_(RGB(255,0,255))) but I've had no success.
BTW, I need this cross-platform.
Best,
Kukulkan
Re: How to set background color in splitter gadget?
Posted: Wed Nov 12, 2014 11:18 pm
by netmaestro
There are some containers and a splitter in this dialog and if all is to look right, they must all have colored backgrounds imho. So here's a thing, I'm pretty noobish when it comes to dialogs and while I could use DialogGadget() to retrieve the ID of the splitter, I had no luck with the containers. You probably know how to do that but I couldn't so I went to some lengths to get the IDs. Sorry for the extra code. Once I had those, It was a matter of subclassing the relevant controls and handling WM_ERASEBKGND with the appropriate hBrush and hPen. So this code is working on Windows. Unfortunately I know less about Linux and MacOS than I do about dialogs so someone else will have to help on those platforms. Wilbert can handle the MacOS without difficulty I'm sure, perhaps Idle for the Linux. But there are others. Anyway, here's Windows:
Code: Select all
Global hBrush = CreateSolidBrush_(RGB(200, 223, 205)), hPen = CreatePen_(#PS_SOLID, 1, RGB(200,223,205))
Global Dim containers(2), numcontainers=0
Procedure BackColorProc(hwnd, msg, wparam, lparam)
oldproc = GetProp_(hwnd, "oldproc")
gadget = GetDlgCtrlID_(hwnd)
Select msg
Case #WM_NCDESTROY
RemoveProp_(hwnd, "oldproc")
Case #WM_ERASEBKGND
SelectObject_(wparam, hBrush)
SelectObject_(wparam, hPen)
GetClientRect_(hwnd, @r.RECT)
Rectangle_(wparam, r\left, r\top, r\right, r\bottom)
ProcedureReturn 1
EndSelect
ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
EndProcedure
Procedure Enummer(hwnd, lparam)
cn$ = Space(100)
GetClassName_(hwnd, @cn$, 100-SizeOf(Character))
If cn$ = "PureContainer"
containers(numcontainers) = GetDlgCtrlID_(hwnd)
numcontainers+1
EndIf
ProcedureReturn 1
EndProcedure
CompilerIf #PB_Compiler_Unicode
#XmlEncoding = #PB_UTF8
CompilerElse
#XmlEncoding = #PB_Ascii
CompilerEndIf
#Dialog = 0
#Xml = 0
#Image = 0
XML$ = "<window id='#PB_Any' name='test' text='test' minwidth='400' minheight='auto' flags='#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget'>" +
"<singlebox name='singlebox' margin='10'>"+
" <splitter name='splitter' flags='#PB_Splitter_Separator'>"+
" <vbox align='left'>"+
" <button text='Some button' />"+
" <empty />"+
" <vbox>"+
" <button text='Example UI content' />"+
" <button text='Example UI content' />"+
" </vbox>"+
" </vbox>"+
" <vbox align='center'>"+
" <button text='Example UI content' />"+
" <button text='Example UI content' />"+
" </vbox>"+
" </splitter>"+
"</singlebox>"+
"</window>"
If CatchXML(#Xml, @XML$, StringByteLength(XML$), 0, #XmlEncoding) And XMLStatus(#Xml) = #PB_XML_Success
If CreateDialog(#Dialog) And OpenXMLDialog(#Dialog, #Xml, "test")
SetWindowColor(DialogWindow(#Dialog), RGB(200, 223, 205))
; Find the containers and enumerate them in an array
EnumChildWindows_(WindowID((DialogWindow(#Dialog))), @Enummer(), 0)
; Subclass the found containers
For i=0 To numcontainers-1
SetProp_(GadgetID(containers(i)), "oldproc", SetWindowLongPtr_(GadgetID(containers(i)), #GWLP_WNDPROC, @BackColorProc()))
Next
; and the splitter too. Now splitter and containers will
; have their backgrounds erased with the colored brush.
hwndSplitter = GadgetID(DialogGadget(#dialog, "splitter"))
SetProp_(hwndSplitter, "oldproc", SetWindowLongPtr_(hwndSplitter, #GWLP_WNDPROC, @BackColorProc()))
Repeat
Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
Else
Debug "Error -Dialog- : " + DialogError(#Dialog)
EndIf
Else
Debug "Error XML : " + XMLError(#Xml) + " (Line: " + XMLErrorLine(#Xml) + ")"
EndIf
Re: How to set background color in splitter gadget?
Posted: Thu Nov 13, 2014 8:04 am
by Kukulkan
Hello netmaestro,
Wow, thank you for that great solution. If I run it here (Win7), it still has a grey one pixel border surrounding each button. Do you have the same or is it only my system?
Best,
Volker
Re: How to set background color in splitter gadget?
Posted: Thu Nov 13, 2014 8:15 am
by netmaestro
I have the same, it's probably part of the button.
Re: How to set background color in splitter gadget?
Posted: Thu Nov 13, 2014 10:43 am
by chi
If I run it here (Win7), it still has a grey one pixel border surrounding each button
Just return your desired brush on #WM_CTLCOLORBTN and you are good to go
Code: Select all
Procedure BackColorProc(hwnd, msg, wparam, lparam)
oldproc = GetProp_(hwnd, "oldproc")
gadget = GetDlgCtrlID_(hwnd)
Select msg
Case #WM_NCDESTROY
RemoveProp_(hwnd, "oldproc")
;------------------------------ added
Case #WM_CTLCOLORBTN
ProcedureReturn hBrush
;------------------------------
Case #WM_ERASEBKGND
SelectObject_(wparam, hBrush)
SelectObject_(wparam, hPen)
GetClientRect_(hwnd, @r.RECT)
Rectangle_(wparam, r\left, r\top, r\right, r\bottom)
ProcedureReturn 1
EndSelect
ProcedureReturn CallWindowProc_(oldproc, hwnd, msg, wparam, lparam)
EndProcedure
Re: How to set background color in splitter gadget?
Posted: Thu Nov 13, 2014 11:10 am
by Kukulkan
Hi,
thanks for the tipps. As I need it cross-platform, it turns out to be not that easy. I'll try to use my own drawn buttons. So I have full control over the colours.
Best,
Kukulkan
Re: How to set background color in splitter gadget?
Posted: Thu Nov 13, 2014 8:02 pm
by netmaestro
Windows will ignore brushes returned from WM_CTLCOLORBTN for all but ownerdrawn buttons. This is because there is just one WM_CTLCOLORBTN message to respond to but more than one color to draw depending upon the state of the button. So unless you've informed the OS that you're responsible for all drawing on the button, Windows will use its own brushes.
Re: How to set background color in splitter gadget?
Posted: Thu Nov 13, 2014 9:26 pm
by chi
Windows will ignore brushes returned from WM_CTLCOLORBTN for all but ownerdrawn buttons. This is because there is just one WM_CTLCOLORBTN message to respond to but more than one color to draw depending upon the state of the button. So unless you've informed the OS that you're responsible for all drawing on the button, Windows will use its own brushes.
Sounds like I'm doing something wrong her!? But, I'm pretty sure, I am not
Code: Select all
Global oldProc, brushBG = CreateSolidBrush_(GetSysColor_(3))
Procedure WndCallback(hwnd, msg, wparam, lparam)
Select msg
Case #WM_CTLCOLORBTN
ProcedureReturn brushBG
Case #WM_CTLCOLORSTATIC
SetBkMode_(wparam, #TRANSPARENT);
ProcedureReturn brushBG
EndSelect
ProcedureReturn CallWindowProc_(oldProc, hwnd, msg, wparam, lparam)
EndProcedure
OpenWindow(0, 0, 0, 320, 200, "", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
SetClassLongPtr_(WindowID(0), #GCL_HBRBACKGROUND, brushBG)
oldProc = SetWindowLongPtr_(WindowID(0), #GWL_WNDPROC, @WndCallback())
ButtonGadget(0, 10, 10, 100, 40, "button")
ButtonGadget(1, 110, 10, 100, 40, "button")
TextGadget(2, 10, 60, 100, 40, "text")
TextGadget(3, 110, 60, 100, 40, "text")
OptionGadget(4, 10, 110, 100, 20, "option 1")
OptionGadget(5, 10, 130, 100, 20, "option 2")
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend