SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Share your advanced PureBasic knowledge/code with the community.
User avatar
Zapman
Enthusiast
Enthusiast
Posts: 205
Joined: Tue Jan 07, 2020 7:27 pm

Re: SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Post by Zapman »

Thanks Azijio. Its a copy/paste error. I fixed it.
Thank you.
User avatar
Zapman
Enthusiast
Enthusiast
Posts: 205
Joined: Tue Jan 07, 2020 7:27 pm

Re: SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Post by Zapman »

ChrisR wrote: Sat Feb 01, 2025 11:00 pm Nice work Luc, everything seems to work well here, thanks for sharing :)
Tested with ObjectTheme.pbi enabled: no problems encountered, no adjustments to make. The two libraries are perfectly compatible and can be used together. :D
User avatar
ChrisR
Addict
Addict
Posts: 1466
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Post by ChrisR »

Thanks for testing it, great to know that the 2 work together.
Having the Menus in color, with font.. is a real bonus to ObjectTheme.
Not much time to test it and for PB at the moment, I'm starting preparations to sell my house with a view to moving to the South-West
User avatar
Zapman
Enthusiast
Enthusiast
Posts: 205
Joined: Tue Jan 07, 2020 7:27 pm

Re: SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Post by Zapman »

ChrisR wrote: Mon Feb 03, 2025 9:59 pmNot much time to test it and for PB at the moment, I'm starting preparations to sell my house with a view to moving to the South-West
California? There's nothing like the sun!
I you still find some time, I've a question for you:
My menu library uses two colors by default (when the user has not defined them): Backcolor and TextColor.
To get default colors defined by ObjectTheme.pbi, I use the following:

