Page 4 of 5

Re: ObjectColor (Dark Mode)

Posted: Sun May 08, 2022 1:20 pm
by ChrisR
BarryG wrote: Sun May 08, 2022 11:51 am That's what I'm currently doing. All windows are created invisibly at first, with all gadgets, and then I'm using SetObjectColor() on them - similar to the code I posted above.
If it is done so, with All gadgets created before SetObjectColor(), a single call to SetObjectColor() should probably be enough.
I don't know for your unpainted ListIconGadget in your pop-up window, ListIconProc() callback should be called normally.
BarryG wrote: Sun May 08, 2022 5:17 am may I suggest that "SetWindowColor(w,darkcolor)" be done as part of SetObjectColor()?
Done and uploaded to GitHub, it's better this way, thanks :)

Re: ObjectColor (Dark Mode)

Posted: Sun May 08, 2022 1:50 pm
by ChrisR
BarryG wrote: Sun May 08, 2022 11:51 am In my case, there's only a ListIconGadget() that doesn't get colored dark in that pop-up window, but its other two gadgets become dark.
Can you try adding this in WinCallback()

Code: Select all

Case #WM_ACTIVATE
  RedrawWindow_(hWnd, #Null, #Null, #RDW_INVALIDATE | #RDW_ERASE | #RDW_ALLCHILDREN | #RDW_UPDATENOW)

Re: ObjectColor (Dark Mode)

Posted: Mon May 09, 2022 2:19 am
by BarryG
Testing for #WM_ACTIVATE didn't make any difference, ChrisR. Below is a (partial) screenshot of the affected window, where you can see the problems.

The ComboBox at top is dark, but its editable text is not white.
The ListIcon is not dark at all.
The Editor background is dark, but its text is not white.

I was doing this to the window:

Code: Select all

colordarkmode=RGB(50,50,50)
SetDarkTheme()
SetWindowColor(win,colordarkmode)
SetObjectColor(win,#PB_All,colordarkmode)
Image

Sorry for all the hassle!

Re: ObjectColor (Dark Mode)

Posted: Tue May 10, 2022 1:07 pm
by ChrisR
Sorry for the late reply, I was not available yesterday.

Good point BarryG,
I had not tested the SplitterGadget. It was not managed as a container and so the colors were not passed on to its children.

It is done now and it is also painted according to its parent background color.
Based on chi's SplitterExt Module :)
There are 3 constants for the Splitter that we can play with:

Code: Select all

#UseUxGripper   = #False   ; #False = Custom, #True = Uxtheme
#LargeGripper   = #True    ; #False
#SplitterBorder = #False   ; #True

Re: ObjectColor (Dark Mode)

Posted: Tue May 10, 2022 1:22 pm
by ChrisR
For the SplitterGadget Test, like yours:

Code: Select all

EnableExplicit

Enumeration Window
  #Window
EndEnumeration

Enumeration Gadgets
  #Combo
  #ListIcon
  #Editor
  #Splitter
EndEnumeration

XIncludeFile "ObjectColor.pbi"

Procedure Open_Window(X = 0, Y = 0, Width = 320, Height = 260)
  Protected I 
  If OpenWindow(#Window, X, Y, Width, Height, "Title", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ComboBoxGadget(#Combo, 10, 10, 300, 28, #CBS_HASSTRINGS|#CBS_OWNERDRAWFIXED)
    For I = 1 To 5 : AddGadgetItem(#Combo, -1,"ComboBox Element " + Str(I)) : Next
    SetGadgetState(#Combo, 1)

    ListIconGadget(#ListIcon, 0, 0, 0, 0, "ListIcon Column 1", 180)
    AddGadgetColumn(#ListIcon, 1, "Column 2", 120)
    For I = 1 To 5 : AddGadgetItem(#ListIcon, -1,"Column 1 Element " + Str(I) +Chr(10)+ "Column 2 Element " + Str(I)) : Next
    EditorGadget(#Editor, 0, 0, 0, 0)
    For I = 0 To 5 : AddGadgetItem(#Editor, I, "Editor Line " + Str(I)) : Next 
    
    SplitterGadget(#Splitter, 10, 50, 300, 200, #ListIcon, #Editor, #PB_Splitter_Separator)
    SetGadgetState(#Splitter, 110)
  EndIf
EndProcedure

Open_Window()

SetDarkTheme()
SetObjectColor(#Window, #PB_All, RGB(50,50,50))

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

Image

Re: ObjectColor (Dark Mode)

Posted: Wed May 11, 2022 2:08 am
by BarryG
Hi ChrisR! Thanks for the update! I appreciate your help. Hope you're not taking offense to all these issues - I just want your code to be rock-solid so it can be dropped into any app and work flawlessly. <Wink>. Only three small issues left at the moment.

Issue 1

I can confirm the latest code works better with my window now except for one bit: the background color of an editable ComboBox is still white instead of dark, like in the screenshot and test code below.

Image

My test code:

Code: Select all

XIncludeFile "ObjectColor.pbi"

Enumeration Window
  #Window_1
  #Window_2
EndEnumeration

Enumeration Gadgets
  #Combo
  #ListIcon
  #Editor
  #Splitter
EndEnumeration

If OpenWindow(#Window_1, 200, 200, 320, 60, "Window 1", #PB_Window_SystemMenu)
  button = ButtonGadget(#PB_Any, 10, 20, 300, 25, "Click to open second window")
EndIf

If OpenWindow(#Window_2, 600, 200, 320, 260, "Window 2", #PB_Window_SystemMenu | #PB_Window_Invisible)
  ComboBoxGadget(#Combo, 10, 10, 300, 28, #PB_ComboBox_Editable | #CBS_HASSTRINGS | #CBS_OWNERDRAWFIXED)
  For I = 1 To 5 : AddGadgetItem(#Combo, -1,"ComboBox Element " + Str(I)) : Next
  SetGadgetState(#Combo, 1)
  
  ListIconGadget(#ListIcon, 0, 0, 0, 0, "ListIcon Column 1", 180)
  AddGadgetColumn(#ListIcon, 1, "Column 2", 120)
  For I = 1 To 5 : AddGadgetItem(#ListIcon, -1,"Column 1 Element " + Str(I) +Chr(10)+ "Column 2 Element " + Str(I)) : Next
  EditorGadget(#Editor, 0, 0, 0, 0)
  For I = 0 To 5 : AddGadgetItem(#Editor, I, "Editor Line " + Str(I)) : Next 
  
  SplitterGadget(#Splitter, 10, 50, 300, 200, #ListIcon, #Editor, #PB_Splitter_Separator)
  SetGadgetState(#Splitter, 110)
EndIf

SetDarkTheme()
SetObjectColor(#PB_All, #PB_All, RGB(50,50,50))

Repeat
  ev = WaitWindowEvent()
  If ev = #PB_Event_Gadget And EventGadget() = button
    HideWindow(#Window_2, #False)
  EndIf
Until ev = #PB_Event_CloseWindow
Issue 2

I have another window that gets opened on demand by the app (after selecting a menu item on the main window to open it), and only its background color goes dark. Its TextGadget and ListIcon don't go dark at all. See the below screenshot of its top-right corner (for privacy) and the code I'm using to open it and make it dark (not compilable, but surely it shows if I'm doing something wrong?).

Image

Code: Select all

win=OpenWindow(#PB_Any,0,0,w,h,"Window",#PB_Window_Invisible|#PB_Window_SystemMenu|#PB_Window_WindowCentered,app) ; app = Main app window.
If win
  txt=TextGadget(#PB_Any,6,5,w-(15),20,"text text",#PB_Text_Center)
  lig=ListIconGadget(#PB_Any,0,29,w,h-(29),n$,w-sw,#LVS_NOCOLUMNHEADER|#PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_MultiSelect|#PB_ListIcon_GridLines)
  AddGadgetColumn(lig,1,"Header",0)
  For i=1 To ws
    AddGadgetItem(lig,-1,w$(i))
  Next
  SetObjectColor(win,#PB_All,colordarkmode) ; Doesn't make TXT or LIG gadgets go dark.
  SetActiveGadget(lig)
  HideWindow(win,0)
  Repeat
    ev=WaitWindowEvent()
    ...
Issue 3

When my main app's window is hidden (HideWindow) and then shown, or unminimized from a minimized state, the ListIcon backgrounds show white briefly before changing back to dark. A noticeable flash. Any tips on how to stop that? Thanks.

Re: ObjectColor (Dark Mode)

Posted: Wed May 11, 2022 5:26 pm
by ChrisR
BarryG wrote: Wed May 11, 2022 2:08 am Hi ChrisR! Thanks for the update! I appreciate your help. Hope you're not taking offense to all these issues - I just want your code to be rock-solid so it can be dropped into any app and work flawlessly. <Wink>. Only three small issues left at the moment.
You're welcome, no worries at all, it allows to improve the tools :)
I would also like it to be as complete as possible and there are still a few things missing but it's progressing, slowly, slowly
For some stuff, like the icons on the tabs, I would need examples as a starting point, I don't know how to do.

For your 1st issue, for the Editable ComboBox, I have updated to also paint the Edit part with the colors now.
And on Windows 10 with the DarkTheme, the ComboBox Image is now partially supported by applying the theme on its chid.
Do not add #CBS_HASSTRINGS|#CBS_OWNERDRAWFIXED for ComboBox Image, only ComboBoxGadget(#Combo,X,Y,W,H,#PB_ComboBox_Image)

For the 3rd, I don't know, I added the code below but not sure if it changes anything:

Code: Select all

    Case #WM_SIZE
      If wParam = #SIZE_RESTORED   ; Not sure if there is a need
        For I = 0 To CountWindow - 1
          If Window(1, I) = hWnd
            RedrawWindow_(hWnd, #Null, #Null, #RDW_INVALIDATE | #RDW_ERASE | #RDW_ALLCHILDREN | #RDW_UPDATENOW)
            Break
          EndIf
        Next
      EndIf
It's uploaded on Github

Re: ObjectColor (Dark Mode)

Posted: Wed May 11, 2022 5:44 pm
by ChrisR
BarryG wrote: Wed May 11, 2022 2:08 am I have another window that gets opened on demand by the app (after selecting a menu item on the main window to open it), and only its background color goes dark. Its TextGadget and ListIcon don't go dark at all. See the below screenshot of its top-right corner (for privacy) and the code I'm using to open it and make it dark (not compilable, but surely it shows if I'm doing something wrong?).
Hi BarryG,
I don't really know why, I don't reproduce with the code below.
Maybe you have several calls to SetObjectColor.
For info, unless the color changes, it should only be called once.
The list (enumerations) of Windows and Gadgets is made only once, at the first use.
And so, to works, all windows and gadgets must be created before the 1st call with #PB_Window_Invisible if needed.

Code: Select all

XIncludeFile "ObjectColor.pbi"

Enumeration Window
  #Window_1
  #Window_2
EndEnumeration

Enumeration Gadgets
  #Combo
  #ListIcon
  #Editor
  #Splitter
EndEnumeration

Global Win, Button, Event, I

If OpenWindow(#Window_1, 200, 200, 320, 260, "Window 1", #PB_Window_SystemMenu)
  Button = ButtonGadget(#PB_Any, 10, 15, 300, 25, "Click to open second window")
EndIf

Win = OpenWindow(#PB_Any, 200, 300, 320, 100, "Window", #PB_Window_Invisible | #PB_Window_SystemMenu | #PB_Window_WindowCentered, WindowID(#Window_1)) ; app = Main app window.
If Win
  Define Txt = TextGadget(#PB_Any, 6, 5, 300, 20, "text text", #PB_Text_Center)
  Define Lig = ListIconGadget(#PB_Any, 0, 29, 320, 60, "ListIcon", 180, #LVS_NOCOLUMNHEADER | #PB_ListIcon_FullRowSelect | #PB_ListIcon_AlwaysShowSelection | #PB_ListIcon_MultiSelect | #PB_ListIcon_GridLines)
  AddGadgetColumn(Lig, 1, "Header", 0)
  For i = 1 To 5
    AddGadgetItem(Lig,  -1, "Element " + Str(i))
  Next
  ; SetObjectColor(Win, #PB_All, RGB(50,50,50))
  ; If SetObjectColor() is done here, the Windows And Gadgets created after are Not enumerated.
  ; Even If SetObjectColor() is called afterwards For all windows (#PB_All). The Windows And Gadgets Enumeration is done only once.
  SetActiveGadget(Lig)
EndIf

If OpenWindow(#Window_2, 600, 200, 320, 260, "Window 2", #PB_Window_SystemMenu | #PB_Window_Invisible)
  ComboBoxGadget(#Combo, 10, 10, 300, 28, #PB_ComboBox_Editable | #CBS_HASSTRINGS | #CBS_OWNERDRAWFIXED)
  For I = 1 To 5 : AddGadgetItem(#Combo, -1, "ComboBox Element " + Str(I)) : Next
  SetGadgetState(#Combo, 1)
  
  ListIconGadget(#ListIcon, 0, 0, 0, 0, "ListIcon Column 1", 180)
  AddGadgetColumn(#ListIcon, 1, "Column 2", 120)
  For I = 1 To 5 : AddGadgetItem(#ListIcon, -1, "Column 1 Element " + Str(I) + Chr(10) + "Column 2 Element " + Str(I)) : Next
  EditorGadget(#Editor, 0, 0, 0, 0)
  For I = 0 To 5 : AddGadgetItem(#Editor, I, "Editor Line " + Str(I)) : Next
  
  SplitterGadget(#Splitter, 10, 50, 300, 200, #ListIcon, #Editor, #PB_Splitter_Separator)
  SetGadgetState(#Splitter, 110)
EndIf

SetDarkTheme()
SetObjectColor(#PB_All, #PB_All, RGB(50, 50, 50))

Repeat
  Event = WaitWindowEvent()
  Select Event
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = Button
        HideWindow(#Window_2, #False)
        HideWindow(Win, #False)
      EndIf
  EndSelect
ForEver

Re: ObjectColor (Dark Mode)

Posted: Thu May 12, 2022 12:11 pm
by BarryG
ChrisR wrote:Maybe you have several calls to SetObjectColor.
The list (enumerations) of Windows and Gadgets is made only once, at the first use.
And so, to works, all windows and gadgets must be created before the 1st call with #PB_Window_Invisible if needed.
Oh... I think that's my problem. Yes, I've been using "SetObjectColor(win,#PB_All,colordarkmode" after every OpenWindow command. So I need to create all the windows first, then just one single call of SetObjectColor() to cover them all? Dang, that won't work for me as a lot of my windows are created on demand because they're not needed until the user chooses, and there's no way for my app to know how many windows the user will want to open. So I don't think this is going to work for me after all. <Sad>. It'd be much better if dark mode could somehow be applied to a window after it's been created.

Sorry for wasting your time due to my misunderstanding. I fear you may have made bug fixes or workarounds where none were actually needed.

Re: ObjectColor (Dark Mode)

Posted: Fri May 13, 2022 11:07 am
by ChrisR
@BarryG, In relation to your (previous!) message on JellyButton disabled, badly displayed.
I handle the WM_ENABLE message now with an InvalidateRect(). It seems to fix the JellyButton display.
And in addition to the grey text, I added an image disabled, greyed, to better see its state.
JellyButton is available in IceDesign.

Re: ObjectColor (Dark Mode)

Posted: Sat May 14, 2022 1:07 am
by BarryG
Thanks, downloaded. I did try the original JellyButton code in this forum without using your ObjectColor code, and it also showed the problem. And the reason I removed my original JellyButton bug report was because I assumed it was due to my incorrect use of ObjectColor, so I didn't want you to chase a possible non-bug.

I'll try it tomorrow as I'm leaving the house in a few minutes. I have no doubts it'll work, though.

[Edit] Yep, I'm happy to report that your new version works correctly.

Re: ObjectColor (Dark Mode)

Posted: Fri Jan 27, 2023 3:40 pm
by ChrisR
Update ObjectColor v1.3.0

  • Supports as many SetObjectColor() calls as desired, even with dynamic Windows.
  • The theme Light: "Explorer" or Dark:" DarkMode_Explorer" (Windows 10 and up) is automatically applied according to the OS version and Background Color of each Gadget.

    About Theme, after calling SetObjectColor(), you can change the applied theme by using one of the 2 macros: SetDarkTheme(Gadget) or SetExplorerTheme(Gadget)
    For example, if you have a Window with a Dark Background Color and a ScrollArea with a Light Color,
    By default, the Light Theme will be applied for the ScollArea and its ScrollBars related to the ScrollArea Background Color.
    But you may want to change it to a Dark Theme to match the Window which is in Dark Color. It would be like this

    Code: Select all

    SetObjectColor(#PB_All, #PB_All, #Black)
    SetObjectColor(#Windows, #ScrollArea, #Gray)
    SetDarkTheme(#ScrollArea)

Re: ObjectColor (Dark Mode)

Posted: Fri Jan 27, 2023 4:12 pm
by Fred
It's really a great piece a work ! Dark mode on Windows is a pain to achieve

Re: ObjectColor (Dark Mode)

Posted: Sat Jan 28, 2023 12:37 am
by ChrisR
Thanks Fred :)

Re: ObjectColor (Dark Mode)

Posted: Sat Jan 28, 2023 2:07 am
by BarryG
ChrisR wrote: Fri Jan 27, 2023 3:40 pmSupports as many SetObjectColor() calls as desired, even with dynamic Windows.
Does this mean I can use it on windows that are created on-the-fly now? Like for my app where the number of windows is indeterminate and are opened/closed during runtime of my app?