reskinning an application (->color questions)
reskinning an application (->color questions)
hi all,
i am currently in the process of reskinning/recoloring my application. i found a handy solution for linux earlier today (http://www.purebasic.fr/english/viewtop ... 15&t=58981), now it's on to windows. as i am not a windows expert, i would be thankful for any suggestion you could give me.
the problem, in a nutshell: i want to recolor gadgets to make a grey/dark theme. setting colors through PB is supported by many of them, but not all. i am looking at 2 options:
1. recolor every gadget manually through a windows api function call ---> please share code samples if you know any, thanks!
2. override the theme on a per-application basis ---> like i did with the gtkrc file on linux. is that even possible?
let me know what you think.
cheers
felix
i am currently in the process of reskinning/recoloring my application. i found a handy solution for linux earlier today (http://www.purebasic.fr/english/viewtop ... 15&t=58981), now it's on to windows. as i am not a windows expert, i would be thankful for any suggestion you could give me.
the problem, in a nutshell: i want to recolor gadgets to make a grey/dark theme. setting colors through PB is supported by many of them, but not all. i am looking at 2 options:
1. recolor every gadget manually through a windows api function call ---> please share code samples if you know any, thanks!
2. override the theme on a per-application basis ---> like i did with the gtkrc file on linux. is that even possible?
let me know what you think.
cheers
felix
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: reskinning an application (->color questions)
For the odd gadget such as CheckBoxGadget(), there is no colour option and it does not respect the Window colour. There is an API method to fix the back colour, but you can draw your own CheckBoxGadget() on a tiny canvas and control everything. Same thing with OptionGadget, there are a few examples of 'DIY' gadgets on this forum.
To colour buttons, I suggest drawing on ButtonImageGadgets(), that is very easy and the Windows Theme does not interfere. Again, you will find examples on this forum.
If you prefer the API way, this is a code snippet published by Rashad:
To colour buttons, I suggest drawing on ButtonImageGadgets(), that is very easy and the Windows Theme does not interfere. Again, you will find examples on this forum.
If you prefer the API way, this is a code snippet published by Rashad:
Code: Select all
Procedure.i WindowCallBack(WindowId.i, Msg.i, wParam.i, lParam.i)
;----------------------------------------------------------------
Protected iReturn.i
If Msg = #WM_CTLCOLORSTATIC
Select GetDlgCtrlID_(lParam) ;API call: allows choosing gadgets by their number
Case #MyOpt0, #MyOpt1, #MyOpt2, #MyChkBx0, #MyChkBx1, #MyChkBx2
; uncomment if compiling without XP support
; SetBkMode_(wParam,#TRANSPARENT)
SetBkColor_(wParam, RGB(0,0,0))
SetTextColor_(wParam, RGB(0,0,255))
iReturn = #False
EndSelect
EndIf
ProcedureReturn iReturn
EndProcedure
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: reskinning an application (->color questions)
thanks! CheckBoxes, Buttons, Frames and Tabs are exactly what gives me trouble.
I would indeed prefer to do it all by API. it might take me longer, but i might learn something about windows along the way.
Please help me one more step. How do I use the callback correctly? i currently have
which leads to my buttons, checkboxes, frames and progress bars disappearing, and the window generally hangs (window close button does nothing, procedures that are supposed to load text from a txt file on the hard drive are not executed)
I would indeed prefer to do it all by API. it might take me longer, but i might learn something about windows along the way.
Please help me one more step. How do I use the callback correctly? i currently have
Code: Select all
SetWindowCallback(@WindowCallBack())
Re: reskinning an application (->color questions)
Please see the help for SetWindowCallback() for an example. When returning other values than #PB_ProcessPureBasicEvents,broozar wrote:Please help me one more step. How do I use the callback correctly? i currently havewhich leads to my buttons, checkboxes, frames and progress bars disappearing, and the window generally hangs (window close button does nothing, procedures that are supposed to load text from a txt file on the hard drive are not executed)Code: Select all
SetWindowCallback(@WindowCallBack())
PureBasic does no further event handling. You need to return #PB_ProcessPureBasicEvents by default, and only return other
values (like a color, or #False/#True) to API directly, when no PB event processing is required for that message.
Re: reskinning an application (->color questions)
thanks! i visited the help page before, but did not spot the #PB_ProcessPureBasicEvents line.
no more hangs this way, but also no coloring. May I just assume that checkboxes cannot be colored that way? I see the callback procedure firing since i added some debug calls, but the color remains unchanged.
no more hangs this way, but also no coloring. May I just assume that checkboxes cannot be colored that way? I see the callback procedure firing since i added some debug calls, but the color remains unchanged.
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: reskinning an application (->color questions)
It should work, it is working in one of my old apps, for Options and CheckBoxes, but I can't get it to work either. Must be something subtle that I'm overlooking. One of the forum experts will no doubt spot it immediately.
Sample code PB5.22LTS:
Sample code PB5.22LTS:
Code: Select all
Enumeration
#Win
#Font10
#Font14B
#MyOpt0
#MyOpt1
#MyOpt2
#MyChkBx0
#MyChkBx1
#MyChkBx2
#BtnImg
#BtnExit
EndEnumeration
LoadFont(#Font10, "Arial", 10, #PB_Font_Bold | #PB_Font_HighQuality + 2)
LoadFont(#Font14B, "Arial Black", 14, #PB_Font_HighQuality + 2)
Global igWinColour.i = RGB(036,036,036)
Global igTxtColour.i = RGB(186,090,087)
;Global igBackColour.i = CreateSolidBrush_(igWinColour)
Procedure DrawBtn(iBtnID.i, sText.s, iW.i, iH.i)
;-----------------------------------------------
Protected iBtnImg.i, dX.d, dY.d, dW.d, dH.d
CreateImage(#BtnImg, iW, iH, 24)
If StartDrawing(ImageOutput(#BtnImg))
DrawingFont(FontID(#Font14B))
dH = TextHeight(sText)
dW = TextWidth(sText)
dX = ((iW - dW) / 2)
dY = ((iH - dH) / 2)
DrawingMode(#PB_2DDrawing_Default)
Box(0,0,iW,iH,igWinColour)
DrawText(dX, dY, sText, igTxtColour, igWinColour)
SetGadgetAttribute(iBtnID, #PB_Button_Image, ImageID(#BtnImg))
StopDrawing()
EndIf
EndProcedure
Procedure.i WindowCallBack(WindowId.i, iMsg.i, wParam.i, lParam.i)
;-----------------------------------------------------------------
Protected iReturn.i = #PB_ProcessPureBasicEvents
If iMsg = #WM_CTLCOLORSTATIC
Select GetDlgCtrlID_(lParam)
;API call: allows choosing gadgets by their number
;Comment out Select to apply to all gadgets
Case #MyOpt0, #MyOpt1, #MyOpt2, #MyChkBx0, #MyChkBx1, #MyChkBx2
;uncomment if compiling without XP support
;SetBkMode_(wParam, #TRANSPARENT)
SetBkColor_(wParam, igWinColour)
SetTextColor_(wParam, igTxtColour)
iReturn = #False
EndSelect
EndIf
ProcedureReturn iReturn
EndProcedure
Procedure Win()
;--------------
Protected iFlags.i = #PB_Window_Invisible | #PB_Window_SystemMenu | #PB_Window_ScreenCentered
If OpenWindow(#Win, 0, 0, 300, 130, "Colour", iFlags)
SetWindowColor(#Win, igWinColour)
SetGadgetFont(#PB_All, FontID(#Font10))
OptionGadget(#MyOpt0, 20, 10, 120, 20, "Option 0")
OptionGadget(#MyOpt1, 20, 40, 120, 20, "Option 1")
OptionGadget(#MyOpt2, 20, 70, 120, 20, "Option 2")
CheckBoxGadget(#MyChkBx0, 150, 10, 120, 20, "Check Box 0")
CheckBoxGadget(#MyChkBx1, 150, 40, 120, 20, "Check Box 1")
CheckBoxGadget(#MyChkBx2, 150, 70, 120, 20, "Check Box 2")
ButtonImageGadget(#BtnExit, 0, 100, 300, 30, 0)
DrawBtn(#BtnExit, "EXIT", 294, 24)
SetWindowCallback(@WindowCallBack(), #Win)
HideWindow(#Win, #False)
EndIf
EndProcedure
Procedure WaitForUser()
;----------------------
Protected iQuit.i = #False
Repeat
Select WaitWindowEvent(1)
Case #PB_Event_CloseWindow: iQuit = #True
Case #PB_Event_Gadget
Select EventGadget()
Case #BtnExit: iQuit = #True
EndSelect
EndSelect
Delay(1)
Until iQuit = #True
EndProcedure
Win()
WaitForUser()
End
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: reskinning an application (->color questions)
thanks for the snippet!
i tried to compile with 5.22, 5.00, as well as 4.51, no success. do you by any chance remember the version where it did still work, in case nobody comes up with a better solution?IdeasVacuum wrote:it is working in one of my old apps
Re: reskinning an application (->color questions)
Code: Select all
Global Bkgcolor_1,Bkgcolor_2,Bkgcolor_3,Bkgcolor_4
Bkgcolor_1 = CreateSolidBrush_($88FCF9)
Bkgcolor_2 = CreateSolidBrush_($88FCA4)
Bkgcolor_3 = CreateSolidBrush_($F4FC88)
Bkgcolor_4 = CreateSolidBrush_($FB89DF)
CreateImage(0,80,22)
StartDrawing(ImageOutput(0))
Box(0,0,80,22,#Yellow)
DrawingMode(#PB_2DDrawing_Transparent )
FrontColor(#Blue)
DrawText(18,3,"TEST")
StopDrawing()
Procedure WindowProc(hwnd, uMsg, wParam, lParam)
Select uMSG
Case #WM_CTLCOLORSTATIC
Select GetProp_(lParam, "PB_ID")
Case 1
SetBkMode_(wParam,#TRANSPARENT )
SetTextColor_(wParam,#Black)
ProcedureReturn Bkgcolor_1
Case 2
SetBkMode_(wParam,#TRANSPARENT )
SetTextColor_(wParam,#Red)
ProcedureReturn Bkgcolor_2
Case 3
SetBkMode_(wParam,#TRANSPARENT )
SetTextColor_(wParam,#Blue)
ProcedureReturn Bkgcolor_3
Case 4
SetBkMode_(wParam,#TRANSPARENT )
SetTextColor_(wParam,#Yellow)
ProcedureReturn Bkgcolor_4
EndSelect
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
OpenWindow(0,0,0,400,300,"test", #PB_Window_MinimizeGadget|#PB_Window_ScreenCentered)
SetWindowColor(0,#Gray)
SetWindowCallback(@WindowProc())
CheckBoxGadget(1,10,10,120,20,"CheckBox # 1")
CheckBoxGadget(2,10,40,120,20,"CheckBox # 2")
OptionGadget(3,140,10,120,20,"Option # 1")
OptionGadget(4,140,40,120,20,"Option # 2")
For Gadget = 1 To 4
SetWindowTheme_(GadgetID(Gadget), @null.w, @null.w)
Next
ButtonImageGadget(5,10,70,80,22,ImageID(0))
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Quit = 1
Case #PB_Event_Gadget
Select EventGadget()
EndSelect
EndSelect
Until Quit = 1
Egypt my love
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: reskinning an application (->color questions)
Hi broozar, it is working in my old app, coded with PB4.61. Tried my snippet in #PB4.61, does not work, though the debug shows that the gadget ID's are picked up correctly.
Hi Rashad - the code I used in my old app to set the back colour and text colour for option and check-box gadgets was posted by you, for me - it didn't use CreateSolidBrush though I have tried that (failed), and in any case that would not fix the text colour which is also not working. SetBkMode does not work either but as I understand it, cannot be used anyway on XP or Win7 if the User has set a fancy theme.
Edit: Just had a thought, is it pallet related? Can the colours only be chosen from a limited range?
Hi Rashad - the code I used in my old app to set the back colour and text colour for option and check-box gadgets was posted by you, for me - it didn't use CreateSolidBrush though I have tried that (failed), and in any case that would not fix the text colour which is also not working. SetBkMode does not work either but as I understand it, cannot be used anyway on XP or Win7 if the User has set a fancy theme.
Edit: Just had a thought, is it pallet related? Can the colours only be chosen from a limited range?
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: reskinning an application (->color questions)
@RASHAD Thanks so much! Checkboxes, labels and buttons work perfectly now. 3 gadgets remain problematic, maybe you have some idea on how to solve these last issues:
1. Tabs do not seem to be affected at all, except for SetWindowTheme_, so i know i have the right gadget(s) targeted
2. Frames: labels are great, the lines around them are pretty white and wide. Any way to thin them out or recolor them?
3. StringGadgets/Inputs: like Frames, they have an ugly border. SetWindowTheme with @null diminishes the effect, but it still is not as pretty as it could be.
i also noticed the call to SetWindowTheme_ which looks very interesting. If i hypothetically made a Windows theme file, could i use this function to override the theme of my application all in one go?
cheers
felix
1. Tabs do not seem to be affected at all, except for SetWindowTheme_, so i know i have the right gadget(s) targeted
2. Frames: labels are great, the lines around them are pretty white and wide. Any way to thin them out or recolor them?
3. StringGadgets/Inputs: like Frames, they have an ugly border. SetWindowTheme with @null diminishes the effect, but it still is not as pretty as it could be.
i also noticed the call to SetWindowTheme_ which looks very interesting. If i hypothetically made a Windows theme file, could i use this function to override the theme of my application all in one go?
cheers
felix
Re: reskinning an application (->color questions)
Full color control Panel Gadget
Code: Select all
Global Bkgcolor
Bkgcolor = CreateSolidBrush_($D5FEFD)
CreateImage(0,64,20)
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_Gradient)
BackColor($1EFDFD)
FrontColor($7878FE)
BoxedGradient(0, 0, 64, 20)
Box(0,0,64,20)
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(4, 2, "Tab One",#Red)
StopDrawing()
CreateImage(1,64,20)
StartDrawing(ImageOutput(1))
Box(0,0,64,20,$BDFEBA)
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(4, 2, "Tab Two",#Black)
StopDrawing()
Imlist = ImageList_Create_(64,20,#ILC_COLOR32,2,10)
ImageList_Add_(Imlist,ImageID(0),0)
ImageList_Add_(Imlist,ImageID(1),0)
OpenWindow(0,0,0,400,300,"Full Control Color Panel Gadget",#PB_Window_SystemMenu| #PB_Window_ScreenCentered)
SetWindowColor(0,$FEFED1)
PanelGadget(0,10,10,380,280)
SendMessage_(GadgetID(0),#TCM_SETPADDING,0,1|3<<16)
SendMessage_(GadgetID(0),#TCM_SETIMAGELIST,0,Imlist)
AddGadgetItem(0,0,"")
ButtonGadget(2, 10, 15, 80, 24,"Tab 1 Button 1")
ButtonGadget(3, 95, 15, 80, 24,"Tab 1 Button 2")
AddGadgetItem(0,1,"")
ButtonGadget(4, 10, 15, 80, 24,"Tab 2 Button 3")
ButtonGadget(5, 95, 15, 80, 24,"Tab 2 Button 4")
CloseGadgetList()
t.TC_ITEM
t\mask = #TCIF_IMAGE
t\iImage = 0
SendMessage_(GadgetID(0),#TCM_SETITEM, 0, @t)
t\iImage = 1
SendMessage_(GadgetID(0),#TCM_SETITEM, 1, @t)
;Comment for the next lines for normal background Color
SetWindowTheme_(GadgetID(0), @null.w, @null.w)
SetClassLongPtr_(GadgetID(0),#GCL_HBRBACKGROUND, Bkgcolor)
TextGadget(10,148,10,250,24,"")
SetGadgetColor(10,#PB_Gadget_BackColor,$FEFED1)
BringWindowToTop_(GadgetID(10))
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Quit = 1
EndSelect
Until Quit = 1
Last edited by RASHAD on Sun Apr 13, 2014 11:04 pm, edited 1 time in total.
Egypt my love
Re: reskinning an application (->color questions)
Full text & color control String Gadget
Text Val. & Hal centered (Work around
)
Text Val. & Hal centered (Work around

Code: Select all
CreateImage(0,300,24)
StartDrawing(ImageOutput(0))
Box(0,0,300,24,#Red)
Box(1,1,298,22,$D3FEFD)
StopDrawing()
OpenWindow(0,0,0,400,300,"", #PB_Window_SystemMenu|#PB_Window_SizeGadget| #PB_Window_ScreenCentered)
ImageGadget(0,10,10,120,24,ImageID(0))
DisableGadget(0,1)
ContainerGadget(1, 10,10,300,24)
StringGadget(2,3,4,296,16,"",#PB_String_BorderLess| #ES_center)
SetGadgetColor(2,#PB_Gadget_BackColor,$D5FEFD)
SetGadgetColor(2,#PB_Gadget_FrontColor,$FF3904)
CloseGadgetList()
SetClassLongPtr_(GadgetID(1),#GCL_HBRBACKGROUND, GetStockObject_(#NULL_BRUSH))
Repeat:Until WaitWindowEvent()=#WM_CLOSE
Egypt my love
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: reskinning an application (->color questions)
For the StringGadgets, why not use #PB_String_BorderLess?
Revised snippet using Rashad's code, Tested working fine on Win8:
Revised snippet using Rashad's code, Tested working fine on Win8:
Code: Select all
Enumeration
#Win
#Font10
#Font14B
#BtnImg
#MyOpt0
#MyOpt1
#MyOpt2
#MyChkBx0
#MyChkBx1
#MyChkBx2
#BtnExit
EndEnumeration
LoadFont(#Font10, "Arial", 10, #PB_Font_Bold | #PB_Font_HighQuality + 2)
LoadFont(#Font14B, "Arial Black", 14, #PB_Font_HighQuality + 2)
Global igWinColour.i = RGB(036,036,036)
Global igTxtColour.i = RGB(186,090,087)
Global igBackColour.i = CreateSolidBrush_(igWinColour)
Procedure DrawBtn(iBtnID.i, sText.s, iW.i, iH.i)
;-----------------------------------------------
Protected iBtnImg.i, dX.d, dY.d, dW.d, dH.d
CreateImage(#BtnImg, iW, iH, 24)
If StartDrawing(ImageOutput(#BtnImg))
DrawingFont(FontID(#Font14B))
dH = TextHeight(sText)
dW = TextWidth(sText)
dX = ((iW - dW) / 2)
dY = ((iH - dH) / 2)
DrawingMode(#PB_2DDrawing_Default)
Box(0,0,iW,iH,igWinColour)
DrawText(dX, dY, sText, igTxtColour, igWinColour)
SetGadgetAttribute(iBtnID, #PB_Button_Image, ImageID(#BtnImg))
StopDrawing()
EndIf
EndProcedure
Procedure.i WindowCallBack(WindowId.i, iMsg.i, wParam.i, lParam.i)
;-----------------------------------------------------------------
Protected iReturn.i = #PB_ProcessPureBasicEvents
If iMsg = #WM_CTLCOLORSTATIC
Select GetProp_(lParam, "PB_ID")
;API call: allows choosing gadgets by their number
;Comment out Select to apply to all gadgets
Case #MyOpt0, #MyOpt1, #MyOpt2, #MyChkBx0, #MyChkBx1, #MyChkBx2
;uncomment if compiling without XP support
SetBkMode_(wParam, #TRANSPARENT)
;SetBkColor_(wParam,igWinColour)
SetTextColor_(wParam,igTxtColour)
iReturn = igBackColour
EndSelect
EndIf
ProcedureReturn iReturn
EndProcedure
Procedure Win()
;--------------
Protected iFlags.i = #PB_Window_Invisible | #PB_Window_SystemMenu | #PB_Window_ScreenCentered
Protected iGadget.i
If OpenWindow(#Win, 0, 0, 300, 130, "Colour", iFlags)
SetWindowColor(#Win, igWinColour)
SetGadgetFont(#PB_All, FontID(#Font10))
OptionGadget(#MyOpt0, 20, 10, 120, 20, "Option 0")
OptionGadget(#MyOpt1, 20, 40, 120, 20, "Option 1")
OptionGadget(#MyOpt2, 20, 70, 120, 20, "Option 2")
CheckBoxGadget(#MyChkBx0, 150, 10, 120, 20, "Check Box 0")
CheckBoxGadget(#MyChkBx1, 150, 40, 120, 20, "Check Box 1")
CheckBoxGadget(#MyChkBx2, 150, 70, 120, 20, "Check Box 2")
ButtonImageGadget(#BtnExit, 0, 100, 300, 30, 0)
DrawBtn(#BtnExit, "EXIT", 294, 24)
For iGadget = #MyOpt0 To #MyChkBx2
SetWindowTheme_(GadgetID(iGadget), @null.w, @null.w)
Next
SetWindowCallback(@WindowCallBack(), #Win)
HideWindow(#Win, #False)
EndIf
EndProcedure
Procedure WaitForUser()
;----------------------
Protected iQuit.i = #False
Repeat
Select WaitWindowEvent(1)
Case #PB_Event_CloseWindow: iQuit = #True
Case #PB_Event_Gadget
Select EventGadget()
Case #BtnExit: iQuit = #True
EndSelect
EndSelect
Delay(1)
Until iQuit = #True
EndProcedure
Win()
WaitForUser()
End
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
Re: reskinning an application (->color questions)
sorry for being quiet for so long, i did not have a chance to check your posts until just a couple of minutes ago.
@ideas boderless puts the text in the top left corner without any padding, which looks meh. rashad's centered text is prettier.
@rashad thanks a lot for your time and effort! originally, i was hoping to get color into the thing without rewriting/custom designing gadgets. but oh well, there seems to be no way around it. however, even with your custom drawn tabs, i get a thin "white" (windows standard dialogue color) border. i will keep investigating.
@ideas boderless puts the text in the top left corner without any padding, which looks meh. rashad's centered text is prettier.
@rashad thanks a lot for your time and effort! originally, i was hoping to get color into the thing without rewriting/custom designing gadgets. but oh well, there seems to be no way around it. however, even with your custom drawn tabs, i get a thin "white" (windows standard dialogue color) border. i will keep investigating.