Gh component ContextMenu windows dependencies

Hi all,

To add to the context menu of a gh_component we use the toolstripmenu in the addadditionalmenuitems method. this is using.windows, so how does that work on Mac?

It works on Mac as we have our own implementation of System Drawing and Windows Forms based on Cocoa APIs. Not everything is implemented however, so testing is certainly recommended. For any forms or other UI we recommend using Eto, as things like TableLayoutPanel and docking aren’t quite up to par. All of the GH dialogs on Mac have been ported over to Eto, for example.

Hope this helps!
Curtis

1 Like

Hej Curtis,

I’m experiencing issues with this for GH_Param types and the GH_Component.

Struggling with what references to include when developing this in .NET 7 windows.

I cant switch to more modern ContextMenu because the abstract McNeel classes are still using ToolStripDropDown.

Eto should contain it, if not, you can always mock it out by creating an additional .dll and define it like so. Again you are only tricking the compiler here:

namespace System.Windows.Forms;

public class ToolStripDropDown
{

}

1 Like

I’m seeing this all over the places including Grasshopper Canvas depending on System.Windows.Forms

@DavidRutten @curtisw is GH1 really dependent on .NET Framework, and if so, how do we build GH1 plugins in .NET 7?

So far my “mock” classes look like this, is this really the way to go?


namespace System.Windows.Forms
{
    public class Component
    {
    }
    /// <summary>
    /// </summary>
    public class ToolStripMenu: Component
    {
        

        public ToolStripMenu(string name ="")
        {
            
        }
    }

    public class ContextMenuStrip : Component
    {
        public List<Component> Items { get; set; }

        public void Show(Point point)
        {
            throw new NotImplementedException();
        }
    }

    public class ToolStripDropDownItem : Component
    {
        public string Text { get; set; }
        public bool Checked { get; set; }
        public EventHandler Click;

        public Bitmap Image { get; set; }
    }

    public class ToolStripSeparator : ToolStripDropDownItem
    {

    }

    public class ToolStripMenuItem: ToolStripDropDownItem
    {
        public string ToolTipText { get; set; }

        public List<ToolStripDropDownItem> DropDownItems = new List<ToolStripDropDownItem>();

        public ToolStripMenuItem(string name = "")
        {
            
        }
    }

    public class Control
    {
        
    }

    public static class Extensions
    {
        public static void Refresh(this Control control)
        {
            control.Refresh();
        }
    }
}

Hey @sonderskovmathias,

Building Grasshopper components with Windows.Forms APIs is possible in net7.0, but unfortunately since there’s no easy way to reference System.Windows.Forms.dll via nuget, you need to add this to your .csproj to make that all work:

  <ItemGroup>
    <PackageReference Include="System.Drawing.Common" Version="7.0.0" ExcludeAssets="runtime" />
    <PackageReference Include="Microsoft.WindowsDesktop.App.Ref" GeneratePathProperty="true" Version="7.0.0" ExcludeAssets="all" />
    <Reference Include="$(PkgMicrosoft_WindowsDesktop_App_Ref)\ref\net7.0\System.Windows.Forms.dll" />
  </ItemGroup>

Even though our nuget packages only target net48 currently, they are still usable from net7.0 and you can ignore the NU1701 and NU1702 warnings. We do have plans to release a nuget package with net7.0 targets but that will take some time, see RH-77311. In the meantime, adding <NoWarn>NU1701;NU1702</NoWarn> will get rid of the warnings.

Additionally, there is no need to add “mock” Windows Forms classes, that will not work.

Hope this helps!

Also, forgot to mention for others that are reading this. If you are targeting net7.0-windows, you can simply add <UseWindowsForms>true</UseWindowsForms> to your csproj instead of the above hack. The above is only needed if you want your plugin to work for both Windows and Mac.

1 Like

Lovely thank you so much. It really frustrated me the amount of hiccups then trying to port a relatively large plugin.

Will check it out in the morning.

Cheers.

Thanks for asking the question Mathias. Just ran into this myself and couldn’t find anything in the docs.

My workaround was to include the following in the csproj to switch between net48 and net*

  <Choose>
    <When Condition="$(TargetFramework.Contains('net4'))">
      <ItemGroup>
        <Reference Include="System.Windows.Forms" />
      </ItemGroup>
    </When>
    <Otherwise>
      <ItemGroup>
        <PackageReference Include="System.Drawing.Common" Version="7.0.0" />
        <PackageReference Include="System.Resources.Extensions" Version="7.0.0" />
        <PackageReference Include="Microsoft.WindowsDesktop.App.Ref" GeneratePathProperty="true" Version="7.0.0" ExcludeAssets="all" />
        <Reference Include="$(PkgMicrosoft_WindowsDesktop_App_Ref)\ref\net7.0\System.Windows.Forms.dll">
          <Private>False</Private>
        </Reference>
      </ItemGroup>
    </Otherwise>
  </Choose>

@curtisw My project was generated by the vsix wizard, could something similar be included in the template?