MenuItem() Shortcut Helper

Mac OSX specific forum
User avatar
Piero
Addict
Addict
Posts: 1113
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

MenuItem() Shortcut Helper

Post by Piero »

Code: Select all

; Mac MenuItem() Shortcut Helper
; More info/stuff (extended keyboards etc.):
; https://www.purebasic.fr/english/viewtopic.php?p=620336#p620336
; https://web.archive.org/web/20160509091827if_/http://x86osx.com:80/bbs/c_data/pds_comment/MacintoshToolboxEssentials.pdf
; Select "TECHNICAL SYMBOLS" on "Select Categories" of "Customize List…" of Character Viewer (to get ⌘, ⇧, ⇥, ⎋ etc.);
; https://support.apple.com/guide/mac-help/use-emoji-and-symbols-on-mac-mchlp1560/mac

EnableExplicit

Global shc.s = "↩︎"

ImportC ""
   sel_registerName(str.p-ascii)
   class_addMethod(class, selector, imp, types.p-ascii)
EndImport

Procedure.s modifierFlagsInfo(modifierFlags)
   Protected r1.s
   If modifierFlags & #NSControlKeyMask
      r1 + "Ctrl+" ; "⌃"
   EndIf
   If modifierFlags & #NSAlternateKeyMask
      r1 + "Alt+" ; "⌥"
   EndIf
   If modifierFlags & #NSShiftKeyMask
      r1 + "Shift+" ; "⇧"
   EndIf
   If modifierFlags & #NSCommandKeyMask
      r1 + "Cmd+" ; "⌘"
   EndIf
   ProcedureReturn r1
EndProcedure

ProcedureC PerformKeyEquivalent(Sender, sel, currentevent)
   Protected modifiers, FlagsInfo.s, Long, Char.s, cAsc, kc
   If currentEvent
      Select CocoaMessage(0, currentEvent, "type")
         Case #NSKeyDown
            kc = CocoaMessage(0, currentEvent, "keyCode")
            modifiers = (CocoaMessage(0, currentEvent, "modifierFlags"))
            FlagsInfo = modifierFlagsInfo(modifiers)
            If 1 ; Not ((kc = 53 Or kc = 48) And FlagsInfo = "") ; simple esc or tab doesn't work
               Long = CocoaMessage(0, currentEvent, "charactersByApplyingModifiers:", 0)
               CocoaMessage(@Long, Long, "UTF8String")
               Char = PeekS(Long, -1, #PB_UTF8)
               cAsc  = Asc(Char)
               If cAsc >= 'a' And cAsc <= 'z'
                  Char = UCase(Char)
               ElseIf kc = 51 ; delete
                  Char = "⌫"
               ElseIf kc = 49 ; space
                  Char = " "
               ElseIf kc = 48 ; tab
                  Char = "⇥"
               ElseIf kc = 36 ; return
                  Char = "↩︎"
               ElseIf kc = 53 ; esc
                  Char = "⎋"
               ElseIf kc = 123 ; arrows
                  Char =  "←"
               ElseIf kc = 124
                  Char =  "→"
               ElseIf kc = 125
                  Char =  "↓"
               ElseIf kc = 126
                  Char =  "↑"
               ElseIf kc = 122
                  Char =  "F1" ; functions
               ElseIf kc = 120
                  Char =  "F2"
               ElseIf kc = 99
                  Char =  "F3"
               ElseIf kc = 118
                  Char =  "F4"
               ElseIf kc = 96
                  Char =  "F5"
               ElseIf kc = 97
                  Char =  "F6"
               ElseIf kc = 98
                  Char =  "F7"
               ElseIf kc = 100
                  Char =  "F8"
               ElseIf kc = 101
                  Char =  "F9"
               ElseIf kc = 109
                  Char =  "F10"
               ElseIf kc = 103
                  Char =  "F11"
               ElseIf kc = 111
                  Char =  "F12"
               ElseIf kc = $69
                  Char =  "F13"
               ElseIf kc = $6B
                  Char =  "F14"
               ElseIf kc = $71
                  Char =  "F15"
               ElseIf kc = $47 ; keypad clear
                  Char = "⌧"
               ElseIf kc = $4C ; keypad enter
                  Char = "⌅"
               ElseIf kc = $72 ; help
                  Char = "?⃝"  ; it's 2 chars: see workarounds below
               ElseIf kc = $75 ; fwd delete
                  Char = "⌦"
               ElseIf kc = $73 ; home
                  Char = "↖"
               ElseIf kc = $77 ; end
                  Char = "↘"
               ElseIf kc = $74 ; pgup
                  Char = "⇞"
               ElseIf kc = $79 ; pgdown
                  Char = "⇟"
               EndIf
               If shc =  FlagsInfo + Char
                  ProcedureReturn 0
               EndIf
               shc =  FlagsInfo + Char
               If shc = "Cmd+C" Or shc = "Cmd+Q" or Char = ""
                  ProcedureReturn 0
               endif
               SetGadgetText(0, shc)
               If Char = "?⃝" : shc = FlagsInfo + Chr(5) : EndIf
               SetMenuItemText(0,1, "Test" + #TAB$ + shc)
               If Char = "?⃝" : shc = FlagsInfo + Char : EndIf
            Else
               ProcedureReturn 0
            EndIf
      EndSelect
   EndIf
   ProcedureReturn 1
EndProcedure

OpenWindow(0, #PB_Ignore, #PB_Ignore, 300, 200, "PB Mac Shortcut Helper")
Define class    = CocoaMessage(0, WindowID(0), "class")
Define selector = sel_registerName("performKeyEquivalent:")
class_addMethod(class, selector, @PerformKeyEquivalent(), "v@:@")
TextGadget(0, 10, 10, 290, 120, ~"Type a Shortcut\n\nUse ⌘C to copy it\n\nType it twice to test it")

CreateMenu(0, WindowID(0))
MenuTitle("Shortcut Test")
MenuItem(0, "Copy" + #TAB$ + "Cmd+C")
MenuItem(1, "Test" + #TAB$ + shc)
Repeat
   Select WaitWindowEvent()
      Case #PB_Event_Menu
         Select EventMenu()
            Case 0
               SetClipboardText(ReplaceString(GetGadgetText(0),"?⃝",Chr(5))) ; ?⃝ will be a strange "ENQ"
            Case 1 : MessageRequester(~"\""+shc+~"\"","WORKS!")
            Case #PB_Menu_Quit : End
         EndSelect
      Case #PB_Event_CloseWindow : End
   EndSelect
ForEver
Last edited by Piero on Thu Nov 20, 2025 8:05 am, edited 1 time in total.
User avatar
Piero
Addict
Addict
Posts: 1113
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: MenuItem() Shortcut Helper

Post by Piero »

Updated for extended keyboards
Now you can also directly test by typing the shortcut twice
Post Reply