Programatically "launch" component's menu item

Is it possible to trigger the event handler associated to a menu item of a compiled component? I would like to remotely trigger it (from a python component)

thanks
aitor

Yeeeeees, however if you can figure out how to call the method or set the property directly that would be better.

You must create a new ToolstripDropDown instance, call AppendMenuItems() on the component you’re interested in. When that method returns your dropdown should have all the items in it. You can then iterate over those items, find the one you want and if it’s of type ToolStripMenuItem call the PerformClick() method on it.

Thank you David for reply.
Aitor and I have been discussing this subject.

What I’m trying to achieve is through clicking a boolean “True/False” toggle, prompt the command
“Set one 2D curve in ARCHICAD”.

Explaination:

  1. User clicks the toogle button and send a “True” boolean to Python script
  2. Python component triggers the “Set one 2D curve in ARCHICAD” for selected component (2DC)
  3. User is directed to ARCHICAD to select one curve (same as happens when you right click on component and selects “Set one 2D curve in ARCHICAD”

This is the info about the 2DC component (developed by Graphisoft/ArchiCAD)
guid3

You cannot modify the toggle during a solution, which is when your python script runs. You will have to wait until the solution is finished, then trigger the toggle. You can use the SolutionEnd event on GH_Document, and then since you’re dealing with UI objects you’re probably best off invoking a method on the UI thread. There’s a RhinoApp.InvokeOnUiThread() method for that.

As you can see it’s really complicated and I’m wondering whether using a button to modify a toggle is really worth the effort. Perhaps it makes more sense simply to expire the object in question rather than trying to make toggles do updates?

thanks for the hints, @DavidRutten . Since the component is compiled, i can’t (afaik) see wich method is handling the item click event. Do you know if its anyway to figure out wich one is it, like a listener or something…

I suppose that here you are referring that i should override AppendMenuItems() method. I tried to do so creating a subclass of the component’s class, but python is complaining that it can’t create a child class since the base clase is “sealed”.

calling that method on the component, it returns a boolean. I feel i’am missing something here. From your words I interpret that an iterable object should be returned, but…

is it any method to recall the ToolstripDropDown object that is actually coded on the component. If this could be possible, then certainly could iterate over the items, search the one i’m looking for and finally call the performClick()…

Too many questions. I’ am certainly lost. :persevere:

While I wait for some help, as long as I can’t figure out how to complete the paths suggested by @DavidRutten , I’am walking blindly, navigating inside ArchiCADConnection.dll, exploring the terrain for alternatives… This is already just a didactical exercise for me.

import scriptcontext as sc
import Grasshopper as gh
from System.Windows import Forms
import clr
clr.AddReference('ArchiCADConnection.dll')
import ArchiCAD


if activate:
    doc = gh.Instances.ActiveCanvas.Document
    comp = [obj for obj in doc.Objects if obj.NickName == name][0]
    comp.Menu_CustomSingleValueItem() #this statement raises the error

i’am trying to execute our infamous component’s Menu_CustomSingleValueItem() method,
Well, the code above raises this exception:

Runtime error (TypeErrorException): cannot access protected member Menu_CustomMultiValueItem without a python subclass of AC_Polyline

Traceback:
line 23, in script

The method happens to be decorated as protected, so no access posible wihout subclassing. But as i said yesterday, subclassing seems to be not allowed, at least i interpret this from python exception message:

class myPolyParamClass(ArchiCAD.PersistentParams.AC_Polyline):
    def __init__(self):
        pass

boom, in the face…

Runtime error (TypeErrorException): cannot derive from ArchiCAD.PersistentParams.AC_Polyline because it is sealed
Traceback:
line 25, in script

wich is exactly what avoid me to follow David’s suggestion of overriding AppendMenuItems() (if i has understood him correctly)

well… Further orientation would be wellcome.
thanks

C# samples will be also welcome…

@aitorleceta I really appreciate your help and dedication with this!!! A big thank you! Unfortunately this is out of my coding knowledge, but I’m hoping it’s solveable and that we both will learn a great deal :smiley:

1 Like

Here’s a file which shows how to perform clicks on menus populated by other components. Just be aware that you cannot toggle menus from within a solution that start a new solution. The panel alignment doesn’t cause a recompute, so it’s safe.

menu toggler.gh (7.5 KB)

2 Likes

@DavidRutten that works like a charm!! :smiley: :smiley:
I’m very very grateful for both of your help solving this!
This opens up so many possibilities of what I wanted to achieve!

My main idea is to use this with Human UI to let users prompt “right click menu commands” through boolean buttons on Human UI (the green and the red button).
Like:

Again, a big thank you to you both and this fantastic community!

Jodå minsann, det här är ett toppenbra ställe. :slight_smile:

// Rolf

1 Like

@RIL ja, underbart att kunna få hjälp :wink:

I translated Davids code into python if anyone want to use it

import Grasshopper
import System

for obj in Grasshopper.Instances.ActiveCanvas.Document.Objects:
    if obj.NickName == Name:
        menu = System.Windows.Forms.ToolStripDropDown()
        obj.AppendMenuItems(menu)

        for item in menu.Items:
            if item.Text == Menu:
                item.PerformClick()

test

1 Like

Hi @agi.andre! Super interesting discussion. I’m trying to do something similar, but I’m not proficient in python. How did you manage to toggle and get the 2d curve from Archicad?

Thank you!

Set Curve Archicad.gh (3.5 KB)
Sure here you go:

Amazing work @agi.andre! Thanks a lot for sharing!