Page 2 of 5

Re: Object Theme Library (for Dark or Light Theme)

Posted: Wed Nov 22, 2023 1:04 am
by jacdelad
Found the culprit: Line 798 in ObjectTheme.pbi. It's a SendMessage_() call within the Callback-function. Don't know if this is even allowed, maybe it's just a timing-thing. Both demos work, if I comment it out.
Also: The ComboBox with image doesn't change color for me. Looks like it works for you.
And finally: Windows 10, x64.

Re: Object Theme Library (for Dark or Light Theme)

Posted: Wed Nov 22, 2023 11:37 am
by ChrisR
Cool that you found it 8)
But I don't really understand why! it should be possible to send a message (even in a callback) to change the theme depending on whether the Gadget is enabled or disabled.
This is what I tried to do for the checkbox, option and TrackBar, to see the disabled state, grayed out. By changing the theme when the message WM_ENABLE is received.
I'll take another look to see how I could do it differently, thanks for the feedback :)

Re: Object Theme Library (for Dark or Light Theme)

Posted: Wed Nov 22, 2023 1:30 pm
by jacdelad
I'm not sure, but maybe this creates an endless recursion or something like that.

Re: Object Theme Library (for Dark or Light Theme)

Posted: Wed Nov 22, 2023 4:13 pm
by ChrisR
I've removed my SetWindowTheme tweak and also the StaticProc callback, which is no longer needed.
it's simpler and better this way.
Thanks :) it's uploaded on Github v1.2

Re: Object Theme Library (for Dark or Light Theme)

Posted: Wed Nov 22, 2023 8:05 pm
by novablue
Very nice! I would like to ask if you could put as much of your code as possible into a module for better code separation?

Re: Object Theme Library (for Dark or Light Theme)

Posted: Wed Nov 22, 2023 10:16 pm
by jacdelad
I downloaded version 1.2, but it crashes again, this time at line 836, another SendMessage_() within the callback procedure.

Re: Object Theme Library (for Dark or Light Theme)

