Communicating between Rhino 7 and a WPF Program running on Second Screen

I’m evaluating CAD Packages and Rhino 7 is on the list.

I’m very interested in Rhino 7’s capability of facilitating users writing their own plugins.

I’m specifically interested in using Rhino as a tool for Simple Architectural Design… Floor Slabs, Walls, Colums, Beams, Web Trusses…etc. So 99.99% of the time I’ll be dealing with straight lines and flat surfaces.

What I’d like to try to do is to design a two-screen setup.

The first screen would run a stand-alone WPF Program, which I would design, and that program would essentially be a “large dashboard” that is customized for creating quick architectural designs. It would create these designs on the fly by sending “Rhino Macros” over to Rhino running on the second screen.

So, on the Rhino side the plugin needs to do two things:

  1. It has to participate in a IPC(InterProcess Communications) with the WPF program for the transfer of the “macro text”. Two possibilities for IPC are “Named Pipes” or WM_COPYDATA.
    Here is a link to some WM_COPYDATA info:
    Interprocess Communication Between .NET and MFC Using WM_COPYDATA - CodeProject

  2. Secondly, the plugin needs to find a way of sending the macro to the command line for processing.

In reading some of the Rhino Developer Docs, I see a Macro can either be assigned an Alias…or assigned to a Button Icon. The Alias method is a non-starter, since it too has to be typed into the console. The button method might work if there is a way for the C# plugin code to define the button…constantly reload the button with new macros…and simulate a button push that would fire off that macro in the Command Line or message loop

Of course, there may be size restrictions on the string length of the Macro text being held in the button…but that would just mean shorter macros…but more of them.

Another issue that comes to mind is if the command line ever throws up error messages/dialog boxes that need user intervention to clear. Hopefully all errors to the keyboard/mouse/command line message loop are non-blocking…and simply display as lines of “error message text” in the “command line log”.

One more thing:
I know graphic objects in WPF have properties of “Visible” or “Hidden”.
I’m sure Rhino graphic objects are the same (which is probably how layers are hidden or visible).
And of course, both WPF and Rhino can set the surface colors.

WPF also has an “opacity property”…which affects the transparency of the object.
This is a very useful capability…and hopefully Rhino has it as a settable property for their Graphical Objects.

I’d appreciate any input…

Thanks!

Hi,

Is there a specific reason why you require a stand-alone application?

I’m asking because everything you mentioned becomes a 100x simpler if you can create a Rhino-Plugin, that launches your WPF window. You get access to the entire RhinoCommon SDK. Surely you already know this, hence my question.

1 Like

You can connect from a .NET application to Rhino using the COM-interface. This allows you to send scripting commands, which can achieve a lot. An example to help you get started with this is here rhino-developer-samples/rhinocommon/cs/SampleCsAutomation at 7 · mcneel/rhino-developer-samples · GitHub

I do agree with @Kaushik though that launching your WPF window as part of a plug-in command or as a custom panel in Rhino gives you more functionality at your fingertips, i.e. the whole RhinoCommon API, instead of the scripting interface only.

Hi @Jim11,

Rather than a stand-alone application, you might consider creating a modeless form or docking panel in Rhino. This would eliminate the inter-process communication.

If you requirement is a separate, stand-alone applictions, than I’d suggest using WCF and a Named Pipe binding.

Rhino plug-in can run command macros using RhinoApp.RunScript. You should be able to find examples of this in the developer samples repo.

Command proceeded with a hyphen character will suppress any dialog boxes that might normally appear.

Rhino objects and layers support colors with alpha.

Let us know what else you need.

– Dale

Thanks Kaushik, Menno, and Dale.

Kaushik said:

Blockquote Is there a specific reason why you require a stand-alone application?
I’m asking because everything you mentioned becomes a 100x simpler if you can create a Rhino-Plugin, that launches your WPF window. You get access to the entire RhinoCommon SDK. Surely you already know this, hence my question.

No I didn’t realize that.
If I could launch my WPF window inside a plugin…that would be ideal.
Then my window would be running within the Rhino process and inter-process communications is not necessary.

Is the Rhino program actually a WPF application?.

It’s a bit of a mix of Win32 windows, WinForms, and WPF. We’ve been transitioning to WPF over the years. We actually use a library that we author called Eto which is an abstraction on top of WPF on Windows (and an abstraction on top of Cocoa on Mac).

Hi Steve,

You said:

It’s a bit of a mix of Win32 windows, WinForms, and WPF. We’ve been transitioning to WPF over the years. We actually use a library that we author called Eto which is an abstraction on top of WPF on Windows (and an abstraction on top of Cocoa on Mac).

Wow…you’re deep into the plumbing.

What I’m used to doing in WPF, is dealing with two source files…
The UI is a .xaml file.
Then there is the .cs file with the c# code.
What builds is the typical.exe file.

So, through your abstraction layer is it possible for me to develop in WPF the same way…and have it launch by the plugin?

