Event watcher

rhinocommon
c

#1

Hi there,

I would like to create user interface for some scripts and I started studying the samples

When I created a new Rhino 5 plugin project I have removed all the code and replaced with the code below (same as the last code on the sample page),

using System;
using Rhino;
using Rhino.Commands;
using Rhino.DocObjects;
using Rhino.Geometry;
using System.Threading;
using System.Windows;
using System.Windows.Controls;

namespace examples_cs
{
  [System.Runtime.InteropServices.Guid("E4A93905-6E61-43BB-9FF0-4D5F6AF76704")]
  public class ChangeUiFromDifferentThreadCommand : Command
  {
    public override string EnglishName { get { return "csChangeUIFromDifferentThread"; } }
    private RhinoDoc _doc;
    private Label _label;
    private Window _window;

    protected override Result RunCommand(RhinoDoc doc, RunMode mode)
    {
      _doc = doc;

      _window = new Window {Title = "Object ID and Thread ID", Width = 500, Height = 75};
      _label = new Label();
      _window.Content = _label;
      new System.Windows.Interop.WindowInteropHelper(_window).Owner = Rhino.RhinoApp.MainWindowHandle();
      _window.Show();


      // register the rhinoObjectAdded method with the AddRhinoObject event
      RhinoDoc.AddRhinoObject += RhinoObjectAdded;

      // add a sphere from the main UI thread.  All is good
      AddSphere(new Point3d(0,0,0));

      // add a sphere from a secondary thread. Not good: the rhinoObjectAdded method
      // doesn't work well when called from another thread
      var addSphereDelegate = new Action<Point3d>(AddSphere);
      addSphereDelegate.BeginInvoke(new Point3d(0, 10, 0), null, null);

      // handle the AddRhinoObject event with rhinoObjectAddedSafe which is
      // desgined to work no matter which thread the call is comming from.
      RhinoDoc.AddRhinoObject -= RhinoObjectAdded;
      RhinoDoc.AddRhinoObject += RhinoObjectAddedSafe;

      // try again adding a sphere from a secondary thread.  All is good!
      addSphereDelegate.BeginInvoke(new Point3d(0, 20, 0), null, null);

      doc.Views.Redraw();

      return Result.Success;
    }

    private void AddSphere(Point3d center) {
      _doc.Objects.AddSphere(new Sphere(center, 3));
    }

    private void RhinoObjectAdded(Object sender, RhinoObjectEventArgs e)
    {
      var message = String.Format("thread id = {0}, obj id = {1}",
            Thread.CurrentThread.ManagedThreadId,
            e.ObjectId.ToString());

      RhinoApp.WriteLine(message);

      try {
        // when a sphere is added from a secondary thread this line will
        // throw an exception because UI controls can only be accessed from
        // the main UI thread
        _label.Content = message;
      } catch (InvalidOperationException ioe) {RhinoApp.WriteLine(ioe.Message);}
    }

    private void RhinoObjectAddedSafe(Object sender, RhinoObjectEventArgs e)
    {
      var message = String.Format("thread id = {0}, obj id = {1}",
            Thread.CurrentThread.ManagedThreadId,
            e.ObjectId.ToString());

      RhinoApp.WriteLine(message);

      // checks if the calling thread is the thread the dispatcher is associated with.
      // In other words, checks if the calling thread is the UI thread
      if (_label.Dispatcher.CheckAccess())
        // if we're on the UI thread then just update the component
        _label.Content = message;
      else
      {
        // invoke the setLabelTextDelegate on the thread the dispatcher is associated with, i.e., the UI thread
        var setLabelTextDelegate = new Action<string>(txt => _label.Content = txt);
        _label.Dispatcher.BeginInvoke(setLabelTextDelegate, new String[] { message });
      }
    }
  }
}

At the end I received some error message but no idea.

Is there any difference in the template that we have to modify if we want to develop a Windows Form App? I know we need to add the line using System.Windows.Forms;.


(Karol Wierzbicki) #2

If you want to create user control, than you should look at below example. You should inherit form UserControl instead of Command, you will also need to register your form, all explained below: