Shows 'CapsLock' in status bar.

Mac OSX specific forum
Josemar
User
User
Posts: 10
Joined: Tue Mar 29, 2022 7:51 pm

Shows 'CapsLock' in status bar.

Post by Josemar »

Hi all.

(Excuse for my English)

I'm still learning about PureBasic (which I'm liking more and more) and I'm trying to develop small utilities that integrate with the MacOS desktop.

In this code I want to have a chivato that notifies me when 'Caps. Lock' is on. In the original Mac keyboard this is not needed because the keyboard itself includes a led, but there are many external keyboards that do not have this led and sometimes it is cumbersome not knowing when the caps lock is activated and when it is not (for example in a password text-field)

I take this opportunity to ask how can I read the "About" menu of the system bar menu bar? The "About" option is disabled when I run an app built with PureBasic.

Of course, any suggestion will be welcome :)

Code: Select all

; –––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––– 
; Icono_BloqMays
;
; Shows an icon in system menu when 'Caps.Lock' is enabled
;
; Código PureBasic para compilar en MacOS
;
; ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––



EnableExplicit

ImportC  ""										
	CGEventSourceKeyState (stateID, key)		; Identificar estado del teclado en MacOS
EndImport

UsePNGImageDecoder()
Global.i icono = CatchImage(#PB_Any, ?icono_capslock )

Procedure Icon_CapsLock(mostrar)
    Static statusBar.i,statusItem.i
    ;  Shared app.i
    Protected itemLength.CGFloat = 24
    If mostrar  
        If Not statusBar
            statusBar = CocoaMessage(0,0,"NSStatusBar systemStatusBar")
        EndIf
        If Not statusItem
            statusItem = CocoaMessage(0,CocoaMessage(0,statusBar,"statusItemWithLength:",itemLength),"retain")
        EndIf
        
        CocoaMessage(0,statusItem,"setHighlightMode:",#YES)
        CocoaMessage(0,statusItem,"setLength:@",@itemLength)
        CocoaMessage(0,statusItem,"setImage:",ImageID(icono))        
        
        ;; Elmentos opcionales para este icono
        ;CreatePopupMenu(0)
        ;MenuItem(0,"Acerca de CapsLock")
        ;MenuBar()
        ;MenuItem(1,"Salir de CapsLock")
        ;CocoaMessage(0,statusItem,"setMenu:",CocoaMessage(0,MenuID(0),"firstObject"))
        
    Else 
        If statusBar And statusItem
            CocoaMessage(0,statusBar,"removeStatusItem:",statusItem)
        EndIf
        statusItem = 0
        If IsMenu(0) : FreeMenu(0) : EndIf
    EndIf
EndProcedure

Procedure.q getCapsLock()    
    #Key_BloqMays 	= 57
    Define.i retorno = Bool ( CGEventSourceKeyState(1, #Key_BloqMays) & 1 )    
    ProcedureReturn retorno 
EndProcedure

Procedure Monitorizar_CapsLock()
    
    Define lapso = 25  ; 25 milisegundos
    Define idTimer = 1
    Define event
    Define salir = #False 
    
    Define.s informacion$ 
    informacion$ = ~"Chivato para \"Caps Lock\" versión 0.0.0. :-) \n\n"
    informacion$ + ~"Monitoriza el estado de la tecla 'Bloqueo de Mayúsculas'.\n"
    informacion$ + ~"Cuando está activa, se muestra un icono en la barra de estado."
    
    
    If OpenWindow(0, 0, 0, 400, 160, "Monitor para CapsLock",  
                   #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget | #PB_Window_Minimize)
        
        
        Define informacion = TextGadget(#PB_Any, 20, 20, 380, 120, informacion$)
        Define btnFinalizar = ButtonGadget(#PB_Any, 140, 120, 120, 30, "Finalizar")
        AddWindowTimer(0, idTimer, lapso)

        Repeat
            event = WaitWindowEvent()
            
            If event = #PB_Event_Timer And EventTimer() = idTimer
                Icon_CapsLock(getCapsLock())
            EndIf    
            
            If event = #PB_Event_Gadget
                If EventGadget() = btnFinalizar
                    salir = #True 
                EndIf 
                
            EndIf
            
            If event = #PB_Event_Menu
                Select  EventMenu() 
                     Case #PB_Menu_Quit
                        salir = #True  
                     Case #PB_Menu_About       ; <----   Disabled in System Menu ??
                       Debug "Acerca de"          
                        
               EndSelect               
            EndIf
            
            If event = #PB_Event_CloseWindow 
                salir = #True 
            EndIf
            
            
        Until salir
    EndIf
EndProcedure    
    
Monitorizar_CapsLock()

DataSection
  icono_capslock:
      IncludeBinary "iconos/caps_lock.png"
  fin_data:
EndDataSection

Regards,
Josemar
User avatar
deseven
Enthusiast
Enthusiast
Posts: 367
Joined: Wed Jan 12, 2011 3:48 pm
Location: Serbia
Contact:

Re: Shows 'CapsLock' in status bar.

Post by deseven »

Hi, PB uses quite a hacky way to work with macos menubar, but it can be done like this:

Code: Select all

OpenWindow(0,0,0,400,300,"macOS menu",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

; this needs to be called even though we already have a menu
CreateMenu(0,WindowID(0))

; enabling default menu items in PB
; they can't be renamed so the text argument doesn't matter
MenuItem(#PB_Menu_Preferences,"")
MenuItem(#PB_Menu_About,"")

Repeat
  ev = WaitWindowEvent()
  If ev = #PB_Event_Menu
    Select EventMenu()
      Case #PB_Menu_Quit
        Debug "quit"
      Case #PB_Menu_Preferences
        Debug "prefs"
      Case #PB_Menu_About
        Debug "about"
    EndSelect
  EndIf
Until ev = #PB_Event_CloseWindow
Josemar
User
User
Posts: 10
Joined: Tue Mar 29, 2022 7:51 pm

Re: Shows 'CapsLock' in status bar.

Post by Josemar »

Hi deseven ,thanks a lot!
This is a solution for use the "About of" menu :)

It's a pity that is not possible shows this menu "About" in other idioms, only English.
Regards,
Josemar
User avatar
mk-soft
Always Here
Always Here
Posts: 6246
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Shows 'CapsLock' in status bar.

Post by mk-soft »

Change menu names ...

Code: Select all

OpenWindow(0,0,0,400,300,"macOS menu",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

; this needs to be called even though we already have a menu
CreateMenu(0,WindowID(0))

; enabling default menu items in PB
; they can't be renamed so the text argument doesn't matter
MenuItem(#PB_Menu_Preferences,"")
MenuItem(#PB_Menu_About,"")
SetMenuItemText(0, #PB_Menu_Preferences, "Einstellungen ...")
SetMenuItemText(0, #PB_Menu_About, "Über " + GetFilePart(ProgramFilename(), #PB_FileSystem_NoExtension))

Repeat
  ev = WaitWindowEvent()
  If ev = #PB_Event_Menu
    Select EventMenu()
      Case #PB_Menu_Quit
        Debug "quit"
      Case #PB_Menu_Preferences
        Debug "prefs"
      Case #PB_Menu_About
        Debug "about"
    EndSelect
  EndIf
Until ev = #PB_Event_CloseWindow
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
deseven
Enthusiast
Enthusiast
Posts: 367
Joined: Wed Jan 12, 2011 3:48 pm
Location: Serbia
Contact:

Re: Shows 'CapsLock' in status bar.

Post by deseven »

Ah, so they can be renamed after all. I thought that since MenuItem() doesn't do anything SetMenuItemText() won't do anything either.
Josemar
User
User
Posts: 10
Joined: Tue Mar 29, 2022 7:51 pm

Re: Shows 'CapsLock' in status bar.

Post by Josemar »

Thank you both :)
Regards,
Josemar
Post Reply