Get Reference to Menu Item

Is it possible to get a reference to a menu item that's selected, but not yet executed?

For example, how can I get a reference to "Set Note…" when I execute a macro at this moment?

2021-11-27_01-49-29_PM

If you mean can this be solved with AppleScript, (which would be the correct and reliable way to solve it) then I don't know, but I will guess that the answer is no.

If you mean can this be solved with any approach, then the answer is yes. This could easily be solved with a combination of Find Image and Monterey OCR. I have used Monterey OCR often enough to feel very comfortable in saying this would work very well.

I'll let others speak out on the AppleScript side of things before I give tips or code for the OCR idea.

Hey Bryan,

I'm not quite sure what you mean by a reference.

Firstly – you can access Set Note... from the Keyboard Maestro Editor's Actions Menu.

Secondly – if you need to access items in the contextual menu the only recourse beside's @Sleepy's idea is AppleScript UI-Scripting – and that would be difficult indeed to get right.

-Chris

I might be wrong but I thought he meant he wanted to get the string of the highlighted item in the menu.

Thanks for the compliment. I have a lot of experience using Image Capture, Find Image and OCR because (a) I'm not very good with AppleScript, and (b) AppleScript only works for apps that provide support for it, which usually runs around 50%. Even in the case you are asking for, i.e., the string representing the highlighted text in a menu, may not be able to use AppleScript support to return its value, because of limitations in AppleScript. You keep calling the highlighted menu item "selected." I'm not sure that's the right word. "Highlighted" would be a more accurate word. The word "selected" usually refers to something that the user has already clicked on, like a file in Finder, or text in an editor.

Here's the principle that I live by:

If a person can perform a task using their mouse, keyboard, ears, eyes and brain, then it's possible for KM to do the same task.

So every time I see the questions "Can KM... do such-and-such..." the answer is always yes, as long as the person asking the question is themselves able to do that same thing with their eyes, hands and brain. However most people have a set methodology in mind when they ask a question. For example, "Hey, can I use KM to trigger a macro when the user moves the mouse?" Since they used the word "trigger", the answer is no. But if they ask the question without prescribing a specific methodology, e.g,, "can a KM macro detect when the mouse is moved" then the answer is yes.

So when you asked the original question, "can I get the name of the currently highlighted menu item?" I instantly knew that the answer was yes. Because as a human being I can get the name by just reading the screen with my eyes and looking for the blue text. But I suspected that you had a methodology in mind so I qualified my answer quite a bit.

I agree.

I also think that they only way to make a judgment on whether something is "worth the effort" is to actually see the solution, which by definition the person asking the question can't do until an answer is provided.

A lot of time when people see an answer, they react, "but I didn't want to solve the problem THAT way," and they decide that the solution is "not worth the effort" because it uses a different approach than they had in mind. I guess that's fine, but it really means that deciding if "something is worth the effort" is really more of an artistic choice than a logical one.

I still can't tell whether you will use my solution. You called it very creative, (thanks for that) but then you spend a lot more time talking about AppleScript again. I agree that AppleScript is usually the best way. But since my solution appears to be the only solution, are you planning to try it, or are you planning to give up? You have every right to give up. I'm just asking what your plans are.

Hey Brian,

I know what a programmatic reference is; I've been in the game for about 40 years.

What I didn't know is what you meant.

  • You didn't say you wanted an AppleScript reference (vanilla or UI).
  • You didn't say what your ultimate objective was.
  • Now you're telling @Sleepy you want a string, but you previously said you want a reference to the selection object...

So. You weren't very clear about what you wanted or why. Hence the query.

Glad to hear it. Most people are.

Not for most people. They take one look, and their eyes roll back in their head...

I've been using and evangelizing UIB since 2005.

Script Debugger is also an anodyne for UI-Scripting if one knows how to use it.

You can definitely get down into the open menu object if you know what action you're working with:

tell application "System Events"
   tell application "System Events"
      tell application process "Keyboard Maestro"
         tell (first window whose subrole is "AXStandardWindow")
            tell group 6
               tell splitter group 1
                  tell scroll area 3
                     tell group 1
                        tell menu button 1
                           if exists of menu 1 then
                              tell menu 1
                                 tell menu item "Set Note…"
                                    return it
                                 end tell
                              end tell
                           end if
                        end tell
                     end tell
                  end tell
               end tell
            end tell
         end tell
      end tell
   end tell
