Hi all.RHino 6 and 7 rhinocommon. I would like to know if the following is correct.
I want to set the position of a wpf window bottom right on active view
var active_view = Rhino.RhinoDoc.ActiveDoc.Views.ActiveView;
var punto_3d = new Rhino.Geometry.Point3d(active_view.Bounds.Width,active_view.Bounds.Bottom,0);
var pt2d = new System.Drawing.Point((int)punto_3d.X,(int)punto_3d.Y);
pt2d = active_view.ActiveViewport.ClientToScreen(pt2d);
Left = pt2d.X -Width;
Top = pt2d.Y -Height;
It works in some computers, in others it goes out of the screen . Do i have to consider the resolution when i use width and height?
I noticed that the problems comes when resolution is over 1920x1080 and or if the text scaling factor is different from 100 .
I tried to add scale factor but it is not correct
Matrix m = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice;
Left = pt2d.X -Widthm.M11;
Top= pt2d.Y -Heightm.M22;
You need to calculate the client coordinates for the view then convert them to screen coordinates before trying to use them as a location and size for your WPF window.
Something like this should get you close, the hard part is translating from Windows screen coordinates to WPF logical units.
using System.Windows;
using Rhino;
using Rhino.Commands;
namespace WpfWindowOverViewPlugIn
{
public class WpfWindowOverViewPlugInCommand : Command
{
public WpfWindowOverViewPlugInCommand()
{
// Rhino only creates one instance of each command class defined in a
// plug-in, so it is safe to store a reference in a static property.
Instance = this;
}
///<summary>The only instance of this command.</summary>
public static WpfWindowOverViewPlugInCommand Instance
{
get; private set;
}
///<returns>The command name as it appears on the Rhino command line.</returns>
public override string EnglishName
{
get { return "WpfWindowOverViewPlugInCommand"; }
}
protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
var view = doc?.Views?.ActiveView;
if (view == null)
return Result.Failure;
var bounds = view.Bounds;
var tl = view.ClientToScreen(bounds.Location);
var br = view.ClientToScreen(new System.Drawing.Point(bounds.Right, bounds.Bottom));
var sr = System.Drawing.Rectangle.FromLTRB(tl.X, tl.Y, br.X, br.Y);
RhinoApp.WriteLine($"Active view bounds: {bounds} screen rectangle:{sr}");
var win = new ViewWindow { WindowStartupLocation = System.Windows.WindowStartupLocation.Manual };
win.Loaded += (s, e) =>
{
var wpftl = RealPixelsToWpf(win, tl);
win.Left = wpftl.X;
win.Top = wpftl.Y;
var wpfbr = RealPixelsToWpf(win, br);
win.Width = wpfbr.X - wpftl.X;
win.Height = wpfbr.Y - wpftl.Y;
};
win.ShowDialog();
return Result.Success;
}
private static Point RealPixelsToWpf(Window w, System.Drawing.Point p)
{
var t = PresentationSource.FromVisual(w).CompositionTarget.TransformFromDevice;
return t.Transform(new Point(p.X, p.Y));
}
}
}
Thank you very much, i tought i calculate the client coordinates here
As i don’t need not the full view but a window with example width 100 and height 100 and its bottom right = rhinoview bottom right,i made some changings to your code but it is not working. Please tell me where is the problem. Yesterday i found a solution that works for me but i would like to undestand how it works
Here your code with changings:
protected override Result RunCommand(RhinoDoc doc,RunMode mode)
{
var view = doc?.Views?.ActiveView;
if(view == null)
return Result.Failure;
var bounds = view.Bounds;
int windowwidth = 100,
windowheight = 100;
var tl = view.ClientToScreen(new System.Drawing.Point(bounds.Right-windowwidth,bounds.Bottom-windowheight));
var win = new Window { WindowStartupLocation = System.Windows.WindowStartupLocation.Manual };
win.Width=windowwidth;
win.Height=windowheight;
win.Loaded += (s,e) =>
{
var wpftl = RealPixelsToWpf(win,tl);
win.Left = wpftl.X;
win.Top = wpftl.Y;
};
win.Show();
return Result.Success;
}
Here my solution
Matrix m = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice;
var punto_3d = new Rhino.Geometry.Point3d(view.Bounds.Width,view.Bounds.Bottom,0);
var pt2d = new System.Drawing.Point((int)punto_3d.X,(int)punto_3d.Y);
pt2d = view.ActiveViewport.ClientToScreen(pt2d);
win.Left= pt2d.X*(1 / m.M11) -Width;
win.Top= pt2d.Y*(1 / m.M22) -Height;
.??