mirror of
https://github.com/terrymacdonald/DisplayMagician.git
synced 2024-08-30 18:32:20 +00:00
37b9a79ff2
Still some bits broken.
299 lines
13 KiB
C#
299 lines
13 KiB
C#
using System;
|
||
using System.Drawing;
|
||
using System.Windows.Forms;
|
||
using DisplayMagicianShared.Windows;
|
||
|
||
namespace DisplayMagicianShared.UserControls
|
||
{
|
||
public partial class DisplayView : UserControl
|
||
{
|
||
private ProfileItem _profile;
|
||
|
||
public DisplayView()
|
||
{
|
||
InitializeComponent();
|
||
ResizeRedraw = true;
|
||
}
|
||
|
||
public int PaddingX { get; set; } = 100;
|
||
public int PaddingY { get; set; } = 100;
|
||
|
||
public ProfileItem Profile
|
||
{
|
||
get => _profile;
|
||
set
|
||
{
|
||
_profile = value;
|
||
Invalidate();
|
||
}
|
||
}
|
||
|
||
protected override void OnPaint(PaintEventArgs e)
|
||
{
|
||
base.OnPaint(e);
|
||
|
||
if (_profile != null)
|
||
{
|
||
DrawView(e.Graphics);
|
||
}
|
||
else
|
||
{
|
||
DrawEmptyView(e.Graphics);
|
||
}
|
||
}
|
||
|
||
private Size DrawString(
|
||
Graphics g,
|
||
string str,
|
||
Color colour,
|
||
Font font,
|
||
SizeF drawingSize = default(SizeF),
|
||
PointF? drawingPoint = null,
|
||
StringAlignment vertical = StringAlignment.Center,
|
||
StringAlignment horizontal = StringAlignment.Center)
|
||
{
|
||
var format = new StringFormat(StringFormat.GenericTypographic)
|
||
{
|
||
Alignment = horizontal,
|
||
LineAlignment = vertical,
|
||
FormatFlags = StringFormatFlags.NoClip
|
||
};
|
||
var stringSize = g.MeasureString(str, Font, drawingSize, format);
|
||
|
||
if (drawingPoint != null)
|
||
{
|
||
g.DrawString(str, font, new SolidBrush(colour), new RectangleF(drawingPoint.Value, drawingSize),
|
||
format);
|
||
}
|
||
|
||
return new Size((int) stringSize.Width, (int) stringSize.Height);
|
||
}
|
||
|
||
public virtual void DrawSpannedTopology(Graphics g, ScreenPosition screen, Rectangle rect)
|
||
{
|
||
g.DrawRectangle(Pens.Black, rect);
|
||
|
||
var targetSize = new Size(rect.Width / screen.SpannedColumns,
|
||
rect.Height / screen.SpannedRows);
|
||
|
||
for (var i = 0; i < screen.SpannedScreens.Count; i++)
|
||
{
|
||
var display = screen.SpannedScreens[i];
|
||
var row = i / screen.SpannedColumns;
|
||
var col = i % screen.SpannedColumns;
|
||
var targetPosition = new Point(targetSize.Width * col + rect.X, targetSize.Height * row + rect.Y);
|
||
var targetRect = new Rectangle(targetPosition, targetSize);
|
||
|
||
g.DrawRectangle(Pens.Black, targetRect);
|
||
|
||
/*switch (display.Rotation)
|
||
{
|
||
case Rotation.Rotate90:
|
||
DrawString(g, "90°", targetRect.Size,
|
||
new PointF(targetRect.X - PaddingX / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
|
||
StringAlignment.Far);
|
||
|
||
break;
|
||
case Rotation.Rotate180:
|
||
DrawString(g, "180°", targetRect.Size,
|
||
new PointF(targetRect.X - PaddingX / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
|
||
StringAlignment.Far);
|
||
|
||
break;
|
||
case Rotation.Rotate270:
|
||
DrawString(g, "270°", targetRect.Size,
|
||
new PointF(targetRect.X - PaddingX / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
|
||
StringAlignment.Far);
|
||
|
||
break;
|
||
}*/
|
||
|
||
/*if (!display.Overlap.IsEmpty)
|
||
{
|
||
DrawString(g, $"[{-display.Overlap.X}, {-display.Overlap.Y}]", targetRect.Size,
|
||
new PointF(targetRect.X + PaddingY / 2, targetRect.Y + PaddingY / 2), StringAlignment.Near,
|
||
StringAlignment.Near);
|
||
}*/
|
||
|
||
// Invert to real monitor resolution
|
||
//var res = ProfileIcon.NormalizeResolution(target.SurroundTopology.Resolution, display.Rotation);
|
||
/*var str = $"{display.DisplayName}{Environment.NewLine}{res.Width}×{res.Height}";
|
||
DrawString(g, str, targetRect.Size, targetRect.Location);*/
|
||
}
|
||
}
|
||
|
||
private void DrawView(Graphics g)
|
||
{
|
||
|
||
var viewSize = ProfileIcon.CalculateViewSize(_profile.Screens, PaddingX, PaddingY);
|
||
var factor = Math.Min(Width / viewSize.Width, Height / viewSize.Height);
|
||
g.ScaleTransform(factor, factor);
|
||
|
||
var xOffset = (Width / factor - viewSize.Width) / 2f;
|
||
var yOffset = (Height / factor - viewSize.Height) / 2f;
|
||
g.TranslateTransform(-viewSize.X + xOffset, -viewSize.Y + yOffset);
|
||
|
||
// How wide the Bezel is on the screen graphics
|
||
int screenBezel = 60;
|
||
int screenWordBuffer = 60;
|
||
|
||
Color lightTextColour = Color.White;
|
||
Color darkTextColour = Color.Black;
|
||
|
||
Font selectedWordFont;
|
||
Font normalWordFont = new Font(Font.FontFamily, 55);
|
||
Font bigWordFont = new Font(Font.FontFamily, 80);
|
||
Font hugeWordFont = new Font(Font.FontFamily, 110);
|
||
|
||
|
||
// Figure out the sized font we need
|
||
if (g.VisibleClipBounds.Width > 10000 || g.VisibleClipBounds.Height > 4000)
|
||
{
|
||
selectedWordFont = hugeWordFont;
|
||
}
|
||
else if (g.VisibleClipBounds.Width > 6000 || g.VisibleClipBounds.Height > 3500)
|
||
{
|
||
selectedWordFont = bigWordFont;
|
||
}
|
||
else
|
||
{
|
||
selectedWordFont = normalWordFont;
|
||
}
|
||
|
||
foreach (ScreenPosition screen in _profile.Screens)
|
||
{
|
||
|
||
Rectangle screenRect;
|
||
Rectangle outlineRect;
|
||
|
||
// draw the screen
|
||
if (screen.IsSpanned)
|
||
{
|
||
// We do these things only if the screen IS spanned!
|
||
// Draw the outline of the spanned monitor
|
||
outlineRect = new Rectangle(screen.ScreenX, screen.ScreenY, screen.ScreenWidth, screen.ScreenHeight);
|
||
g.FillRectangle(new SolidBrush(Color.FromArgb(255, 33, 33, 33)), outlineRect);
|
||
g.DrawRectangle(Pens.Black, outlineRect);
|
||
|
||
// Draw the screen of the monitor
|
||
screenRect = new Rectangle(screen.ScreenX + screenBezel, screen.ScreenY + screenBezel, screen.ScreenWidth - (screenBezel * 2), screen.ScreenHeight - (screenBezel * 2));
|
||
g.FillRectangle(new SolidBrush(screen.Colour), screenRect);
|
||
g.DrawRectangle(Pens.Black, screenRect);
|
||
|
||
// Temporarily disabling this dotted line as it really isn't great visually.
|
||
/*foreach (SpannedScreenPosition subScreen in screen.SpannedScreens)
|
||
{
|
||
Rectangle spannedScreenRect = new Rectangle(subScreen.ScreenX, subScreen.ScreenY, subScreen.ScreenWidth, subScreen.ScreenHeight);
|
||
Pen dashedLine = new Pen(Color.Black);
|
||
dashedLine.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDotDot;
|
||
g.DrawRectangle(dashedLine, spannedScreenRect);
|
||
}*/
|
||
|
||
}
|
||
else
|
||
{
|
||
// We do these things only if the screen isn't spanned!
|
||
// Draw the outline of the monitor
|
||
outlineRect = new Rectangle(screen.ScreenX, screen.ScreenY, screen.ScreenWidth, screen.ScreenHeight);
|
||
g.FillRectangle(new SolidBrush(Color.FromArgb(255, 33, 33, 33)), outlineRect);
|
||
g.DrawRectangle(Pens.Black, outlineRect);
|
||
|
||
// Draw the screen of the monitor
|
||
screenRect = new Rectangle(screen.ScreenX + screenBezel, screen.ScreenY + screenBezel, screen.ScreenWidth - (screenBezel * 2), screen.ScreenHeight - (screenBezel * 2));
|
||
g.FillRectangle(new SolidBrush(screen.Colour), screenRect);
|
||
g.DrawRectangle(Pens.Black, screenRect);
|
||
}
|
||
|
||
// Draw the location of the taskbar for this screen
|
||
Rectangle taskBarRect;
|
||
Rectangle startButtonRect;
|
||
int taskBarWidth = (int)(0.05 * screenRect.Height);
|
||
int startButtonSpacer = (int)(0.25 * taskBarWidth);
|
||
int startButtonSize = 2 * startButtonSpacer;
|
||
switch (screen.TaskBarEdge)
|
||
{
|
||
case TaskBarLayout.TaskBarEdge.Left:
|
||
taskBarRect = new Rectangle(screenRect.X, screenRect.Y + 2, taskBarWidth, screenRect.Height - 4);
|
||
startButtonRect = new Rectangle(taskBarRect.X + startButtonSpacer, taskBarRect.Y + startButtonSpacer, startButtonSize, startButtonSize);
|
||
break;
|
||
case TaskBarLayout.TaskBarEdge.Top:
|
||
taskBarRect = new Rectangle(screenRect.X + 2, screenRect.Y, screenRect.Width - 4, taskBarWidth);
|
||
startButtonRect = new Rectangle(taskBarRect.X + startButtonSpacer, taskBarRect.Y + startButtonSpacer, startButtonSize, startButtonSize);
|
||
break;
|
||
case TaskBarLayout.TaskBarEdge.Right:
|
||
taskBarRect = new Rectangle(screenRect.X + screenRect.Width - taskBarWidth, screenRect.Y + 2, taskBarWidth, screenRect.Height - 4);
|
||
startButtonRect = new Rectangle(taskBarRect.X + startButtonSpacer, taskBarRect.Y + startButtonSpacer, startButtonSize, startButtonSize);
|
||
break;
|
||
case TaskBarLayout.TaskBarEdge.Bottom:
|
||
taskBarRect = new Rectangle(screenRect.X + 2, screenRect.Y + screenRect.Height - taskBarWidth, screenRect.Width - 4, taskBarWidth);
|
||
startButtonRect = new Rectangle(taskBarRect.X + startButtonSpacer, taskBarRect.Y + startButtonSpacer, startButtonSize, startButtonSize);
|
||
break;
|
||
default:
|
||
taskBarRect = new Rectangle(screenRect.X + 2, screenRect.Y + screenRect.Height - taskBarWidth, screenRect.Width - 4, taskBarWidth);
|
||
startButtonRect = new Rectangle(taskBarRect.X + startButtonSpacer, taskBarRect.Y + startButtonSpacer, startButtonSize, startButtonSize);
|
||
break;
|
||
}
|
||
g.FillRectangle(new SolidBrush(Color.FromArgb(255, 200, 200, 200)), taskBarRect);
|
||
g.FillRectangle(new SolidBrush(Color.FromArgb(255, 3, 194, 252)), startButtonRect);
|
||
//g.DrawRectangle(Pens.Black, outlineRect);
|
||
|
||
Rectangle wordRect = new Rectangle(screen.ScreenX + screenBezel + screenWordBuffer, screen.ScreenY + screenBezel + screenWordBuffer, screen.ScreenWidth - (screenBezel * 2) - (screenWordBuffer * 2), screen.ScreenHeight - (screenBezel * 2) - (screenWordBuffer * 2));
|
||
Color wordTextColour = pickTextColorBasedOnBgColour(screen.Colour, lightTextColour, darkTextColour);
|
||
// Draw the name of the screen and the size of it
|
||
string str = $"{screen.Name}{Environment.NewLine}";
|
||
str += $"{screen.ScreenWidth}×{ screen.ScreenHeight}{ Environment.NewLine}{ screen.DisplayConnector}";
|
||
if (screen.IsPrimary)
|
||
{
|
||
str = $"Primary Display{Environment.NewLine}" + str;
|
||
}
|
||
if (screen.IsClone)
|
||
{
|
||
str += $"(+{screen.ClonedCopies-1} Clone)";
|
||
}
|
||
if (!String.IsNullOrEmpty(screen.AdapterName))
|
||
{
|
||
str += $"Adapter {screen.AdapterName}{Environment.NewLine}";
|
||
}
|
||
|
||
|
||
DrawString(g, str, wordTextColour, selectedWordFont, wordRect.Size, wordRect.Location);
|
||
|
||
// Draw the position of the screen
|
||
str = $"[{screen.ScreenX},{screen.ScreenY}]";
|
||
DrawString(g, str, wordTextColour, selectedWordFont, wordRect.Size, wordRect.Location, StringAlignment.Near, StringAlignment.Near);
|
||
}
|
||
}
|
||
|
||
|
||
private Color pickTextColorBasedOnBgColour(Color bgColour, Color lightColour, Color darkColour)
|
||
{
|
||
if ((bgColour.R * 0.299 + bgColour.G * 0.587 + bgColour.B * 0.114) > 186)
|
||
{
|
||
return darkColour;
|
||
}
|
||
else
|
||
{
|
||
return lightColour;
|
||
}
|
||
}
|
||
|
||
private Bitmap pickBitmapBasedOnBgColour(Color bgColour, Bitmap lightBitmap, Bitmap darkBitmap)
|
||
{
|
||
if ((bgColour.R * 0.299 + bgColour.G * 0.587 + bgColour.B * 0.114) > 186)
|
||
{
|
||
return darkBitmap;
|
||
}
|
||
else
|
||
{
|
||
return lightBitmap;
|
||
}
|
||
}
|
||
|
||
private void DrawEmptyView(Graphics g)
|
||
{
|
||
RectangleF rect = g.VisibleClipBounds;
|
||
g.FillRectangle(new SolidBrush(Color.FromArgb(15, Color.White)), rect);
|
||
g.DrawRectangle(Pens.Black, rect.X, rect.Y, rect.Width, rect.Height);
|
||
}
|
||
}
|
||
} |