How to set background color in splitter gadget?

Everything else that doesn't fall into one of the other PB categories.
User avatar
Kukulkan
Addict
Addict
Posts: 1422
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

How to set background color in splitter gadget?

Post 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
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8453
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: How to set background color in splitter gadget?

Post 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
BERESHEIT
User avatar
Kukulkan
Addict
Addict
Posts: 1422
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: How to set background color in splitter gadget?

Post 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
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8453
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: How to set background color in splitter gadget?

Post by netmaestro »

I have the same, it's probably part of the button.
BERESHEIT
User avatar
chi
Addict
Addict
Posts: 1092
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: How to set background color in splitter gadget?

Post 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
Et cetera is my worst enemy
User avatar
Kukulkan
Addict
Addict
Posts: 1422
Joined: Mon Jun 06, 2005 2:35 pm
Location: germany
Contact:

Re: How to set background color in splitter gadget?

Post 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
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8453
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: How to set background color in splitter gadget?

Post 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.
BERESHEIT
User avatar
chi
Addict
Addict
Posts: 1092
Joined: Sat May 05, 2007 5:31 pm
Location: Austria

Re: How to set background color in splitter gadget?

Post 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
Et cetera is my worst enemy
Post Reply