Skip to content

Commit

Permalink
Merge pull request #2639 from cwensley/curtis/wpf-add-logical-to-nati…
Browse files Browse the repository at this point in the history
…ve-screen-conversion

Add WpfHelpers.ToEtoScreen/ToNativeScreen helper methods
  • Loading branch information
cwensley authored Apr 3, 2024
2 parents 5266b08 + 366eea5 commit 210024b
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 79 deletions.
5 changes: 5 additions & 0 deletions src/Eto.Mac/SDConversions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ public static sd.PointF ToSD (this PointF point)
return new sd.PointF (point.X, point.Y);
}

public static sd.Point ToSDPoint (this PointF point)
{
return new sd.Point ((int)point.X, (int)point.Y);
}

internal static sd.PointF[] ToSD (this PointF[] points)
{
var result = new sd.PointF[points.Length];
Expand Down
18 changes: 9 additions & 9 deletions src/Eto.WinForms/Win32.dpi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ public static Eto.Drawing.Point LogicalToScreen(this Eto.Drawing.PointF point, E
{
screen = screen ?? Eto.Forms.Screen.FromPoint(point);
var sdscreen = ScreenHandler.GetControl(screen);
var location = sdscreen.GetLogicalLocation();
var pixelSize = sdscreen.GetLogicalPixelSize(usePerMonitor);
var location = sdscreen.GetBounds().Location;
var screenBounds = screen.Bounds;
var sdscreenBounds = usePerMonitor ? sdscreen.GetBounds() : sdscreen.Bounds.ToEto();

var x = location.X + (point.X - screenBounds.X) * pixelSize;
var y = location.Y + (point.Y - screenBounds.Y) * pixelSize;
var x = sdscreenBounds.X + (point.X - location.X) * pixelSize;
var y = sdscreenBounds.Y + (point.Y - location.Y) * pixelSize;

return Drawing.Point.Round(new Drawing.PointF(x, y));
}
Expand All @@ -76,10 +76,10 @@ public static Eto.Drawing.PointF ScreenToLogical(this Eto.Drawing.Point point, s

public static Eto.Drawing.PointF ScreenToLogical(this sd.Point point, swf.Screen sdscreen = null, bool usePerMonitor = true)
{
sdscreen = sdscreen ?? swf.Screen.FromPoint(point);
sdscreen ??= swf.Screen.FromPoint(point);
var location = sdscreen.GetLogicalLocation();
var pixelSize = sdscreen.GetLogicalPixelSize(usePerMonitor);
var sdscreenBounds = sdscreen.GetBounds();
var sdscreenBounds = usePerMonitor ? sdscreen.GetBounds() : sdscreen.Bounds.ToEto();

var x = location.X + (point.X - sdscreenBounds.X) / pixelSize;
var y = location.Y + (point.Y - sdscreenBounds.Y) / pixelSize;
Expand All @@ -93,10 +93,10 @@ public static Eto.Drawing.RectangleF ScreenToLogical(this Eto.Drawing.Rectangle
sdscreen = sdscreen ?? swf.Screen.FromPoint(rect.Location.ToSD());
var location = sdscreen.GetLogicalLocation();
var pixelSize = sdscreen.GetLogicalPixelSize(usePerMonitor);
var screenBounds = sdscreen.GetBounds();
var sdscreenBounds = usePerMonitor ? sdscreen.GetBounds() : sdscreen.Bounds.ToEto();
return new Eto.Drawing.RectangleF(
location.X + (rect.X - screenBounds.X) / pixelSize,
location.Y + (rect.Y - screenBounds.Y) / pixelSize,
location.X + (rect.X - sdscreenBounds.X) / pixelSize,
location.Y + (rect.Y - sdscreenBounds.Y) / pixelSize,
rect.Width / pixelSize,
rect.Height / pixelSize
);
Expand Down
70 changes: 0 additions & 70 deletions src/Eto.WinForms/WinConversions.shared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,76 +59,6 @@ public static sd.Color ToSD(this Color color)
return sd.Color.FromArgb((byte)(color.A * 255), (byte)(color.R * 255), (byte)(color.G * 255), (byte)(color.B * 255));
}

public static Point ToEto(this sd.Point point)
{
return new Point(point.X, point.Y);
}

public static PointF ToEto(this sd.PointF point)
{
return new PointF(point.X, point.Y);
}

public static sd.PointF ToSD(this PointF point)
{
return new sd.PointF(point.X, point.Y);
}

public static sd.Point ToSDPoint(this PointF point)
{
return new sd.Point((int)point.X, (int)point.Y);
}

public static Size ToEto(this sd.Size size)
{
return new Size(size.Width, size.Height);
}

public static sd.Size ToSD(this Size size)
{
return new sd.Size(size.Width, size.Height);
}

public static Size ToEtoF(this sd.SizeF size)
{
return new Size((int)size.Width, (int)size.Height);
}

public static SizeF ToEto(this sd.SizeF size)
{
return new SizeF(size.Width, size.Height);
}

public static sd.SizeF ToSD(this SizeF size)
{
return new sd.SizeF(size.Width, size.Height);
}

public static Rectangle ToEto(this sd.Rectangle rect)
{
return new Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
}

public static RectangleF ToEto(this sd.RectangleF rect)
{
return new RectangleF(rect.X, rect.Y, rect.Width, rect.Height);
}

public static sd.Rectangle ToSD(this Rectangle rect)
{
return new sd.Rectangle(rect.X, rect.Y, rect.Width, rect.Height);
}

public static sd.RectangleF ToSD(this RectangleF rect)
{
return new sd.RectangleF(rect.X, rect.Y, rect.Width, rect.Height);
}

public static sd.Rectangle ToSDRectangle(this RectangleF rect)
{
return new sd.Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
}

internal static sd.Point[] ToSD(this Point[] points)
{
var result =
Expand Down
28 changes: 28 additions & 0 deletions src/Eto.Wpf/WpfHelpers.cs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,33 @@ public static Window ToEtoWindow(IntPtr windowHandle)
return null;
return new Form(new HwndFormHandler(windowHandle));
}

/// <summary>
/// Converts a System.Drawing.Point in screen coordinates to an Eto point in screen coordinates.
/// </summary>
/// <param name="point">A point in Windows Forms/win32 screen coordinates.</param>
/// <returns>A point in Eto screen coordinates.</returns>
public static PointF ToEtoScreen(this sd.Point point, swf.Screen sdscreen = null, bool perMonitor = false) => Win32.ScreenToLogical(point, sdscreen, perMonitor);

public static RectangleF ToEtoScreen(this sd.Rectangle rect, swf.Screen sdscreen = null, bool perMonitor = false)
{
var topLeft = ToEtoScreen(rect.Location, sdscreen, perMonitor);
var bottomRight = ToEtoScreen(new sd.Point(rect.X + rect.Width, rect.Y + rect.Height), sdscreen, perMonitor);
return new RectangleF(topLeft, new SizeF(bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y));
}

/// <summary>
/// Converts a point in Eto screen coordinates to a point in Windows Forms/win32 screen coordinates.
/// </summary>
/// <param name="point">A point in Eto screen coordinates.</param>
/// <returns>A point in Windows Forms/win32 screen coordinates.</returns>
public static Point ToNativeScreen(this PointF point, Screen screen = null, bool perMonitor = false) => Win32.LogicalToScreen(point, screen, perMonitor);
public static Rectangle ToNativeScreen(this RectangleF rect, Screen screen = null, bool perMonitor = false)
{
var topLeft = rect.TopLeft.ToNativeScreen(screen, perMonitor);
var bottomRight = rect.BottomRight.ToNativeScreen(screen, perMonitor);
return new Rectangle(topLeft, new Size(bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y));
}

}
}
99 changes: 99 additions & 0 deletions test/Eto.Test.Wpf/UnitTests/ScreenToClientTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Eto.Test.UnitTests;
using NUnit.Framework;
using swf = System.Windows.Forms;
using sd = System.Drawing;

namespace Eto.Test.Wpf.UnitTests
{
[TestFixture]
public class ScreenToClientTests : TestBase
{

class NonActivatingForm : swf.Form
{
protected override bool ShowWithoutActivation => true;
}

[Test, ManualTest]
public void ScreenLocationsShouldBeCorrect()
{
var mre = new ManualResetEvent(false);
Invoke(() =>
{
var wfwindows = new List<swf.Form>();
var windows = new List<Window>();
void CreateWindow(Rectangle rect)
{
var window = new Form
{
ShowActivated = false,
ShowInTaskbar = false,
Minimizable = false,
Maximizable = false,
Bounds = rect,
Content = TableLayout.AutoSized("Click to dismiss", centered: true)
};
window.MouseDown += (sender, e) =>
{
foreach (var w in windows)
{
w.Close();
}
foreach (var w in wfwindows)
{
w.Close();
}
mre.Set();
};
window.Show();
windows.Add(window);
bool perMonitor = true;
var sdrect = WpfHelpers.ToNativeScreen(rect, window.Screen, perMonitor: perMonitor).ToSD();
var wfwindow = new NonActivatingForm
{
Bounds = sdrect,
ShowInTaskbar = false,
MinimizeBox = false,
MaximizeBox = false,
StartPosition = swf.FormStartPosition.Manual,
BackColor = sd.Color.Blue
};
wfwindow.Controls.Add(new swf.Label { Text = "Move me", Dock = swf.DockStyle.Fill, ForeColor = sd.Color.White });
wfwindow.LocationChanged += (sender, e) =>
{
var loc = wfwindow.RectangleToScreen(wfwindow.ClientRectangle);
window.Bounds = (Rectangle)WpfHelpers.ToEtoScreen(loc, swf.Screen.FromControl(wfwindow), perMonitor: perMonitor);
};
wfwindow.SizeChanged += (sender, e) =>
{
var loc = wfwindow.RectangleToScreen(wfwindow.ClientRectangle);
window.Bounds = (Rectangle)WpfHelpers.ToEtoScreen(loc, swf.Screen.FromControl(wfwindow), perMonitor: perMonitor);
};
wfwindow.Show();
wfwindows.Add(wfwindow);
}
foreach (var screen in Screen.Screens)
{
var bounds = (Rectangle)screen.WorkingArea;
var size = new Size(200, 200);
CreateWindow(new Rectangle(bounds.TopLeft, size));
CreateWindow(new Rectangle(bounds.TopRight - new Size(size.Width, 0), size));
CreateWindow(new Rectangle(bounds.BottomLeft - new Size(0, size.Height), size));
CreateWindow(new Rectangle(bounds.BottomRight - size, size));
}
});
mre.WaitOne();
}

}
}

0 comments on commit 210024b

Please sign in to comment.