Code: Select all

            CompilerIf Defined(ObjectTheme, #PB_Module)
              ; Manage compatibility with the ObjectTheme.pbi library:
              TextColor = ObjectTheme::GetObjectThemeAttribute(#PB_GadgetType_Button, #PB_Gadget_FrontColor)
            CompilerEndIf
            CompilerIf Defined(ObjectTheme, #PB_Module)
              ; Manage compatibility with the ObjectTheme.pbi library:
              BackColor = ObjectTheme::GetObjectThemeAttribute(0, #PB_Gadget_BackColor)
            CompilerEndIf 
Do you think I do that well or is there a better way?

Here is how it looks like:
Image
User avatar
ChrisR
Addict
Addict
Posts: 1466
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Post by ChrisR »

California, I would like it but I would be too afraid of being expelled :)
I prefer our Southwest a little less sunny and a little more humid, ideal for our renowned red wine.

I've updated the latest ObjectTheme version on Github: https://github.com/ChrisRfr/ObjectTheme
And I made a code snippet, below, to test the 2 libraries together.

The “OwnerDraw” ComboBox was not drawn, without #WM_DRAWITEM event in ObjectTheme.
It looks better by commenting "ProcedureReturn #True" at the end of #WM_DRAWITEM in SetMenuItemEx.pbi, so the original callback is called.

Otherwise, I have a bug when the menu is displayed for the first time, MenuItem are seen as MenuTitle!
It's better afterwards, when I recreate it by pressing the "Apply xxxx Theme" button.

Code: Select all

XIncludeFile "ObjectTheme.pbi" : UseModule ObjectTheme
XIncludeFile "SetMenuItemEx.pbi"

Enumeration Window
  #Window
EndEnumeration

Enumeration MenuToolStatusBar
  #MainMenu
EndEnumeration

Enumeration MenuItems
  #Menu_New
  #Menu_Open
  #Menu_Save
  #Menu_Quit
  #Menu_About
EndEnumeration

Enumeration Gadgets
  #Checkbox
  #Option_1
  #Option_2
  #Combo
  #Editor
  #String
  #ApplyTheme
EndEnumeration

Procedure IsDarkColor(Color)
  If Red(Color)*0.299 + Green(Color)*0.587 + Blue(Color)*0.114 < 128   ; Based on Human perception of color, following the RGB values (0.299, 0.587, 0.114)
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure Menu_Window()
  Protected Menu_Title, Menu_Bar, Menu_Help
  Protected BackColor, FrontColor
  BackColor = GetObjectThemeAttribute(#PB_WindowType, #PB_Gadget_BackColor)
  If IsDarkColor(BackColor) : FrontColor = #White : Else : FrontColor = #Black : EndIf   ; Or GetObjectThemeAttribute(#PB_GadgetType_Text, #PB_Gadget_FrontColor)
  ;Or BackColor = GetObjectThemeAttribute(#PB_GadgetType_Button, #PB_Gadget_BackColor) : FrontColor = GetObjectThemeAttribute(#PB_GadgetType_Button, #PB_Gadget_FrontColor)
  If CreateMenu(#MainMenu, WindowID(#Window))
    Menu_Title = MenuTitle("File")
    SetMenuTitleColor(#MainMenu, Menu_Title, #PB_Gadget_BackColor, BackColor) : SetMenuTitleColor(#MainMenu, Menu_Title, #PB_Gadget_FrontColor, FrontColor)
    MenuItem(#Menu_New, "New")
    SetMenuItemColor(#MainMenu, #Menu_New,   #PB_Gadget_BackColor, BackColor) : SetMenuItemColor(#MainMenu, #Menu_New,   #PB_Gadget_FrontColor, FrontColor)
    MenuItem(#Menu_Open, "Open...")
    SetMenuItemColor(#MainMenu, #Menu_Open,  #PB_Gadget_BackColor, BackColor) : SetMenuItemColor(#MainMenu, #Menu_Open,  #PB_Gadget_FrontColor, FrontColor)
    MenuItem(#Menu_Save, "Save")
    SetMenuItemColor(#MainMenu, #Menu_Save,  #PB_Gadget_BackColor, BackColor) : SetMenuItemColor(#MainMenu, #Menu_Save,  #PB_Gadget_FrontColor, FrontColor)
    Menu_Bar = MenuBar()
    SetMenuItemColor(#MainMenu, Menu_Bar,    #PB_Gadget_BackColor, BackColor) : SetMenuItemColor(#MainMenu, Menu_Bar,    #PB_Gadget_FrontColor, FrontColor)
    MenuItem(#Menu_Quit, "&Quit")
    SetMenuItemColor(#MainMenu, #Menu_Quit,  #PB_Gadget_BackColor, BackColor) : SetMenuItemColor(#MainMenu, #Menu_Quit,  #PB_Gadget_FrontColor, FrontColor)
    Menu_Help = MenuTitle("?")
    SetMenuTitleColor(#MainMenu, Menu_Help,  #PB_Gadget_BackColor, BackColor) : SetMenuTitleColor(#MainMenu, Menu_Help,  #PB_Gadget_FrontColor, FrontColor)
    MenuItem(#Menu_About, "About")
    SetMenuItemColor(#MainMenu, #Menu_About, #PB_Gadget_BackColor, BackColor) : SetMenuItemColor(#MainMenu, #Menu_About, #PB_Gadget_FrontColor, FrontColor)   
  EndIf
EndProcedure

Procedure Open_Window(X = 0, Y = 0, Width = 400, Height = 300)
  If OpenWindow(#Window, X, Y, Width, Height, "Simple Demo ObjectTheme", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    CheckBoxGadget(#Checkbox, 20, 10, 210, 24, "Checkbox")
    OptionGadget(#Option_1, 270, 10, 110, 24, "Option 1")
    OptionGadget(#Option_2, 270, 40, 110, 24, "Option 2")      
    ComboBoxGadget(#Combo, 20, 40, 210, 28, #CBS_HASSTRINGS | #CBS_OWNERDRAWFIXED)   ;  <== Specific ComboBox, Add the 2 Constants to be drawn.
    AddGadgetItem(#Combo, -1, "Combo Element 1") : AddGadgetItem(#Combo, -1, "Combo Element 2")  : AddGadgetItem(#Combo, -1, "Combo Element 3")
    SetGadgetState(#Combo, 0)
    EditorGadget(#Editor, 20, 80, 360, 80)
    AddGadgetItem(#Editor, -1, "Editor Line 1") : AddGadgetItem(#Editor, -1, "Editor Line 2") : AddGadgetItem(#Editor, -1, "Editor Line 3")
    StringGadget(#String, 20, 170, 360, 24, "String")
    ButtonGadget(#ApplyTheme, 20, 210, 360, 50, "Apply Light Blue Theme")
    ProcedureReturn #True
  EndIf
EndProcedure

If Open_Window()
 SetObjectTheme(#ObjectTheme_DarkBlue) 
 Menu_Window()
 
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break
      Case #PB_Event_Menu
        Select EventMenu()
          Case #Menu_Quit
            Break
        EndSelect
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #ApplyTheme
            Select GetObjectTheme()
              Case #ObjectTheme_DarkBlue
                SetGadgetText(#ApplyTheme, "Apply Dark Red Theme")
                SetObjectTheme(#ObjectTheme_LightBlue)
                Menu_Window()
              Case #ObjectTheme_LightBlue
                SetGadgetText(#ApplyTheme, "Apply Dark Blue Theme")
                SetObjectTheme(#ObjectTheme_DarkRed)
                Menu_Window()
              Case #ObjectTheme_DarkRed
                SetGadgetText(#ApplyTheme, "Apply Light Blue Theme")
                SetObjectTheme(#ObjectTheme_DarkBlue)
                Menu_Window()
            EndSelect
        EndSelect
    EndSelect
  ForEver
EndIf
User avatar
Zapman
Enthusiast
Enthusiast
Posts: 205
Joined: Tue Jan 07, 2020 7:27 pm

Re: SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Post by Zapman »

Hi ChrisR,

A new version (Feb 6-2025) is available in this zip:
https://www.editions-humanis.com/downlo ... olorEx.zip
Here is how it looks like now:
Image
ChrisR wrote: Thu Feb 06, 2025 2:20 amCalifornia, I would like it but I would be too afraid of being expelled :)
I prefer our Southwest a little less sunny and a little more humid, ideal for our renowned red wine.
Sorry. You write English so well that I thought you were American! My daughter lives in Salvagnac. I love the region.
ChrisR wrote: Thu Feb 06, 2025 2:20 amThe “OwnerDraw” ComboBox was not drawn, without #WM_DRAWITEM event in ObjectTheme. It looks better by commenting "ProcedureReturn #True" at the end of #WM_DRAWITEM in SetMenuItemEx.pbi, so the original callback is called.
It's OK. It's probably better to remove it for good. So, I did it in the new version (Feb 6-2025)
ChrisR wrote: Thu Feb 06, 2025 2:20 amOtherwise, I have a bug when the menu is displayed for the first time, MenuItem are seen as MenuTitle!
Perhaps due to the existence and organization of the ObjectTheme's ErrorHandler() procedure. Anyway, my obsession about closing openSubmenu was excessive. The new version fixes this issue.

I've also added two new functions to facilitate a color theme usage:

Code: Select all

;  • SetMenuColor()      ; Apply a color to all existing items of a menu
;  • SetMenuFont()       ; Apply a font to all existing items of a menu

And I added the ApplyDarkModeToWindow() procedure, allready present in my SetGadgetColorEx.pbi library. May I suggest you add it to your library as well? This allows for a much better rendering of the title bar in a 'Dark mode' environment.

Here is your example code modified:
• Menu_Window() is simplified using SetMenuColor()
• ApplyDarkModeToWindow() is called at line 74

Code: Select all

XIncludeFile "../ObjectTheme.pbi" : UseModule ObjectTheme
XIncludeFile "SetMenuItemEx.pbi"

Enumeration Window
  #Window
EndEnumeration

Enumeration MenuToolStatusBar
  #MainMenu
EndEnumeration

Enumeration MenuItems
  #Menu_New
  #Menu_Open
  #Menu_Save
  #Menu_Quit
  #Menu_About
EndEnumeration

Enumeration Gadgets
  #Checkbox
  #Option_1
  #Option_2
  #Combo
  #Editor
  #String
  #ApplyTheme
EndEnumeration

Procedure IsDarkColor(Color)
  If Red(Color)*0.299 + Green(Color)*0.587 + Blue(Color)*0.114 < 128   ; Based on Human perception of color, following the RGB values (0.299, 0.587, 0.114)
    ProcedureReturn #True
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure Menu_Window()
  Protected Menu_Title, Menu_Bar, Menu_Help
  Protected BackColor, FrontColor
  BackColor = GetObjectThemeAttribute(#PB_WindowType, #PB_Gadget_BackColor)
  If IsDarkColor(BackColor) : FrontColor = #White : Else : FrontColor = #Black : EndIf   ; Or GetObjectThemeAttribute(#PB_GadgetType_Text, #PB_Gadget_FrontColor)
  ;Or BackColor = GetObjectThemeAttribute(#PB_GadgetType_Button, #PB_Gadget_BackColor) : FrontColor = GetObjectThemeAttribute(#PB_GadgetType_Button, #PB_Gadget_FrontColor)
  If CreateMenu(#MainMenu, WindowID(#Window))
    Menu_Title = MenuTitle("File")
    MenuItem(#Menu_New, "New")
    MenuItem(#Menu_Open, "Open...")
    MenuItem(#Menu_Save, "Save")
    Menu_Bar = MenuBar()
    MenuItem(#Menu_Quit, "&Quit")
    Menu_Help = MenuTitle("?")
    MenuItem(#Menu_About, "About")
    SetMenuColor(#MainMenu, #PB_Gadget_BackColor, BackColor)
    SetMenuColor(#MainMenu, #PB_Gadget_FrontColor, FrontColor)
  EndIf
EndProcedure

Procedure Open_Window(X = 0, Y = 0, Width = 400, Height = 300)
  If OpenWindow(#Window, X, Y, Width, Height, "Simple Demo ObjectTheme and MenuItemEx", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    CheckBoxGadget(#Checkbox, 20, 10, 210, 24, "Checkbox")
    OptionGadget(#Option_1, 270, 10, 110, 24, "Option 1")
    OptionGadget(#Option_2, 270, 40, 110, 24, "Option 2")      
    ComboBoxGadget(#Combo, 20, 40, 210, 28, #CBS_HASSTRINGS | #CBS_OWNERDRAWFIXED)   ;  <== Specific ComboBox, Add the 2 Constants to be drawn.
    AddGadgetItem(#Combo, -1, "Combo Element 1") : AddGadgetItem(#Combo, -1, "Combo Element 2")  : AddGadgetItem(#Combo, -1, "Combo Element 3")
    SetGadgetState(#Combo, 0)
    EditorGadget(#Editor, 20, 80, 360, 80)
    AddGadgetItem(#Editor, -1, "Editor Line 1") : AddGadgetItem(#Editor, -1, "Editor Line 2") : AddGadgetItem(#Editor, -1, "Editor Line 3")
    StringGadget(#String, 20, 170, 360, 24, "String")
    ButtonGadget(#ApplyTheme, 20, 210, 360, 50, "Apply Light Blue Theme")
    ProcedureReturn #True
  EndIf
EndProcedure

If Open_Window()
 ApplyDarkModeToWindow()
 SetObjectTheme(#ObjectTheme_DarkBlue) 
 Menu_Window()
 
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_CloseWindow
        Break
      Case #PB_Event_Menu
        Select EventMenu()
          Case #Menu_Quit
            Break
        EndSelect
      Case #PB_Event_Gadget
        Select EventGadget()
          Case #ApplyTheme
            Select GetObjectTheme()
              Case #ObjectTheme_DarkBlue
                SetGadgetText(#ApplyTheme, "Apply Dark Red Theme")
                SetObjectTheme(#ObjectTheme_LightBlue)
                Menu_Window()
              Case #ObjectTheme_LightBlue
                SetGadgetText(#ApplyTheme, "Apply Dark Blue Theme")
                SetObjectTheme(#ObjectTheme_DarkRed)
                Menu_Window()
              Case #ObjectTheme_DarkRed
                SetGadgetText(#ApplyTheme, "Apply Light Blue Theme")
                SetObjectTheme(#ObjectTheme_DarkBlue)
                Menu_Window()
            EndSelect
        EndSelect
    EndSelect
  ForEver
EndIf
User avatar
ChrisR
Addict
Addict
Posts: 1466
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Post by ChrisR »

Thanks for the update and for the 2 new very useful functions SetMenuColor() and SetMenuFont(),
I guess that SetMenuColor() will be used in more than 90% of cases.

The example works well now
I just have a small display problem when I change the background color of the menu: SetMenuColor(#Menu, #PB_Gadget_BackColor, Color).
The empty part to the right of the last "MenuTitle" of the menu bar is not painted.
It is repainted if I click on this empty part and then hover a MenuTitle.
It looks good by adding "SendMessage_(hWnd, #WM_INITMENU, GetMenu_(hWnd), 0)" after "If BackGroundMustBePainted <> #S_OK" but it's probably not the right place to send this message!

Otherwise, for your suggestion to add ApplyDarkModeToWindow() in ObjectTheme, the same thing is already done at the bottom of SetWindowThemeColor() and AddWindowTheme() procedures.
User avatar
Zapman
Enthusiast
Enthusiast
Posts: 205
Joined: Tue Jan 07, 2020 7:27 pm

Re: SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Post by Zapman »

ChrisR wrote: Fri Feb 07, 2025 12:40 amI just have a small display problem when I change the background color of the menu: SetMenuColor(#Menu, #PB_Gadget_BackColor, Color). The empty part to the right of the last "MenuTitle" of the menu bar is not painted.
I was a bad boy yesterday: I updated the procedure several times after posting my message reporting the update and I didn't report it so as not to spoil the forum. I think you don't have the latest version (Feb 2025 - 6.1). I hope it fixes also that point. Please try again https://www.editions-humanis.com/downlo ... olorEx.zip
ChrisR wrote: Fri Feb 07, 2025 12:40 amOtherwise, for your suggestion to add ApplyDarkModeToWindow() in ObjectTheme, the same thing is already done at the bottom of SetWindowThemeColor() and AddWindowTheme() procedures.
But if I don't call ApplyDarkModeToWindow() after having open the window, I get this:
Image

And if I call it, all is allright until I change the theme. Then, I get this:
Image

If you've time for this, you can compare from how it runs with "Test Simple Demo SetGadgetColorEx and MenuItemEx.pb" (in the same zip file as the new version)
Image

Have also a look at what happens to other application windows running behind (i.e. PureBasic): with ObjectTheme, they are redrawn when you change the theme. With SetGadgetColorEx , they are not. That's weird.
User avatar
ChrisR
Addict
Addict
Posts: 1466
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: SetMenuItemFont, SetMenuItemColor and many more... [Windows]

Post by ChrisR »

Zapman wrote: Fri Feb 07, 2025 12:56 pm I was a bad boy yesterday: I updated the procedure several times after posting my message reporting the update and I didn't report it so as not to spoil the forum. I think you don't have the latest version (Feb 2025 - 6.1). I hope it fixes also that point. Please try again https://www.editions-humanis.com/downlo ... olorEx.zip
You are not the first or the last to do it. I downloaded it too early then, everything looks good now with latest version :)
Zapman wrote: Fri Feb 07, 2025 12:56 pm But if I don't call ApplyDarkModeToWindow() after having open the window, I get this:
Thanks for insisting on the problem, the Prototype DwmSetWindowAttribute in ObjectTheme was just crazy :shock: :oops:
It should be fixed now, I tested it on a windows 11 virtual machine (yes, I stayed on windows 10), It looks good now.
ObjectTheme v1.6.1 is uploaded to Github

Thanks for your great work, drawing and coloring menus is far from easy 8)
Post Reply