end tell

However there is no easy way to tell what the action is, unless it's selected. The trouble there is that a selected action can be detected by AppleScripting the Keyboard Maestro Editor, but that reference cannot be passed directly to System Events for UI-Scripting.

There is a method of detecting what menu is open using System Events and entire contents, but it's a kludge.

Keyboard Maestro does in fact have a selection object, but that doesn't help one bit in this case.

System Events? You can capture a click event and usually acquire a reference to the object clicked.

Correctly Identifying GUI Elements - #28 by CJK

Have fun.

-Chris

My guess is @commiepinko wanted to select a particular menu item. And it looks like a context menu.

UI Browser I've found to be unreliable and in fact crashtastic when it comes to dynamic UI - such as a context menu.

What I have found to work - most of the time - is first character navigation of menu items.

He has withdrawn some of his posts. I'm not sure why. Perhaps I was too argumentative?

In one of his withdrawn posts I think he said that I was right that he wanted a copy of the text that was highlighted under the mouse and he called my solution "wildly creative."

1 Like

But why would you want to know the text of a menu item under the mouse? I'd genuinely love to know - and might give another solution to their overall problem (whatever that might be).

In my experience, 50% of all questions are half-way down the wrong path. But I gave this one the benefit of the doubt. It sounds legit to me.

1 Like

Me too. Just widening the conversation in case the OP's problem can be solved another way.

Fair enough. I hope I wasn't being rudely argumentative.

@commiepinko No, that’s the standard, everyday meaning of the word. In programming, it is the means by which direct access to a data structure is provided, rather than a copy of data it contains.

Reading what others have interpreted as your presumed objective, I’m inferring that you want the name of the selected menu item. It looks like—as also guessed by others—that you’re dealing with a context menu. @ccstone has illustrated the obtaining of a [AppleScript] reference to a context menu class object in KM:

He mentioned that this was specific to a particular action in a list of actions. If you want to generalise it, the reference of importance from the above will be one of either group 6 or group 1, of which my money is on the latter. That is to say, group 1 of scroll area 3 of splitter group 1 of group 6 of window 1 whose … is what I am guessing represents the first action in the macro currently open for editing in the KM editor. The second action would then be group 2 of…, etc. Some actions (e.g. conditional or looping actions) can, themselves, contain actions. It would follow that, if the second action in the macro were one of these containers, then group 2 of… would house a UI sub-tree that reflects this structure, meaning you’ll have to use either a looping structure or recursion principles to successfully implement complete generality.

For the top-level set of actions, however, the name of the selected menu item, and the action reference object (i.e. group class UI element) to which it belongs, can be retrieved like so:

tell application "System Events"
    tell application process "Keyboard Maestro"
        tell (window 1 whose subrole is "AXStandardWindow")
            tell group 6's splitter group 1's scroll area 3
                set _actions to a reference to its every group
            end tell
        end tell
    end tell

    tell a reference to the _actions --to repeat while it exists
        tell its menu button 1 to set _menuitem ¬
            to a reference to every menu item in ¬
            menu 1 whose selected = true   

        tell (it whose class of menu button 1's menu contains menu) ¬
            to if it exists then return {|action|:item 1, menu_item:¬
            the _menuitem's name as text}
        
        --set _actions to a reference to the _action's <nested actions’s relative reference>
    end
end tell

return false

The |action| property of the returned record corresponds to the object returned from:

tell application "Keyboard Maestro" to get the first item in (get the selection)

(if the selected action is in the top-level of the hierarchy). Since some of the menu items also contain sub-menus, you will also need to implement recursive processing if you want to know which sub-menu is selected (the parent menu item name will be returned otherwise).

I’ve templated a loop that, provided you obtain the relative reference chain that takes one from any given layer of actions to the nested actions one level below, should generalise the inclusivity of the above code in operation. There’s two comment marks to remove when able.

Bear in mind I don’t have KM installed yet, so testing has been done only to make sure the code is alright in principle, but it could require minor tweaks (contains may in fact be is, for example), and there’s almost certainly some silly typos during typing (done via my iPad, which has been a royal ball ache).

If you were working with a menu from the menu bar, it would be infinitely simpler.

1 Like

You weren't, not at all

1 Like