using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Linq; using System.Windows.Forms; using CursorGuardRail.Dtos; using RyzStudio.Drawing; namespace CursorGuardRail.Windows.Forms { public class ScreensLayout : RyzStudio.Windows.ThemedForms.T3UserControl { private readonly Pen screenBorderColour = new Pen(Color.Black, 2f); private readonly Brush screenBackColour = new SolidBrush(Color.FromArgb(218, 218, 218)); private readonly Brush selectedScreenBackColour = new SolidBrush(Color.FromArgb(0, 120, 215)); private readonly Pen selectedAreaBorderColour = new Pen(Color.FromArgb(254, 135, 0), 2f) { DashStyle = System.Drawing.Drawing2D.DashStyle.Dot }; public ScreensLayout() { this.Font = new Font(this.Font.FontFamily, 20f, FontStyle.Regular); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); var g = e.Graphics; for (var i=0; i x.IsSelected)) { var area = CalcMaxBound(this.Screens.Where(x => x.IsSelected).Select(x => x.Bound).ToList()); g.DrawRectangle(selectedAreaBorderColour, area); } } g.Flush(); } protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (e.Button == MouseButtons.Left) { for (var i = 0; i < this.Screens.Count; i++) { if (this.Screens[i].Bound.Contains(e.Location)) { this.Screens[i].IsSelected = !this.Screens[i].IsSelected; break; } } } } protected override void OnResize(EventArgs e) { base.OnResize(e); this.InvalidateScreens(); } protected override void UpdateBackground() { if (base.ClientRectangle.Width <= 0 || base.ClientRectangle.Height <= 0) { return; } var backColour = Color.FromArgb(242, 242, 242); var backgroundImage = new Rectangoid(base.ClientRectangle, CurrentStyle.Border.Radius, CurrentStyle.Border.Width).ToBitmap(new Pen(new SolidBrush(CurrentStyle.Border.Colour), CurrentStyle.Border.Width), new SolidBrush(backColour)); this.BackgroundImage = backgroundImage; } public void InvalidateScreens() { var virtualDesktop = SystemInformation.VirtualScreen; var offsetX = (virtualDesktop.X <= 0 ? -virtualDesktop.X : 0); this.Screens.Clear(); foreach (var screen in Screen.AllScreens) { var bound = screen.Bounds; bound.Offset(offsetX, 0); var newBound = new RectangleF(bound.X, bound.Y, bound.Width, bound.Height); newBound = newBound.ScaleDown(ScaleRatio); this.Screens.Add(new ScreenItem() { Bound = newBound, IsPrimary = screen.Primary, IsSelected = false }); } CenterRectangles(this.Screens); this.Invalidate(); } private int ActualWidth { get => this.ClientSize.Width - this.Padding.Horizontal; } private int ActualHeight { get => this.ClientSize.Height - this.Padding.Vertical; } public List Screens { get { if (field == null) field = new List(); return field; } private set { field = value; } } [Browsable(false), EditorBrowsable(EditorBrowsableState.Always), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool ShowArea { get => field; set { field = value; this.Invalidate(); } } = false; private decimal ScaleRatio { get { var virtualScreen = SystemInformation.VirtualScreen; var widthRatio = decimal.Divide(virtualScreen.Width, ActualWidth); var heightRatio = decimal.Divide(virtualScreen.Height, ActualHeight); return Math.Max(widthRatio, heightRatio); } } private PointF CalcCentreOffset(List rectangles) { if (rectangles.Count <= 0) { return PointF.Empty; } // Find the bounds var left = rectangles.Min(r => r.Left); var top = rectangles.Min(r => r.Top); var right = rectangles.Max(r => r.Right); var bottom = rectangles.Max(r => r.Bottom); var bounds = RectangleF.FromLTRB(left, top, right, bottom); // Calculate offset var offsetX = this.Padding.Left + (ActualWidth - bounds.Width) / 2 - bounds.Left; var offsetY = this.Padding.Top + (ActualHeight - bounds.Height) / 2 - bounds.Top; return new PointF(offsetX, offsetY); } private void CenterRectangles(List screen) { var offset = CalcCentreOffset(screen.Select(x => x.Bound).ToList()); for (var i=0; i bounds) { RectangleF? rect = null; for (var i = 0; i < bounds.Count; i++) { if (rect == null) { rect = bounds[i]; } else { rect = RectangleF.Union(bounds[i], rect.Value); } } return rect ?? Rectangle.Empty; } } }