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;
.