Posted: Thu Nov 23, 2023 12:12 pm
by ChrisR
Very strange, I don't know why you have this, as for the previous one, I don't reproduce despite the number of tries made.
There should be no worries, endless recursion...by using SendMessage_(lParam, #EM_SETSEL, -1, 0) in the Window Callback. There's no reason and it's been working like that for a while now in ObjectColor with no return!
And here, it is useful to deselect the ComboBox editable string if it is not the active Gadget. Otherwise, the text would be selected after each use of SetObjectTheme()
Does anyone else reproduce or have any idea why jacdelad has this error that I don't have ?

Re: Object Theme Library (for Dark or Light Theme)

Posted: Thu Nov 23, 2023 12:25 pm
by ChrisR
novablue wrote: Wed Nov 22, 2023 8:05 pm Very nice! I would like to ask if you could put as much of your code as possible into a module for better code separation?
I'm not always a fan of modules but here it's appropriate, it works by itself, without the need for postevent()...
I've updated it as a module, on Github in version 1.3 now.
UseModule ObjectTheme is mandatory to call macros directly (e.g. ButtonGadget) without having to change existing code and use ObjectTheme::ButtonGadget.

Re: Object Theme Library (for Dark or Light Theme)

Posted: Thu Nov 23, 2023 6:34 pm
by Kuron
novablue wrote: Wed Nov 22, 2023 8:05 pm Very nice! I would like to ask if you could put as much of your code as possible into a module for better code separation?
I would ask that he DOESN'T.

Re: Object Theme Library (for Dark or Light Theme)

Posted: Thu Nov 23, 2023 7:31 pm
by ChrisR
It shouldn't be too hard to maintain the 2 versions, standard and module, they are very close.
The 2 versions are on GitHub, the module version at the root and the standard version in the Non-Module_Version folder.

I'm a bit annoyed by jacdelad bugs that I don't understand at all, so thanks for the feedback to know how it goes for you?
In case of crash, it would be good to have Callstack infos

Re: Object Theme Library (for Dark or Light Theme)

Posted: Thu Nov 23, 2023 7:33 pm
by Little John
ChrisR wrote: Thu Nov 23, 2023 12:12 pm Does anyone else reproduce or have any idea why jacdelad has this error that I don't have ?
I don't encounter any issues with this library here (on Windows 11). For me, version 1.3 works as well as version 1.0 did.

Re: Object Theme Library (for Dark or Light Theme)

Posted: Thu Nov 23, 2023 11:30 pm
by jacdelad
It's even getting stranger for me: I put a Debug right before said SendMessage_() and it always works about a hundred times or so before crashing at also said position.

I tried using #WM_GETTEXT and #WM_SETTEXT. It doesn't crash, but rendering doesn't work anymore...

Re: Object Theme Library (for Dark or Light Theme)

Posted: Fri Nov 24, 2023 12:16 pm
by ChrisR
Little John wrote: Thu Nov 23, 2023 7:33 pm
ChrisR wrote: Thu Nov 23, 2023 12:12 pm Does anyone else reproduce or have any idea why jacdelad has this error that I don't have ?
I don't encounter any issues with this library here (on Windows 11). For me, version 1.3 works as well as version 1.0 did.
Thanks for your confirmation Little John.
Just for further testing, I added this snippet to ObjectTheme_Demo.pb, to change theme every 10s and with 10 call to SendMessage_(lParam, #EM_SETSEL, -1, 0) each time.
And I let it running all night, with no problems, no bugs and no memory leaks.
So it's up to jacdelad!

Code: Select all

Procedure Thread(Value)
  PostEvent(#PB_Event_Gadget, #Window_1, #ApplyTheme_1, #PB_EventType_LeftClick)
  Delay(Value)
  CreateThread(@Thread(),10000)
EndProcedure
........
Open_Window_1()
Open_Window_2()

CreateThread(@Thread(), 10000)

Re: Object Theme Library (for Dark or Light Theme)

Posted: Fri Nov 24, 2023 2:33 pm
by dcr3
First time trying it, I haven't tried previous versions. So I can't comment on it.

On this version 1.3, It crashes on the 64bit, on the 32bit there is a stack overflow at line 1030.

Re: Object Theme Library (for Dark or Light Theme)

Posted: Fri Nov 24, 2023 4:55 pm
by ChrisR
Gulp!
If you're compiling in x64, what does the OnError window say when it crashes?
In x86, can you please send the Debug\Callstack infos, screenshot or info with lines and procedure.

There's a bit of work behind it and I wouldn't want to put it in the trash.
It seems to work well for me and Little John but not for you and jacdelad. What's wrong!!!

Does it also crash with this summary code?
And possibly, does ObjectColor crash as well?

Code: Select all

EnableExplicit

Enumeration Window
  #Window
EndEnumeration

Enumeration Gadgets
  #String
  #Combo
  #Btn_Change_Color
EndEnumeration

Global BaseColor.l    = $2A0408
Global BrushBaseColor = CreateSolidBrush_(BaseColor)
Global NewColor.l     = $04082A
Global BrushNewColor  = CreateSolidBrush_(NewColor)
Global BrushHighLight = CreateSolidBrush_(GetSysColor_(#COLOR_HIGHLIGHT))

Procedure SetComboDarkMode(IDGadget)
  Protected ChildGadget, Buffer.s = Space(64)

  If GetClassName_(IDGadget, @Buffer, 64)
    If Buffer = "ComboBox"
      SetWindowTheme_(IDGadget, "DarkMode_CFD", "Combobox")
    EndIf
  EndIf
  ChildGadget = GetWindow_(IDGadget, #GW_CHILD)
  If ChildGadget
    Buffer = Space(64)
    If GetClassName_(ChildGadget, @Buffer, 64)
      If Buffer = "ComboBox"
        SetWindowTheme_(ChildGadget, "DarkMode_CFD", "Combobox")
      EndIf 
    EndIf
  EndIf
EndProcedure

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
  Protected Result = #PB_ProcessPureBasicEvents
  Protected Gadget, ParentGadget, Buffer.s, Text.s
  Protected *DrawItem.DRAWITEMSTRUCT
  
  Select uMsg
    Case #WM_CLOSE
      PostEvent(#PB_Event_Gadget, GetDlgCtrlID_(hWnd), 0, #PB_Event_CloseWindow)
      
    Case #WM_NCDESTROY
      DeleteObject_(BrushBaseColor)
      DeleteObject_(BrushNewColor)
      DeleteObject_(BrushHighLight)
      
    Case #WM_CTLCOLOREDIT
      ParentGadget = GetParent_(lParam)
      Buffer = Space(64)
      If GetClassName_(ParentGadget, @Buffer, 64)
        If Buffer = "ComboBox"
          Gadget = GetDlgCtrlID_(ParentGadget)
          If Gadget <> GetActiveGadget()
            ; TRY by commenting the SendMessage below, the text in the ComboBox edit part is selected, as long as it has not been deselected
            SendMessage_(lParam, #EM_SETSEL, -1, 0)   ; Deselect the ComboBox editable string if not the active Gadget
          EndIf
          SetTextColor_(wParam, #White)
          SetBkMode_(wParam, #TRANSPARENT)
          If GetWindowColor(#Window) = BaseColor
            ProcedureReturn BrushBaseColor
          Else
            ProcedureReturn BrushNewColor
          EndIf
        EndIf
      EndIf
      
    Case #WM_DRAWITEM
      *DrawItem.DRAWITEMSTRUCT = lParam
      If *DrawItem\CtlType = #ODT_COMBOBOX And IsGadget(wParam) And *DrawItem\itemID <> -1
        If *DrawItem\itemstate & #ODS_SELECTED
          FillRect_(*DrawItem\hDC, *DrawItem\rcitem, BrushHighLight)
        Else
          If GetWindowColor(#Window) = BaseColor
            FillRect_(*DrawItem\hDC, *DrawItem\rcitem, BrushBaseColor)
          Else
            FillRect_(*DrawItem\hDC, *DrawItem\rcitem, BrushNewColor)
          EndIf
        EndIf
        
        SetBkMode_(*DrawItem\hDC, #TRANSPARENT)
        SetTextColor_(*DrawItem\hDC, #White)
        Text = GetGadgetItemText(*DrawItem\CtlID, *DrawItem\itemID)
        *DrawItem\rcItem\left + DesktopScaledX(4)
        DrawText_(*DrawItem\hDC, Text, Len(Text), *DrawItem\rcItem, #DT_LEFT | #DT_SINGLELINE | #DT_VCENTER)
      EndIf
      
  EndSelect
  
  ProcedureReturn Result
EndProcedure

Procedure Open_Window(X = 0, Y = 0, Width = 220, Height = 175)
  Protected I
  If OpenWindow(#Window, X, Y, Width, Height, "CTLCOLOREDIT", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    SetWindowColor(#Window, BaseColor)
    StringGadget(#String, 20, 20, 180, 24, "String")
    SetGadgetColor(#String, #PB_Gadget_FrontColor, #White)
    SetGadgetColor(#String, #PB_Gadget_BackColor, BaseColor)
    ComboBoxGadget(#Combo, 20, 65, 180, 28, #PB_ComboBox_Editable | #CBS_HASSTRINGS | #CBS_OWNERDRAWFIXED)
    SendMessage_(GadgetID(#Combo), #CB_SETMINVISIBLE, 5, 0)
    For I = 1 To 10 : AddGadgetItem(#Combo, -1, "Combo Element " + Str(I)) : Next
    SetGadgetState(#Combo, 0)
    ButtonGadget(#Btn_Change_Color, 20, 115, 180, 40, "Change_Color")
    
    SetComboDarkMode(GadgetID(#Combo))
    SetWindowCallback(@WinCallback(), #Window)
    ProcedureReturn #True
  EndIf
EndProcedure

If Open_Window()
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #Btn_Change_Color
            If GetWindowColor(#Window) = BaseColor
              SetWindowColor(#Window, NewColor)
              SetGadgetColor(#String, #PB_Gadget_BackColor, NewColor)
            Else
              SetWindowColor(#Window, BaseColor)
              SetGadgetColor(#String, #PB_Gadget_BackColor, BaseColor)
            EndIf
        EndSelect
    EndSelect
  ForEver
EndIf