Is what Kaushik is suggesting above possible.
Can I launch a WPF Window from a Rhino Plugin?

Hi @Jim11,

Here is sample code to a Rhino plug-in that displays WPF forms.

And here is a sample that uses Eto, which is just WPF on Windows.

– Dale

You’re free to directly use WPF if you want. The only downside is that this forces your plug-in to be Windows only

Thanks Everyone!!!
That gives me enough to get started…

1 Like

This is an Update…

My original goal was to create a WPF plugin that would run on a second screen and act as a high-level “Dashboard”…tying back into RhinoCommon.
The idea is to have a little bit of Dashboard manipulation that would drive a whole bunch of Rhino functionality.
My empahsis will be on creating an Architecture Dashboard…

As a first step, I had to make sure that a very simple “Hello World” WPF full-Window would run.
So after a bit of discovery and hair pulling…I now have a sample RhinoCommon Plugin working like a champ.
I also created a plugin to fire off one of my very complex WPF applications…and it too works with no issues.

Below I am going to list the 3 sample files…a “Command .cs file” that launches the plugin…and a the “.cs and .xaml files” of the actual WPF window.

These 3 sample files need to be added into the current c# Developer Sample “SampleCsWpf” that resides up on github in the “cs” directory.

But before you do that you should build the original sample SampleCsWpf in in Visual Studio…and make sure you get it working.

The command file (SampleCsWpfWindowCommand.cs) needs to be Copied into the Commands Directory of SampleCsWpf.
The .xaml (SampleCsWpfWindow.cs.xaml) and .cs (SampleCsWpfWindow.cs.xaml) window creation files need to be copied into the Views Directory of SampleCsWpf.

Then as a last step you have to register these files in the Solution Explorer box of Visual Studio
Right Click on the Commands Directory…Click on Add Existing Item…then double click on the SampleCsWpfWindowCommand.cs file listing in the popup dialog.
Next, Right Click on the Views Directory…Click on Add Existing Item…then double click on the SampleCsWpfWindow.cs.xaml file listing in the popup dialog.
Next repeat, Right Click on the Views Directory…Click on Add Existing Item…then double click on the SampleCsWpfWindow.cs file listing in the popup dialog.

Build the new sample and load the .dll plugin.

There should be 4 different WPF commands to play with…

This is the Command file SampleCsWpfWindowCommand

using Rhino;
using Rhino.Commands;

namespace SampleCsWpf.Commands
{
public class SampleCsWpfWindowCommand : Command
{
public override string EnglishName => “SampleCsWpfWindow”;

protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
  Views.SampleCsWpfWindow window = new Views.SampleCsWpfWindow();
  window.Show();

  return Result.Success;
}

}
}

This is the .xaml.cs file SampleCsWpf.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace SampleCsWpf.Views
{
//


// Interaction logic for SampleCsWpfWindow.xaml
//

public partial class SampleCsWpfWindow : Window
{
public SampleCsWpfWindow()
{
InitializeComponent();

  // Windows initialization User Code Starts Here.
  // The execution of this Code does not rely on
  // any "Event Driven" actions, but will execute "Inline".
  //This Message Box demonstrates a single line of
  //User Code executed during the Initialization and 
  //Loading of the Window.
  MessageBox.Show("Starting Up Standalone WPF Window");
  
  // During Window Initilization we set the Button Background to Yellow.
  Name_Button.Background = new SolidColorBrush(Colors.Yellow);
  // Set Button Foreground to Red.
  Name_Button.Foreground = new SolidColorBrush(Colors.Red);
}

// Global Variables and Methods User Code Starts Here.
// Any code out here is "Event Driven", relying on 
// such things such as "Mouse and Keyboard Events"...etc...
private static string BG_Color = "Red";
private void Button_Click_Event(object sender, RoutedEventArgs e)
{
  if(BG_Color == "Red")
  {
    Name_Button.Background = new SolidColorBrush(Colors.Blue);
    Name_Button.Foreground = new SolidColorBrush(Colors.White);
    BG_Color = "Blue";
  }
  else
  {
    Name_Button.Background = new SolidColorBrush(Colors.Red);
    Name_Button.Foreground = new SolidColorBrush(Colors.Black);
    BG_Color = "Red";
  }
}

}
}

The markup in the xaml file is screwing up the posting…

You can also attach files. Furthermore, if you want to add a new example, you can use a pull request on GitHub.

Hi Menno

I have no idea on the in’s and out’s of using Git Hub.

So as far as adding stuff to the repository…I’ll take a pass.
I don’t want to screw things up.

But, if somebody wants to download the “SampleCsWpf” add my 3 files…and follow the above directions to do a rebuild in Visual Studio…and load the modified plugin to see the results…that’s good…

I’ve attached the
SampleCsWpfWindow.xaml (795 Bytes)
SampleCsWpfWindow.xaml.cs (2.0 KB)
SampleCsWpfWindowCommand.cs (416 Bytes)
3 files…

1 Like