Windows Forms on GH and Rhino 8

Hi All,

on Rhino8 for the MAC how do we access winforms? Meaning that all the UI extension for grasshopper are tided to winform and in .net 7 winforms are not available on the mac. Is there something I am missing? E.g. the following code will not build on the mac (C#)

public override bool AppendMenuItems(ToolStripDropDown menu)
{
  var output = base.AppendMenuItems(menu);

   Menu_AppendSeparator(menu);
   Menu_AppendItem(menu, textItem, (s, e) => { RhinoApp.WriteLine("Does not build"); });
}

is there a package on nuget that we can reference or any suggestion you have?

Thanks a lot.
Alberto

1 Like

The best suggestion I can give is to rewrite against Eto.Forms, which is used by Rhino itself, in both Rhino 7 and Rhino 8.

But this is in grasshopper, can you rewrite this for me?

GH_DocumentObject.Menu_AppendItem Method

Is there an API that uses Eto that I am not aware of?

Alberto

I have the same question.

1 Like

@Alberto The ToolStripDropDown is a System.Windows.Forms type. On macOS try adding System.Windows.Forms in the Rhino 8 folder to your project. Do not include that with your plugin distribution as it is already shipped with Rhino

@curtisw Is there a NuGet package to use for macOS Grasshopper plugin builds that need access to ToolStripDropDown and other similar types?

same here :wink:

Thanks @eirannejad whatever works :wink:

Where can I can find the assembly? I looked into the Rhino8 package but cannot find it

Should I grab it from some other location?

Thanks a lot,
Alberto

Rhino 8.app/Contents/Frameworks/RhCore.framework/Versions/Current/Resources/

I tried to add the reference like this:

        <Reference Include="System.Windows.Forms">
          <HintPath>/Applications/Rhino 8.app/Contents/Frameworks/RhCore.framework/Versions/Current/Resources/System.Windows.Forms.dll</HintPath>
        </Reference>

If I do that, I get a weird unrelated error when building:

$  dotnet build --configuration MyConfig --framework net7.0-macos  MySolution.sln
MSBuild version 17.7.3+4fca21998 for .NET
  Determining projects to restore...
  Determining projects to restore...
/usr/local/share/dotnet/sdk/7.0.403/NuGet.targets(158,5): error : Invalid framework identifier ''. [...]

Anyone running into the same problem?

Currently this is blocking us from providing a Mac-compatible version of the ShapeDiver plugin for Rhino 8.

I am not sure that .csproj allows unix-style paths. I copied the dll into my project folder and that make it work.

1 Like

How did you specify the reference to the dll in your csproj file?

@Alberto I could solve it, many thanks for your hint regarding the UNIX path.

Note for others: Using the same approach for System.Drawing.Common.dll included with Rhino 8 for Mac works fine.
Related thread: System.Drawing.Common not compatible with macOS anymore

@curtisw would it be possible to include the mac-specific versions of System.Windows.Forms.dll and System.Drawing.Common.dll in the RhinoCommon nuget package (for the macos platform) ?

Yes we can add that, currently the only way to get access to System.Windows.Forms is to target net48. As for System.Drawing.Common it’s already a nuget package which you can reference (but don’t include the .dll as part of your plugin). I’ve created RH-80655 to get that included.

Thanks for bringing it to our attention!

Cheers,
Curtis.

Just as an update, I’ve found this works for referencing System.Windows.Forms and System.Drawing.Common from non-windows targets:

  <ItemGroup Condition="$(TargetFramework) == 'net7.0-macos'">
    <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" Private="False" />
  </ItemGroup>
1 Like

Not a C# expert so maybe I am missing something obvious, but I’m converting a C# script to a plugin. It uses Rhino.UI.SaveFileDialog which requires some types from System.Windows.Forms. I’ve read through this post, but it isn’t entirely clear to me what the solution is. Here is my .csproj unmodified from the template I just used:

<Project Sdk="Microsoft.NET.Sdk">
	
  <PropertyGroup>
    <!-- Select the framework(s) you wish to target.
        Rhino 6: net45
        Rhino 7: net48
        Rhino 8 Windows: net48, net7.0, net7.0-windows, net7.0-windows10.0.22000.0, etc
        Rhino 8 Mac: net7.0, net7.0-macos, net7.0-macos12.0, etc
    -->
    <TargetFrameworks>net7.0;net48</TargetFrameworks>
    <EnableDynamicLoading>true</EnableDynamicLoading>
    <TargetExt>.rhp</TargetExt>
    <NoWarn>NU1701</NoWarn>
  </PropertyGroup>
  
  <PropertyGroup>
    <!-- Specifies information for Assembly and Yak -->
    <Version>1.0</Version>
    <Title>rhino-cube-plugin</Title>
    <Company>rhino-cube-plugin Authors</Company>
    <Description>Description of rhino-cube-plugin</Description>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Grasshopper" Version="8.0.23304.9001" ExcludeAssets="runtime" />
  </ItemGroup>
  
</Project>

I don’t plan to distribute this (at least anytime soon), and will just be using it on OS X/Rhino 8. If I add the ItemGroup snippet from Curtis’ last post, but change the TargetFramework to net7.0, and remove net48 from the TargetFrameworks at the top I get a successful build (with a warning SaveFileDialog.ShowDialog()' is obsolete: 'Use ShowSaveDialog). Is that the correct solution? Are there some docs I should read that I haven’t spotted yet?

I know this is an old thread, but it seems to be exactly what I’m seeing so seems better to reply than start a new one.

Thanks

Yes. Check the RhinoCommon API documentation for SaveFileDialog.ShowSaveDialog Method